分布式锁实现方案对比:MySQL vs Redis vs Zookeeper

Executive Summary

核心观点(金字塔原理)

结论先行: 分布式锁是解决分布式环境下资源竞争问题的核心手段,MySQL、Redis、Zookeeper三种方案各有优劣,需根据业务场景选择

支撑论点:

  1. MySQL方案实现简单但性能较低,适合低频场景
  2. Redis方案性能最优,Redisson可解决主从同步问题,适合高并发场景
  3. Zookeeper方案可靠性高,但存在网络分区时的并发问题

SWOT 分析

维度 分析
S 优势 MySQL简单易实现;Redis性能高;ZK可靠性强、支持Watch机制避免羊群效应
W 劣势 MySQL服务重启锁无法释放;Redis主从同步问题;ZK网络分区可能多客户端获锁
O 机会 资源竞争控制、分布式事务协调、限流控制
T 威胁 死锁风险、锁超时设置不当、网络分区导致一致性问题

适用场景

  • 低频资源竞争场景(MySQL乐观锁/悲观锁)
  • 高并发分布式锁场景(Redis + Redisson)
  • 强一致性要求的协调场景(Zookeeper)

问题

  • 资源竞争

场景

  • 锁(Lock)是并发编程中用于控制多个线程/进程对共享资源访问的同步机制,同一时刻只允许持有锁的一方操作资源
  • 锁需要保证三个核心特性:互斥性(Mutual Exclusion,同一时刻只有一个持有者)、可见性(Visibility,锁释放后其他线程能看到最新状态)、原子性(Atomicity,加锁与释放是不可分割的操作)
  • 锁粒度的选择直接影响系统性能:粗粒度锁(Coarse-grained Lock)实现简单但并发度低,容易成为瓶颈;细粒度锁(Fine-grained Lock)并发度高但实现复杂,需注意死锁风险
  • 根据竞争范围可分为单机锁(JVM内)和分布式锁(跨进程/跨机器),两者解决思路不同

    JVM内竞争

  • synchronized关键字:基于Object Monitor(对象监视器)实现,JVM内置支持,可修饰方法或代码块;JDK 1.6后引入偏向锁、轻量级锁、重量级锁的锁升级优化
  • ReentrantLock:基于AQS(AbstractQueuedSynchronizer)实现,相比synchronized优势明显——支持公平锁/非公平锁切换、tryLock超时获取可中断等待(lockInterruptibly),灵活性更高
  • ReadWriteLock:适用于读多写少场景,允许多个线程同时持有读锁(共享锁),写锁(排他锁)与读锁互斥,显著提升读密集型业务的并发性能
  • volatile关键字:保证变量的可见性有序性(禁止指令重排序),但不保证原子性,适用于状态标志位等简单场景
  • CAS(Compare-And-Swap)与Atomic类:基于CPU指令的无锁(Lock-Free)方案,AtomicInteger、AtomicLong、AtomicReference等原子类通过CAS + 自旋实现线程安全,避免上下文切换开销,适合低竞争场景

分布式环境竞争

解决方案

DB:mysql
  • 设置唯一主键,insert拿到锁,用完删除。注意唯一性,比如a线程上锁,需要a线程删锁
  • 乐观锁,update table set version = xxx where version = xx
  • 可能存在问题:
    • 一旦上锁后,服务重启,则无法释放锁了,其他线程无法释放
      • 解决方案:定时任务处理清除超时一定时间的数据
    • 锁非阻塞的:insert失败没有排队队列,需要重新触发重新获取锁
      • 客户端处理
    • 锁为非重入锁
      • 建表时,增加进入次数字段
Redis
  • 非重入:set lockKey randomValue NX PX 5000
  • 重入:可以基于hash实现可重入锁,key对应的value增加count属性,每次重入+1,释放-1
  • 优点:
    • redis速度快
    • Redission处理多节点加锁问题,处理主从数据同步问题
Zookeeper
  • 序号小的获取到锁资源,watch前一个节点,避免”羊群效应”
  • 优点
    • 内存中,性能高于DB
  • 缺点:
    • 并发问题:ZK集群网络分区,会出现多个client同时获取到锁的情况