MST

星途 面试题库

面试题:分布式系统中基于分布式锁实现分布式事务,简述常见的分布式锁实现方式及各自优缺点

在分布式系统里,为实现分布式事务常借助分布式锁。请简要阐述如基于数据库、Redis、Zookeeper实现分布式锁的方式,并分析它们各自的优点和缺点。
35.5万 热度难度
后端开发分布式系统

知识考点

AI 面试

面试题答案

一键面试

基于数据库实现分布式锁

  1. 实现方式
    • 基于表记录:创建一张锁表,表中至少包含锁的标识字段(如业务唯一标识)和锁状态字段。当需要获取锁时,向表中插入一条记录,插入成功则获取锁,失败则说明锁已被占用。释放锁时,删除对应的记录。
    • 基于排他锁:使用数据库的排他锁(如MySQL的SELECT... FOR UPDATE语句),对特定的记录加锁。当事务执行SELECT... FOR UPDATE时,如果记录未被其他事务锁定,则当前事务获取锁,否则等待锁释放。
  2. 优点
    • 实现简单:对于熟悉数据库操作的开发者,基于数据库实现分布式锁的逻辑相对易懂。
    • 可靠性较高:数据库本身有持久化机制,数据不会因进程重启等原因丢失,锁的状态相对稳定。
  3. 缺点
    • 性能问题:数据库的读写性能通常不如内存型存储,频繁的锁操作会导致数据库压力增大,影响系统整体性能。
    • 锁的粒度问题:基于表记录方式锁粒度较粗,如果业务需要更细粒度的锁,实现起来比较复杂。基于排他锁方式虽然可以实现较细粒度锁,但会增加数据库事务管理的复杂度。
    • 单点故障:如果数据库出现故障,整个分布式锁服务将不可用。

基于Redis实现分布式锁

  1. 实现方式
    • SETNX命令:使用Redis的SETNX(SET if Not eXists)命令,当键不存在时,设置键的值。如果设置成功,表示获取到锁;设置失败,则说明锁已被其他客户端持有。释放锁时,使用DEL命令删除对应的键。
    • Redisson框架:Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它提供了更高级的分布式锁实现,支持公平锁、可重入锁等多种特性。例如,使用Redisson获取锁时,它会在后台自动续约锁的有效期,防止因业务执行时间过长导致锁自动释放。
  2. 优点
    • 性能高:Redis是内存型数据库,读写速度非常快,适合高并发场景下的锁操作。
    • 灵活性好:可以通过设置不同的键值对,轻松实现不同粒度的锁,并且可以方便地设置锁的过期时间,防止死锁。
  3. 缺点
    • 可靠性问题:如果Redis采用单节点部署,存在单点故障问题。虽然可以通过主从复制、哨兵模式或集群模式提高可靠性,但在某些情况下(如主从切换期间),可能会出现锁的误判(例如,客户端A在主节点获取了锁,还未同步到从节点,主节点故障,从节点升级为主节点,客户端B又获取到了相同的锁)。
    • 锁的续期问题:对于一些需要长时间持有锁的业务,如果使用简单的SETNX + DEL方式,需要手动处理锁的续期逻辑,否则可能因业务执行时间过长导致锁提前释放。

基于Zookeeper实现分布式锁

  1. 实现方式
    • 临时顺序节点:Zookeeper客户端在指定的锁目录下创建一个临时顺序节点。然后获取该目录下所有的子节点,并判断自己创建的节点是否是序号最小的节点。如果是,则获取到锁;否则,监听比自己序号小的前一个节点的删除事件。当前一个节点释放锁(即被删除)时,Zookeeper会通知等待的客户端,客户端再次判断自己是否是序号最小的节点,若是则获取锁。释放锁时,删除自己创建的临时节点。
  2. 优点
    • 可靠性高:Zookeeper采用的是分布式集群架构,通过多个节点的数据冗余和一致性协议(如ZAB协议)保证数据的一致性和可靠性,即使部分节点故障,也不影响整个集群的正常运行,从而保证锁服务的可靠性。
    • 天然支持公平锁:由于是基于顺序节点实现,先创建节点的客户端先获取锁,天然支持公平锁机制,避免了某些客户端长时间获取不到锁的情况。
  3. 缺点
    • 性能问题:Zookeeper主要用于协调服务,其写性能相对较低,因为每次写操作都需要通过ZAB协议进行数据同步,在高并发场景下,可能成为性能瓶颈。
    • 实现复杂:相比基于Redis和数据库实现分布式锁,基于Zookeeper实现分布式锁的逻辑较为复杂,需要处理节点的创建、监听、删除等多种操作。