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

redission的原理

分布式锁的实现
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.dtcms.com/a/38531.html

      相关文章:

    • JS UI库DHTMLX Suite 发布v9.1:具有行扩展器、多重排序、多用户后端等功能的网格
    • 《算法笔记》9.6小节 数据结构专题(2)并查集 问题 A: 通信系统
    • IO 和NIO有什么区别?
    • 2025.2.26总结
    • 机试刷题_面试题 08.08. 有重复字符串的排列组合【python】
    • 算法day1 dfs搜索2题
    • 智绘教:Windows平台上的高效悬浮窗画笔工具深度解析
    • mac 安装Eclipse,汉化及安装ERMaster
    • 搜索赋能:大型语言模型的知识增强与智能提升
    • mamba,mamba2环境搭建
    • # C/C++右移高位补0还是1?
    • eclipse配置Spring
    • 数据安全_笔记系列07:数据泄露防护(DLP)(监控与阻断敏感数据外泄)深度解析
    • AI创作教程:用deepseek和猫箱做互动故事游戏
    • NLP的预处理数据
    • 磁盘使用LVM方式挂载目录
    • 【xinference 词嵌入】embbeding 使用教程
    • 大白话Vue 双向数据绑定的实现原理与数据劫持技术
    • 【10】RUST的迭代器与闭包
    • Proof Beyond Boundaries: Hong Kong zkNight 活动精彩回顾
    • 零样本学习 zero-shot
    • LeetCodehot 力扣热题100 全排列
    • 《Keras 3 使用 PointNet 进行点云分类》:此文为AI自动翻译
    • Ubuntu指令(一)
    • SVT-AV1接入ffmpeg说明
    • SSM和SpringBoot有什么区别?
    • Spring 框架学习笔记:从零到精通的 21 个关键点
    • pyautogui库的screenshot()函数
    • python poetry添加某个git仓库的某个分支
    • 学习FreeRTOS推荐几篇质量高的文章