分布式锁的这三种实现90%的人都不知道( 四 )


分布式锁的这三种实现90%的人都不知道文章插图
2.任务执行过程中 , 客户端崩溃
获得锁的Client1在任务执行过程中 , 如果Duang的一声崩溃 , 则会断开与Zookeeper服务端的链接 。 根据临时节点的特性 , 相关联的节点Lock1会随之自动删除 。
分布式锁的这三种实现90%的人都不知道文章插图
由于Client2一直监听着Lock1的存在状态 , 当Lock1节点被删除 , Client2会立刻收到通知 。 这时候Client2会再次查询ParentLock下面的所有节点 , 确认自己创建的节点Lock2是不是目前最小的节点 。 如果是最小 , 则Client2顺理成章获得了锁 。
分布式锁的这三种实现90%的人都不知道文章插图
同理 , 如果Client2也因为任务完成或者节点崩溃而删除了节点Lock2 , 那么Client3就会接到通知 。
分布式锁的这三种实现90%的人都不知道文章插图
最终 , Client3成功得到了锁 。
方案:
可以直接使用zookeeper第三方库Curator客户端 , 这个客户端中封装了一个可重入的锁服务 。
分布式锁的这三种实现90%的人都不知道文章插图
Curator提供的InterProcessMutex是分布式锁的实现 。 acquire方法用户获取锁 , release方法用于释放锁 。
缺点:
性能上可能并没有缓存服务那么高 。 因为每次在创建锁和释放锁的过程中 , 都要动态创建、销毁瞬时节点来实现锁功能 。 ZK中创建和删除节点只能通过Leader服务器来执行 , 然后将数据同不到所有的Follower机器上 。
其实 , 使用Zookeeper也有可能带来并发问题 , 只是并不常见而已 。 考虑这样的情况 , 由于网络抖动 , 客户端可ZK集群的session连接断了 , 那么zk以为客户端挂了 , 就会删除临时节点 , 这时候其他客户端就可以获取到分布式锁了 。 就可能产生并发问题 。 这个问题不常见是因为zk有重试机制 , 一旦zk集群检测不到客户端的心跳 , 就会重试 , Curator客户端支持多种重试策略 。 多次重试之后还不行的话才会删除临时节点 。 (所以 , 选择一个合适的重试策略也比较重要 , 要在锁的粒度和并发之间找一个平衡 。 )
4.总结下面的表格总结了Zookeeper和Redis分布式锁的优缺点:
分布式锁的这三种实现90%的人都不知道文章插图
三种方案的比较 上面几种方式 , 哪种方式都无法做到完美 。 就像CAP一样 , 在复杂性、可靠性、性能等方面无法同时满足 , 所以 , 根据不同的应用场景选择最适合自己的才是王道 。
从理解的难易程度角度(从低到高)
数据库 > 缓存 > Zookeeper
从实现的复杂性角度(从低到高)
Zookeeper >= 缓存 > 数据库
从性能角度(从高到低)
缓存 > Zookeeper >= 数据库
从可靠性角度(从高到低)
Zookeeper > 缓存 > 数据库
来源:


推荐阅读