专栏名称: 聊聊架构
聊聊架构
目录
相关文章推荐
51好读  ›  专栏  ›  聊聊架构

如何实现靠谱的分布式锁?

聊聊架构  · 公众号  · 架构  · 2018-08-25 13:10

正文

请到「今天看啥」查看全文


注:ZAB 一致性协议保证了锁数据的安全性,不会因为数据丢失造成多个锁持有者;心跳保活机制解决死锁问题,防止由于进程挂掉或者僵死导致的锁长时间被无效占用。具备阻塞锁特性,并通过 Watch 机制能够及时从阻塞状态被唤醒。

解锁流程是 删除当前线程创建的临时接点。

该方案的问题在于通过心跳保活机制解决死锁会造成锁的不安全性,可能会出现如下场景:

持有锁的线程 A 僵死或网络故障,导致服务端长时间收不到来自客户端的保活心跳,服务端认为客户端进程不存活主动释放锁,线程 B 抢到锁,线程 A 恢复,同时有两个线程访问共享资源。

基于上诉对现有锁方案的讨论,我们能看到,一个理想的锁设计目标主要应该解决如下问题:

  1. 锁数据本身的安全性。

  2. 不发生死锁。

  3. 不会有多个线程同时持有相同的锁。

而为了实现不发生死锁的目标,又需要引入一种机制,当持有锁的进程因为宕机、GC 活者网络故障等各种原因无法主动过释放锁时,能够有其他手段释放掉锁,主流的做法有两种:

  1. 锁设置过期时间,过期之后 Server 端自动释放锁。

  2. 对锁的持有进程进行探活,发现持锁进程不存活时 Server 端自动释放。

实际上不管采用哪种方式,都可能造成锁的安全性被破坏,导致多个线程同时持有同一把锁的情况出现。因此我们认为锁设计方案应在预防死锁和锁的安全性上取得平衡,没有一种方案能够绝对意义上保证不发生死锁并且是安全的。

而锁一般的用途又可以分为两种,实际应用场景下,需要根据具体需求出发,权衡各种因素,选择合适的锁服务实现模型。无论选择哪一种模型,需要我们清楚地知道它在安全性上有哪些不足,以及它会带来什么后果。

  1. 为了效率,主要是避免一件事被重复的做多次,用于节省 IT 成本,即使锁偶然失效,也不会造成数据错误,该种情况首要考虑的是如何防止死锁。

  2. 为了正确性,在任何情况下都要保证共享资源的互斥访问,一旦发生就意味着数据可能不一致,造成严重的后果,该种情况首要考虑的是如何保证锁的安全。

下面主要介绍一下 SharkLock 的一些设计选择。

锁信息设计如下

  • lockBy:Client 唯一标识。

  • condition:Client 在加锁时传给 Server,用于定义 Client 期望 Server 的行为方式。

  • lockTime:加锁时间。

  • txID:全局自增 ID。

  • lease:租约。

如何保证锁数据的可靠性






请到「今天看啥」查看全文