分布式锁:Redisson、Zookeeper、MySQL 三种方案场景对比&选型参考

面向面试 + 实战双场景,涵盖 API 用法、源码原理、性能差异、踩坑经验,一文带你读透分布式锁的核心知识体系。


🧩 一、分布式锁的设计目标

分布式环境中,一个合格的锁需要满足以下核心特性:

  • 互斥性:同一时刻只能有一个客户端持有锁
  • 可重入性:同一线程可以重复获得锁
  • 安全释放:避免释放掉别人的锁
  • 容错性:服务宕机后锁可自动释放
  • 高可用性:不能成为系统瓶颈
  • 高性能:延迟低、并发强

🧱 二、主流实现方案对比

实现方式 优势 缺点 是否推荐
Redis(Redisson) 高性能、支持多种锁、自动续约、API 丰富 Redis 单点风险(需哨兵或集群)、依赖内存 ✅ 推荐
Zookeeper 强一致性、顺序临时节点、天然支持公平锁 TPS 较低、维护复杂 ⚠️ 谨慎
MySQL 易于上手、可用性高 实现复杂、易死锁、性能差、不可自动释放 ❌ 不推荐

🚀 三、Redisson 分布式锁实战

✅ 1. 基本使用

java 复制代码
RLock lock = redissonClient.getLock("order:lock:" + orderId);
lock.lock(10, TimeUnit.SECONDS); // 最多持有 10 秒
try {
    // 执行业务逻辑
} finally {
    lock.unlock();
}

🧠 2. 看门狗机制详解

  • 默认加锁时间为 30 秒
  • Redisson 会在后台自动续期(每隔 10 秒续 30 秒)
  • 适用于业务执行时间不确定的场景

🔒 3. 锁释放的原子性(Lua 脚本)

使用 Lua 保证"判断是否自己持有锁 + 删除锁"原子执行:

lua 复制代码
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end

🧾 4. 注解式封装(简化调用)

java 复制代码
@RedisLock(key = "order:lock:#orderId", expire = 20)
public void createOrder(Long orderId) {
    // your business logic
}

🦁 四、Zookeeper 分布式锁原理

✨ 原理简介

  • 客户端在 /lock 节点下创建临时顺序节点,如 /lock/lock_0000001
  • 所有客户端监听比自己小的前一个节点
  • 最小编号者获得锁,释放后触发下一个客户端监听器

🧪 示例(Curator)

java 复制代码
InterProcessMutex lock = new InterProcessMutex(client, "/lock/order");
lock.acquire();
try {
    // 临界区
} finally {
    lock.release();
}

🧱 五、MySQL 锁实现方式(仅学习用途)

🏗️ 方式一:唯一主键锁表法

sql 复制代码
CREATE TABLE distributed_lock (
  lock_key VARCHAR(64) PRIMARY KEY,
  expire_at DATETIME
);
sql 复制代码
-- 加锁
INSERT INTO distributed_lock(lock_key, expire_at)
VALUES ('order_lock', now() + interval 30 second);

-- 解锁
DELETE FROM distributed_lock WHERE lock_key = 'order_lock';

🚨 问题

  • 表锁性能差,不适合高并发
  • 不具备自动过期能力
  • 事务控制复杂,易产生死锁

📚 六、典型应用场景

🎯 幂等控制(避免重复下单)

java 复制代码
RLock lock = redissonClient.getLock("order:lock:" + userId);
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
    try {
        // 幂等校验逻辑
    } finally {
        lock.unlock();
    }
}

🛡️ 缓存击穿保护

  • 热点数据突然失效,防止多个线程同时访问 DB
  • 可结合 Bloom Filter + 分布式锁

⏳ 限流控制(加锁 + 队列)

  • 通过锁粒度控制同时执行的任务数量
  • 可用于控制某些业务压测/大促期间限流策略

📈 七、性能 & 适用场景对比

实现方案 性能 一致性保障 开发成本 适用场景
Redis ⭐⭐⭐⭐ 弱一致性 秒杀、缓存更新、幂等控制
Zookeeper ⭐⭐ 强一致性 任务调度、公平锁
MySQL 基于事务 小并发系统或实验环境

❓ 八、常见面试问答速记

🔹 Q:Redisson 和原生 Redis 加锁有何不同?

Redisson 内部封装了看门狗机制、Lua 原子解锁、支持公平锁/联锁/红锁等高级特性,避免自己维护续约线程、并发细节。


🔹 Q:为什么不推荐用 MySQL 实现分布式锁?

MySQL 作为关系型数据库,不适合高频并发场景,表锁实现复杂、缺乏原子释放机制,且无自动超时释放能力,极易出现死锁。


🔹 Q:Zookeeper 为什么可以实现公平锁?

其基于"顺序临时节点"机制,所有客户端排队监听比自己序号小的节点,天然具备公平性。


✅ 总结

  • ✅ 推荐使用 Redisson:性能高、易用、可扩展,适配大多数 Spring Boot 项目
  • ⚠️ Zookeeper 适用于对一致性极高要求的任务调度、主节点竞选等场景
  • MySQL 实现锁 不建议在任何中高并发系统中使用

相关推荐
这里有鱼汤15 分钟前
“三角收敛”战法全解析:我靠这一招实现了年化35%
后端·python
小鱼人爱编程42 分钟前
Java基石--Java发动机ClassLoader
java·spring boot·后端
一只叫煤球的猫1 小时前
从屎山说起:支付流程重构实战,三种设计模式灵活运用
java·后端·架构
xiezhr1 小时前
那些年我们一起追过的Java技术,现在真的别再追了!
java·后端·编程语言
Victor3561 小时前
MySQL(155)什么是MySQL的事件调度器?
后端
Victor3561 小时前
MySQL(156)如何使用MySQL的事件调度器?
后端
程序员爱钓鱼2 小时前
Go语言实战案例-使用map实现学生成绩管理
后端·google·go
程序员爱钓鱼2 小时前
Go语言实战案例-合并多个文本文件为一个
后端·google·go
Microsoft Word6 小时前
用户中心项目实战(springboot+vue快速开发管理系统)
vue.js·spring boot·后端
不写八个9 小时前
GoLang教程005:switch分支
开发语言·后端·golang