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

Redis中的分布式锁

目录

基于Redis的SetNx命令

实现:

为什么要判断锁是否是本线程加上的(为什么要引入校验id)?

为什么要使用用Lua脚本来完成(为什么要引入Lua)?

问题

基于Redisson

Redisson可重入锁原理

1.获取锁的逻辑

2.释放锁的逻辑

超时续约机制(看门狗机制)

Redisson分布式锁的数据未同步导致线程安全

主从问题:

解决方案:

Redlock 算法的具体过程


基于Redis的SetNx命令

SetNX 如果key已存在,则结果返回0。如果key不存在,则结果返回1。

实现:

1.加锁set unique_key 机器码+线程ID NX EX TTLunique_key 一般是业务唯一标识)

  • 加锁成功:执行命令结果返回1
  • 加锁失败:执行命令结果返回0
  • 能实现互斥且设置了TTL,可以通过TTL到期删除key,自动释放锁,防止死锁情况

2.释放锁执行 del 删除 key 的命令

a.先 Get key 拿到 value 判断当前锁是否是本机器本线程加上的

  • 若是,可以正常删除锁
  • 若不是,则不需要处理

为什么要判断锁是否是本线程加上的(为什么要引入校验id)?

是为了防止锁误删的情况

举例: 线程1业务阻塞,锁的TTL到期,Redis key 自动删除,则锁释放,然后线程2获取到了锁。在线程2正常执行时,线程1恢复运行,如果线程1不判断当前锁是否是自己加上的,直接把锁删除了,就出现问题——线程1误删了线程2的锁。

为什么要使用用Lua脚本来完成(为什么要引入Lua)?

因为判断是否是当前线程的锁 + 删除key释放锁 两个操作,这两个操作如果不是原子的就会出现如图片上的问题,使用Lua脚本,使得这两个操作变为原子性的

问题

  • 由于业务执行耗时太长,TTL到期,锁被迫释放,存在多个线程并行的情况
  • SetNX 线程不可重入

  • TTL不好设置,业务到底要执行多长时间,我们不太确定(这个可以引入看门狗解决)

基于Redisson

Redisson 是市面上成熟的分布式锁组件,相对于用 SetNx 命令实现的分布式锁更加强大和完善。

Redisson可重入锁原理

即一个线程可以多次获取锁。利用Hash结构,记录获取锁的线程获取锁的次数

1.获取锁的逻辑

a.判断 key(unique_value一般是业务唯一标识) 是否存在,即判断是否有线程持有锁

  • 如果key不存在,代表没有线程持有锁,则获取锁,即设置一个Hash结构的 (field,value),field是机器码+线程ID,value是 次数 1
  • 如果key存在,代表有线程持有锁,此时判断持有锁的线程是否是当前线程,如果是当前线程,则重入次数+1。
2.释放锁的逻辑

a.重入次数-1,如果重入次数为0,删除key,释放锁。

超时续约机制(看门狗机制)

为了解决TTL不好设置,如果分布式锁的key设置了TTL,又因为业务阻塞原因,导致当前线程的业务未完成,TTL到期了,导致被迫释放锁,此时就会有其他线程抢占锁,导致有线程并行执行,违背了加分布式锁的初心。

当 Redisson 获取锁没有指定锁的TTL时,默认会使用超时续约机制(看门狗WatchDog)机制。

续期规则

  • 默认 TTL 为 30 秒,后台线程(定时任务)每隔 10 秒 检查业务是否完成。
  • 若未完成 → 通过 Lua 脚本重置锁 TTL(续期至 30 秒),保证锁不被释放,等到业务执行完。

Redisson分布式锁的数据未同步导致线程安全

主从问题

  • 主节点宕机时,若从节点未同步 锁 数据 (就是主节点还没来得及把数据给同步到从节点,就挂了,导致加锁失败)→ 新主节点可能允许其他线程重复加锁 → 锁失效

解决方案:

  • 此时需要部署多个 Redis 主节点,多主多从架构,向多个主节点都去获取锁
  • MultiLock 联锁方案:要求 所有主节点加锁成功,否则立即失败并释放已获取的锁(要么全部成功要么全部失败)
  • RedLock 红锁方案:要求 半数主节点以上(如 3/5)加锁成功,否则立即失败并释放已获取的锁。
Redlock 算法的具体过程

引⼊⼀组 Redis 节点. 其中每⼀组 Redis 节点都包含⼀个主节点和若⼲从节点. 并且组和组之间存 储的数据都是⼀致的, 相互之间是 "备份" 关系(⽽并⾮是数据集合的⼀部分, 这点有别于 Redis cluster). 加锁的时候, 按照⼀定的顺序, 写多个 master 节点. 在写锁的时候需要设定操作的 "超时时间". ⽐如 50ms. 即如果 setnx 操作超过了 50ms 还没有成功, 就视为加锁失败.

同理, 释放锁的时候, 也需要把所有节点都进⾏解锁操作. (即使是之前超时的节点, 也要尝试解锁, 尽量保 证逻辑严密)

Redlock 算法的核⼼就是, 加锁操作不能只写给⼀个 Redis 节点, ⽽要写个多个!! 分布式系统中任何⼀个节点都是不可靠的. 最终的加锁成功结论是 "少数服从多数的"

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

相关文章:

  • JVM核心知识整理《1》
  • 可以上传数据的网站开发图书页面设计模板
  • 09.MCP协议介绍
  • 彻底讲清楚 Kotlin 的 when 表达式
  • 济宁网站建设 果壳科技腾讯云主机
  • 百度收录不到我的网站聊大 网站设计
  • Jackson SerializerModifier 拦截器(高性能)实现时间戳自动添加
  • 虚拟机server2012 安装oracle11g遇到的坑
  • Webpack中各种devtool配置的含义与SourceMap生成逻辑
  • 深入理解 PostgreSQL Tuple 与 Dead Tuple:检测方法与 VACUUM 自动化实践
  • 系统分析师-案例分析-数据库系统数据仓库反规范化技术NoSQL内存数据库
  • 用Python来学微积分32-定积分的可积性条件详解
  • 游戏远程操控性能横评:ToDesk、Parsec、UU远程深度对比
  • 【C/C++刷题集】二叉树算法题(二)
  • Django登录注册完整代码(图片、邮箱验证、加密)
  • 基于Optuna 贝叶斯优化的自动化XGBoost 超参数调优器
  • Qt开发初识
  • ReactNative 快速入门手册
  • 【C++:map和set的使用】C++ map/multimap完全指南:从红黑树原理入门到高频算法实战
  • GPT-OSS大模型Attention架构设计
  • 基于Mask R-CNN和TensorRT的高效草莓实例分割
  • RV1126 NO.38:OPENCV查找图形轮廓重要API讲解
  • 腾讯WAIC发布“1+3+N”AI全景图:混元3D世界模型开源,具身智能平台Tairos亮相
  • 各种开源闭源大模型,包括自己本地部署的一些8b 14b模型,支持函数调用(功能调用)function call吗?
  • Spring Boot 深度剖析:从虚拟线程到声明式 HTTP 客户端,再到云原生最优解
  • 创新的商城网站建设网站页面怎么设计
  • 2016年网站建设总结php网站开发工资多少
  • 线程3.1
  • Kubernetes基础概念和命令
  • 技术干货-MYSQL数据类型详解