我们在设计分布式锁需要考虑的问题
- 互斥性
- 可重入性
- 锁超时
- 高效的获取锁
- 阻塞/非阻塞
- 公平/非公平
分布式锁的实现
db实现
- 缺点
- 性能瓶颈在数据库,不方便拓展
- 需要自己实现超时、事务
- 优点 实现比较简单
- 互斥性:当然可以保证
- 可重入性:在db维护机器信息和线程名,可以实现重入
- 超时:需要自行实现,获取锁时加一个超时时间
- 阻塞:用while(true)实现即可
- 公平:是非公平锁,即在锁资源释放时,需要竞争
zk实现
实现原理
- 每个请求到zk时,会创建一个临时节点
- zk会负责维护这些临时节点的顺序
- 客户端获取节点后,比较节点的顺序是否是当前第一个:
- 如果是,说明获取到锁。
- 如果不是,建立一个监听器,监听第一个节点
- 当第一个节点被释放后,其余客户端会收到监听消息,可以获取锁。
缺点
- 需要维护一套zk
- 据说性能与mysql差别不大
优点
- 有现成的实现
- 支持锁超时
- 支持读写锁
- 是公平锁
redis
实现简单,大部分分布式锁是用redis实现
- 简单实现 setNx+expire,setNx表示当不存在值时,可以插入,expire实现过期时间。 不过这样做,两次操作不是原子操作。
- jedis或redisson
- 使用lual脚本,实现原子操作
- 需要将value放入,这样释放锁的时候,才知道释放的是自己的锁。
- 可能存在的问题
-
gc的stw
-
时钟发生跳跃
-
长时间的IO
-