我们都知道在微服务架构中,微服务之间要保持单线程运行一段代码只能用到分布式锁,下面这个文章介绍了几种实现分布式锁的方案,并对比了每种方案的优势和劣势:
需要注意的是,这篇文章中提到了公平锁的概念,在上面这个文章的方案中zookeeper和etcd这两个是天然的公平锁方案,目前来看是值得推荐和考虑的。如果一个分布式锁不是公平锁,会导致先申请锁的线程,可能后获取到锁,例如下面的例子:
- 线程A获取到锁,开始执行单线程业务代码。
- 线程B申请获取锁,由于线程A获取到了锁,所以线程B一直进入一个循环,直到获取到锁。
- 线程C申请获取锁(线程C晚于线程B),由于线程A获取到了锁,所以线程C也一直进入一个循环,直到获取到锁。
- 线程A执行完业务代码,释放锁。
- 由于没有一个机制来判定线程B和线程C,谁先该获取到锁,所以有可能线程C比线程B先抢到了锁,线程C开始执行单线程业务代码,线程B继续循环,直到获取到锁。
从上面这个过程可以看到明明线程B先于线程C申请获取锁,但是线程C却比线程B先获取到锁,这就是因为没有一个机制(队列)来判定线程B和线程C谁先申请的锁。这样在高并发量申请锁的情况下,可能会有个别线程会一直获取不到锁,一直等待。
对于公平锁的问题,在Java中可以使用Redis结合Redisson来实现分布式公平锁:Redisson分布式锁之公平锁原理
然而在C#中要实现分布式公平锁:
- 目前要么只有用数据库锁,依赖数据库事务排队来实现公平锁。
- 要么使用C#结合zookeeper来实现分布式公平锁:Zookeeper基础教程(五):C#实现Zookeeper分布式锁。
- 使用DistributedLock结合zookeeper来实现分布式公平锁,详情参见GitHub文档。
- 如果后续有更好的方案再补充。