请问各位,我想去学习分布式锁、分布式事务这些,有有好的书籍推荐么?


勿忘初心提问于 2019-01-03 14:33
1 个回答
  • 未来已来2019-01-03 14:35


    分布式锁需要满足如下特性:


    • 互斥。这是锁服务的基本能力,多个节点下必须确保同一时刻只有一个节点能获得锁。
    • 避免死锁。死锁在分布式环境下很容易出现,比如某个节点得到锁之后,因为节点故障宕机,或者节点和锁服务之间网络故障,都会造成锁没有机会释放的情况。因为锁未释放,所以其他节点也就无法再获得锁提供正常服务,从而使得整个系统处于死锁状态。分布式锁服务要做的是从锁本身出发,规避死锁。一般可以通过对锁加自动过期时间解决。
    • 高性能。因为锁服务是用来协调分布式系统中各节点的,所以很容易形成系统性能瓶颈和单点故障。性能也是分布式锁服务是否适合生产环境的重要考虑因素。
    • 可重入性。如果同一个节点可以重复获取一个已经获取到的锁,这种锁一般称为可重入锁。根据业务场景,我们可以按需求设计锁服务是否支持重入性。
     


    分布式锁实现模型


    如上图是抽象的分布式锁实现模型,共享存储负责锁和对应客户端信息的存储。客户端1发起acquire()调用后,共享存储返回获取锁成功,当客户端2再发起对同一个锁的acquire()调用时,共享存储会返回获取锁失败。


    以秒杀场景为例,常见的分布式锁服务的实现包括基于数据库、基于Redis、基于ZooKeeper三种。每种方案都有在可靠性、可用性、易用性等方面的优缺点。如何根据业务场景选型,需要技术人员分析并验证。


    • 基于数据库


    利用关系数据库支持数据的ACID强一致性和基于复制的高可用性,为系统中的竞争资源设计一张lock表。这张表用一列表示资源ID,表示正在尝试分配的资源,这一列用UNIQUE KEY约束,通过数据库保证这个资源ID不会被尝试分配多次,以此来提供锁能力,保证客户端互斥执行。


    当客户端A尝试拍下宠物时,先将这只宠物ID加入到lock表,然后再进行剩余的支付操作,等支付成功后,将lock表中记录删除。如果在记录删除之前,有客户端B尝试拍下这只宠物,因为得不到锁,所以会返回给客户端B一个失败提醒。


    优点:拥有较高的可靠性和稳定性。


    缺点:性能会差些,并且会存在死锁问题。


    • 基于Redis缓存


    Redis提供SET NX EX原子操作,它的语义是:当KEY不存在时,SET NX返回成功,并且设置这个KEY的过期时间;当KEY已存在时,SET NX返回失败。


    我们可以构造一个以包含宠物ID的KEY,当客户端A执行SET {PET_ID} {VALUE} NX EX {EXPIRE_TIME}时,Redis返回成功。
    在客户端A释放这个KEY之前,如果客户端B也执行SET NX指令,那么Redis会返回失败。


    优势:有更高的性能和更低的延时,同时Redis原生支持的KEY过期机制,使得死锁问题很容易规避。


    缺点:相比基于数据库的方案,Redis的高可用是异步复制的,这会在极端情况下出现KEY信息未及时同步宕机而导致锁丢失的情况。


    • 基于ZooKeeper


    ZooKeeper天生就是提供分布式协调服务的,非常适合用来实现分布式锁服务。有以下几个原因:

    • ZooKeeper实现了Paxos一致性协议,从协议层面支持多节点的数据一致性问题,能容忍网络分区。
    • ZooKeeper的临时节点支持客户端断连后自动删除。这个特性可以用来保证客户端异常后锁自动释放,规避死锁问题。
    • ZooKeeper支持Watcher机制。当锁被删除或者释放之后,其他客户端可以实时收到通知。

    我们用一个包含了宠物ID信息的znode/path-to-lock/{pet-id}表示锁。多个客户端节点同时请求这个节点,只有一个节点能返回成功,其余返回失败。如果未抢到锁的客户端关心锁释放问题,可以同时注册一个Watcher事件,等待ZooKeeper的通知。


    卖一下我厂架构师编著的《云原生应用架构实践》,以上内容出自该书,有删节。除了分布式锁的内容,书中也包含分布式事务的几种方案,但本身是解释互联网架构的纲要,即从单体架构到面向云计算的分布式服务化架构的演进。云计算是互联网业务的标配,如有整体了解对应的架构演进的需求,建议阅读。