当前位置: 首页 > news >正文

Redis分布式锁详解

Redis分布式锁详解

分布式锁是在分布式系统中实现互斥访问共享资源的重要机制。Redis因其高性能和原子性操作特性,常被用来实现分布式锁。

一、基础实现方案

1. SETNX + EXPIRE方案(基本版)

# 加锁
SETNX lock_key unique_value  # 设置唯一标识
EXPIRE lock_key 10          # 设置过期时间

# 解锁
DEL lock_key                # 删除键

问题

  • 非原子性操作(SETNX和EXPIRE分开执行可能失败)
  • 可能误删其他客户端的锁

2. SET扩展命令方案(推荐)

# 原子性加锁
SET lock_key unique_value NX PX 10000  # NX表示不存在才设置,PX设置毫秒级过期时间

# 解锁(Lua脚本保证原子性)
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

优势

  • 原子性加锁
  • 设置过期时间防止死锁
  • 通过唯一值避免误删

二、Redlock算法(多节点版)

当需要更高可靠性时,Redis作者提出的Redlock算法:

  1. 获取当前时间(毫秒)
  2. 依次尝试从N个独立的Redis节点获取锁
  3. 计算获取锁总耗时(小于锁过期时间)
  4. 当从多数节点(N/2+1)获取成功,且总耗时小于锁有效时间,才认为加锁成功
  5. 若失败,向所有节点发起解锁请求

三、Java实现示例(Redisson)

// 1. 获取锁对象
RLock lock = redissonClient.getLock("myLock");

try {
    // 2. 尝试加锁(参数:等待时间,锁自动释放时间,时间单位)
    boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
    
    if (isLocked) {
        // 3. 执行业务代码
        doBusiness();
    }
} finally {
    // 4. 释放锁
    lock.unlock();
}

四、关键问题与解决方案

1. 锁续期(Watchdog机制)

问题:业务执行时间超过锁过期时间
方案:Redisson的看门狗会定期(默认10秒)检查并延长锁时间

2. 可重入性

方案:使用计数器记录重入次数(Redisson已实现)

3. 锁等待与公平性

方案

  • 实现锁等待队列
  • 使用Redis的List结构模拟队列

4. 主从切换问题

问题:主节点崩溃可能导致锁丢失
方案

  • 使用Redlock多节点方案
  • 或使用Redis的WAIT命令确保数据同步

五、生产环境建议

  1. 锁命名规范业务:资源:操作order:123:pay
  2. 超时时间设置
    • 不宜过短(业务未完成锁已释放)
    • 不宜过长(系统故障时恢复慢)
  3. 监控指标
    • 锁获取成功率
    • 平均持有时间
    • 等待队列长度
  4. 降级方案:Redis不可用时切换本地锁或数据库锁

六、与其他方案对比

方案优点缺点适用场景
Redis锁性能高、实现简单可靠性依赖Redis大多数分布式场景
Zookeeper锁可靠性高性能较低强一致性要求场景
数据库锁无需额外组件性能差、有死锁风险简单场景

七、最佳实践

  1. 始终为锁设置合理的过期时间
  2. 使用唯一标识(UUID/线程ID)作为锁值
  3. 释放锁前验证持有者身份
  4. 考虑使用成熟的客户端(如Redisson)而非自己实现
  5. 重要业务实现锁续期机制

Redis分布式锁在大多数场景下能很好工作,但对于对可靠性要求极高的场景,建议考虑Zookeeper或etcd等强一致性协调服务实现的分布式锁。

http://www.dtcms.com/a/112384.html

相关文章:

  • AWS Langfuse AI用Bedrock模型使用完全教程
  • 【万字总结】前端全方位性能优化指南(八)——Webpack 6调优、模块联邦升级、Tree Shaking突破
  • 安卓离线畅玩的多款棋类单机游戏推荐
  • 【leetcode100】动态规划Java版本
  • Debezium日常分享系列之:Debezium 3.1.0.Final发布
  • 什么是量子计算?
  • 【代码艺廊】pyside6桌面应用范例:homemade-toolset
  • 如何实现浏览器中的报表打印
  • Pytorch使用GPU、CUDA安装步骤注意事项
  • Redis 中 Set(例如标签) 和 ZSet(例如排行榜) 的详细对比,涵盖定义、特性、命令、适用场景及总结表格
  • CSS 创建与使用学习笔记
  • 室内指路机器人是否支持环境监测功能?
  • 【数据分享】2002-2023中国湖泊水位变化数据集(免费获取)
  • 【数据结构】树的介绍
  • k8s的pod的概述和配置
  • Vue 未编译模板闪现现象解说
  • Spring Boot 与 TDengine 的深度集成实践(二)
  • 【力扣hot100题】(051)腐烂的橘子
  • Mybatis---入门
  • 音视频基础(音频常用概念)
  • zk基础—2.架构原理和使用场景一
  • python爬虫:小程序逆向实战教程
  • leetcode数组-有序数组的平方
  • 软件工程面试题(二十五)
  • 58.基于springboot老人心理健康管理系统
  • 网络:华为HCIA学习笔记:ICMP协议
  • List结构之非实时榜单实战
  • Nginx配置伪静态,URL重写
  • 通过 ModelScope 下载模型,解决sentence-transformers/all-MiniLM-L6-v2无法下载问题
  • 【leetcode100】数组中的第K个最大元素