Redis 分布式锁全解析:原理、实现与实战技巧一次掌握!

测试智商的网站 1周前 (08-04) 阅读数 5359 #性能测试

Redis 分布式锁深度解析:从原理到实战,一篇全懂!


一、为什么需要分布式锁?

在分布式系统中,多个进程/线程/服务可能同时操作同一资源,容易导致数据竞争、重复提交、状态错乱等问题。此时需要分布式锁来确保同一时间只有一个客户端操作临界资源


二、Redis 为啥适合做分布式锁?

  • 支持原子操作(SETNX、Lua)
  • 高性能、部署方便
  • TTL 能自动释放死锁
  • 支持 key 的过期时间和可视化调试

三、单机 Redis 分布式锁的核心实现

实现方案:基于 SET 命令的原子操作

SET lock_key unique_value NX EX 30

解释:

  • lock_key:锁的名字
  • unique_value唯一标识该客户端,用于释放锁验证
  • NX:只在 key 不存在时设置(SETNX)
  • EX 30:锁超时时间,防止死锁

释放锁必须使用 Lua 保证原子性:

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

Python 示例(使用 redis-py):

import redis
import uuid

r = redis.StrictRedis()
lock_key = "my_lock"
client_id = str(uuid.uuid4())

# 加锁
result = r.set(lock_key, client_id, nx=True, ex=30)
if result:
    try:
        # 临界区代码
        pass
    finally:
        # 释放锁(Lua脚本)
        lua_script = """ if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end """
        r.eval(lua_script, 1, lock_key, client_id)

四、常见问题与优化点

设置过期时间很关键

避免程序异常退出,锁不释放,导致死锁

唯一标识必须保证全局唯一

不能用线程 ID、主机名,推荐使用 UUID

释放锁必须校验身份

不能直接 DEL,必须校验是否是自己加的锁。


五、RedLock:Redis 官方分布式锁算法(多节点)

背景:

  • 单节点 Redis 锁在主从同步过程中可能发生“脑裂”
  • RedLock 提供更高安全性的分布式锁方案

RedLock 核心机制:

  1. 获取当前时间戳(单位:毫秒)
  2. 向多个 Redis 实例尝试获取锁(设置相同 key、value,带过期时间)
  3. 超过半数(N/2 + 1)节点加锁成功,并且加锁总耗时 < 锁过期时间
  4. 成功则认为加锁成功
  5. 如果加锁失败,依次释放所有节点上的锁

RedLock 是一种「多数节点 + 时间限制 + 锁释放一致性」的加锁方案


六、RedLock 的争议(附面试亮点️)

Martin Kleppmann(《设计数据密集型应用》作者)提出过质疑:

  • 多节点同步有延迟
  • 网络分区下可能锁重入
  • 容错机制不如 ZooKeeper 严格

Redis 官方回应:RedLock 适用于大多数非强一致性业务场景(如秒杀、库存控制等)

面试时如果你能谈到这场争议,绝对加分


七、Redis 锁 vs ZooKeeper 锁

特性 Redis 分布式锁 ZooKeeper 分布式锁
可用性
一致性
实现复杂度 简单 较复杂(需节点监听)
性能 高(适合高并发)
推荐使用场景 秒杀、抢单、库存、限流 金融交易、强一致业务

八、总结一张图

         Redis分布式锁核心点
 ┌─────────────────────────────┐
 │ SET key value NX EX seconds│←原子加锁
 │ if GET == value => DEL key │←Lua原子释放锁
 │ value = UUID() 唯一标识    │
 │ 设置 TTL 避免死锁           │
 └─────────────────────────────┘
        ↑                      ↑
    单机适用             RedLock:多节点安全

九、面试高频 Q&A 🧠

Q: Redis 加锁后服务崩了怎么办?

答:设置了 EX 过期时间,锁会自动过期释放,防止死锁。


Q: 多个服务竞争 Redis 锁,如何避免误删别人加的锁?

答:加锁时使用唯一 UUID 标识自己,释放锁时需验证 valueUUID 是否一致。


推荐使用的开源封装库

  • Java:Redisson(支持可重入锁、读写锁等)
  • Python:redis-lock、redlock-py
  • Go:go-redsync

总结一句话

Redis 分布式锁核心是:原子加锁 + 过期时间 + 身份校验 + 安全释放,RedLock 是其在分布式环境下的延伸方案。


如果你想我进一步写一篇《Redisson 分布式锁实战教程(附代码)》或《基于 Redis 分布式锁的秒杀系统设计》,我也可以继续扩展

  • 随机文章
  • 热门文章
  • 热评文章
热门