redission的原理

news/2025/2/27 10:17:05

分布式锁的实现
Redisson 最出名的功能之一是分布式锁(RLock)。它的锁机制基于 Redis 的原子性操作:

  • 使用 SET NX(SET if Not eXists)命令尝试获取锁,并设置一个过期时间(防止死锁)。
  • 通过 Lua 脚本确保锁的释放是原子性的,只有持有锁的客户端才能释放锁。
  • 支持锁续期(Watchdog 机制):如果任务未完成,Redisson 会自动为锁延长过期时间。

实现细节

1. 锁的基本存储

Redisson 使用 Redis 的 Hash 数据结构来存储锁的状态。锁的键名默认是用户指定的锁名称(例如 myLock),而 Hash 中的字段(field)则是客户端的唯一标识符(通常是线程 ID 或 UUID),值则是锁的重入计数。

  • Redis 中的表现形式

    myLock: { "thread-id-123": 1 }

    这里 myLock 是锁的键名,thread-id-123 是客户端标识,1 表示锁被获取了一次(支持重入)。

2. 获取锁的流程

Redisson 获取锁时,依赖 Redis 的 SET NX(SET if Not eXists)或更复杂的 Lua 脚本。以下是详细步骤:

  • 尝试加锁: Redisson 执行一个 Lua 脚本,脚本逻辑大致如下:
    1. 检查锁是否存在(通过 HEXISTS 检查 Hash 中是否有该客户端的字段)。
    2. 如果锁不存在,使用 HSET 设置锁状态,并通过 PEXPIRE 设置过期时间(默认 30 秒)。
    3. 如果锁已存在但属于当前客户端(重入),增加重入计数(HINCRBY)。
    4. 如果锁被其他客户端持有,返回失败。
  • Lua 脚本的优势: Redis 执行 Lua 脚本是原子性的,避免了多线程并发时的竞争问题。脚本伪代码可能像这样:
if (redis.call('exists', KEYS[1]) == 0) then
    redis.call('hset', KEYS[1], ARGV[1], 1);
    redis.call('pexpire', KEYS[1], ARGV[2]);
    return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[1]) == 1) then
    redis.call('hincrby', KEYS[1], ARGV[1], 1);
    redis.call('pexpire', KEYS[1], ARGV[2]);
    return nil;
end;
return redis.call('pttl', KEYS[1]);
    • KEYS[1]:锁的键名。
    • ARGV[1]:客户端标识。
    • ARGV[2]:锁的过期时间(毫秒)。
    • 返回结果: 如果成功获取锁,返回 nil;如果失败,返回锁的剩余存活时间(pttl),客户端可以据此决定是否重试。

4. 释放锁的流程

释放锁同样通过 Lua 脚本实现,确保只有锁的持有者能释放锁:

if (redis.call('hexists', KEYS[1], ARGV[1]) == 0) then
    return nil;
end;
local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1);
if (counter > 0) then
    redis.call('pexpire', KEYS[1], ARGV[2]);
    return 0;
end;
redis.call('del', KEYS[1]);
redis.call('publish', 'redisson_lock_channel', ARGV[3]);
return 1;

    释放逻辑

    1. 检查锁是否存在且属于当前客户端(HEXISTS)。
    2. 如果是重入锁,减少计数(HINCRBY -1)。
    3. 如果计数降为 0,删除锁(DEL)。
    4. 如果锁不属于当前客户端,返回失败。

    关键特性总结

    • 高可用性:在 Redis 集群中,锁状态会同步到多个节点。
    • 原子性:通过 Lua 脚本保证操作的原子性。
    • 重入性:支持同一客户端多次获取锁,使用计数器管理。
      安全性:只有锁的持有者能释放锁。


      http://www.niftyadmin.cn/n/5869937.html

      相关文章

      组件传递props校验

      注意&#xff1a;prop是只读的&#xff01;不可以修改父组件的数据。 可以检验传过来的内容是否类型没问题。 App.vue <template><div><!-- <parentDemo/> --><componentA/></div></template> <script> import ComponentA …

      港科大提出开放全曲音乐生成基础模型YuE:可将歌词转换成完整歌曲

      YuE是港科大提出的一个开源的音乐生成基础模型&#xff0c;专为音乐生成而设计&#xff0c;专门用于将歌词转换成完整的歌曲&#xff08;lyrics2song&#xff09;。它可以生成一首完整的歌曲&#xff0c;时长几分钟&#xff0c;包括朗朗上口的声乐曲目和伴奏曲目。YuE 能够模拟…

      【Java项目】基于Spring Boot的旅游管理系统

      【Java项目】基于Spring Boot的旅游管理系统 技术简介&#xff1a;采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介&#xff1a;旅游管理系统是一个基于Web的在线平台&#xff0c;主要分为前台和后台两大功能模块。前台功能模块包括&#xff08;1&#xff09;首…

      35. Spring Boot 2.1.3.RELEASE 应用监控【监控信息可视化】

      在 Spring Boot 2.1.3.RELEASE 中实现监控信息可视化可以通过多种方式&#xff0c;下面为你详细介绍使用 Spring Boot Actuator 结合 Grafana 和 Prometheus 以及使用 Spring Boot Admin 这两种常见方法。 方法一&#xff1a;Spring Boot Actuator Grafana Prometheus 1. 添…

      TCP/IP 5层协议簇:数据链路层(交换机工作原理)

      目录 1. 数据链路层 2. 帧 3. 工作在数据链路层的设备 4. 交换机工作原理 1. 数据链路层 数据链路层&#xff08;2层Data Link Layer&#xff09;&#xff1a;传输单元是帧、这层工作的主要设备二层交换机、网卡 2. 帧 帧的结构如下&#xff1a;帧最大1518字节 如下&…

      前端项目配置初始化

      creat-vue 安装 https://cn.vuejs.org/guide/quick-start.html 官网复制npm安装语句 cmd窗口创建文件夹 npm create vue3.12.2安装webstorm启动vue项目 https://www.jetbrains.com/webstorm/download/other.html 2024.3.2.1 安装依赖 下载包node_modules package 运行服…

      鸿蒙开发第4篇__关于在鸿蒙应用中使用Java语言进行设计

      本博文很重要 HarmonyOS从 API8 开始不再支持使用Java作为开发语言&#xff0c;未来的新功能将在ArkTS中实现. API 8对应的是HarmonyOS 3.0.0版本。请看下图&#xff1a; 因此&#xff0c; 读者如果看到类似《鸿蒙应用程序开发》(2021年版本 清华大学出版计)书 还使用Java语言…

      [深度学习]基于C++和onnxruntime部署yolov12的onnx模型

      基于C和ONNX Runtime部署YOLOv12的ONNX模型&#xff0c;可以遵循以下步骤&#xff1a; 准备环境&#xff1a;首先&#xff0c;确保已经下载后指定版本opencv和onnruntime的C库。 模型转换&#xff1a; 安装好yolov12环境并将YOLOv12模型转换为ONNX格式。这通常涉及使用深度学习…