分布式锁需要遵循的准则
- 可重入(同一线程可重复获得锁)
- 加锁解锁时的高可用,例如(一个(模块)宕掉,一直不释放锁)
- 公平锁 先来先得
- 希望该锁是阻塞的,没获得锁时,一直阻塞
数据库
缺点
- 单点
- 不可重入
- 非阻塞
- 不高可用(释放所)
可解决
两个数据库 同步
可重入 在表中加入字段主机信息和线程信息,下次加锁时,查看是不是当前锁的拥有者
高可用 设置锁的过期时间
阻塞 while循环 insert成功后跳出
redis
利用setNx方法(不存在则设置)
缺点
- 单点
- 不可重入
- 非公平
- 非阻塞
- 无过期时间
以上问题均可解决
但是redis的同步策略不是强一致性的,在并发条件下会导致节点锁的状态信息不一致。
zookeeper
可以很好的解决上述问题
- 可重入
把客户端主机信息 线程信息写入节点 - 高可用
zk检测到客户端断开后自动删除节点 - 公平性
zk创建节点是有序的,每次通知最小节点获取锁 - 弱一致性(最终一致性)
脑裂问题:https://blog.csdn.net/varyall/article/details/80150660