Redisson 分布式锁源码 09:RedLock 红锁的故事

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: RedLock 红锁,是分布式锁中必须要了解的一个概念。所以本文会先介绍什么是 RedLock,当大家对 RedLock 有一个基本的了解。然后再看 Redisson 中是如何实现 RedLock 的。

前言


RedLock 红锁,是分布式锁中必须要了解的一个概念。

所以本文会先介绍什么是 RedLock,当大家对 RedLock 有一个基本的了解。然后再看 Redisson 中是如何实现 RedLock 的。

在文章开头先说明 Redisson RedLock 建议不要使用!!!在文章开头先说明 Redisson RedLock 建议不要使用!!!在文章开头先说明 Redisson RedLock 建议不要使用!!!

重要的事情重复三遍!


什么是 RedLock?

RedLock,这块可以从网上搜到很多资料,本文也简单介绍下,当做扫盲。

单实例加锁

SET resource_name my_random_value NX PX 30000
复制代码

对于单实例 Redis 只需要使用这个命令即可。

  • NX:仅在不存在 key 的时候才能被执行成功;
  • PX:失效时间,传入 30000,就是 30s 后自动释放锁;
  • my_random_value:就是随机值,可以是线程号之类的。主要是为了更安全的释放锁,释放锁的时候使用脚本告诉 Redis: 只有 key 存在并且存储的值和我指定的值一样才能删除成功

可以通过以下 Lua 脚本实现锁释放:

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

为什么要设置随机值?

主要是为了防止锁被其他客户端删除。有这么一种情况:

  1. 客户端 A 获得了锁,还没有执行结束,但是锁超时自动释放了;
  2. 客户端 B 此时过来,是可以获得锁的,加锁成功;
  3. 此时,客户端 A 执行结束了,要去释放锁,如果不对比随机值,就会把客户端 B 的锁给释放了。

当然前面看过 Redisson 的处理,这个 my_random_value 存放的是 UUID:ThreadId 组合成的一个类似 931573de-903e-42fd-baa7-428ebb7eda80:1 的字符串。


当锁遇到故障转移

单实例肯定不是很可靠吧?加锁成功之后,结果 Redis 服务宕机了,这不就凉凉~

这时候会提出来将 Redis 主从部署。即使是主从,也是存在巧合的!

主从结构中存在明显的竞态:

  1. 客户端 A 从 master 获取到锁
  2. 在 master 将锁同步到 slave 之前,master 宕掉了。
  3. slave 节点被晋级为 master 节点
  4. 客户端 B 取得了同一个资源被客户端 A 已经获取到的另外一个锁。安全失效!

有时候程序就是这么巧,比如说正好一个节点挂掉的时候,多个客户端同时取到了锁。如果你可以接受这种小概率错误,那用这个基于复制的方案就完全没有问题。

那我使用集群呢?

如果还记得前面的内容,应该是知道对集群进行加锁的时候,其实是通过 CRC16 的 hash 函数来对 key 进行取模,将结果路由到预先分配过 slot 的相应节点上。

发现其实还是发到单个节点上的


RedLock 概念

这时候 Redis 作者提出了 RedLock 的概念

网络异常,图片无法展示
|

总结一下就是对集群的每个节点进行加锁,如果大多数(N/2+1)加锁成功了,则认为获取锁成功。


RedLock 的问题

看着 RedLock 好像是解决问题了:

  1. 客户端 A 锁住了集群的大多数(一半以上);
  2. 客户端 B 也要锁住大多数;
  3. 这里肯定会冲突,所以 客户端 B 加锁失败。

那实际解决问题了么?

推荐大家阅读两篇文章:

最终,两方各持己见,没有得出结论。

鉴于本文主要是分析 Redisson 的 RedLock,就不做额外赘述,感兴趣的小伙伴可以自己阅读。


Redisson 中 RedLock 源码

这里会简要分析一下 Redisson 中 RedLock 的源码,然后会介绍为什么文章开头不建议大家使用 Redisson 的 RedLock。


使用方式

网络异常,图片无法展示
|


乍一看,感觉和联锁 MultiLock 的使用方式很像啊!

网络异常,图片无法展示
|

实际上就是很像,RedissonRedLock 完全是 RedissonMultiLock 的子类嘛!

只不过是重写 failedLocksLimit 方法。

在 MultiLock 中,要所有的锁都锁成功才可以。

在 RedLock 中,要一半以上的锁成功。

剩余部分源码都和 MultiLock 一样,就不在重复描述了。


Redisson 中 RedLock 的问题


1、加锁 key 的问题

阅读源码之前,有一个很大的疑问,我加锁 lock1、lock2、lock3,但是 RedissonRedLock 是如何保证这三个 key 是在归属于 Redis 集群中不同的 master 呢?

因为按照 RedLock 的理论,是需要在半数以上的 master 节点加锁成功

阅读完源码之后,发现 RedissonRedLock 完全是 RedissonMultiLock 的子类,只是重写了 failedLocksLimit 方法,保证半数以上加锁成功即可。

所以这三个 key,是需要用户来保证分散在不同的节点上的。

网络异常,图片无法展示
|

github.com/redisson/re…

在 Redisson 的 issues 也有同样的小伙伴提出这个问题,相关开发者给出的回复是用户来保证 key 分散在不同的 master 上。

github.com/redisson/re…

更有小伙伴提出使用 5 个客户端。

网络异常,图片无法展示
|

那我使用 5 个单节点的客户端,然后再使用红锁,听着好像是可以的,并且 RedissonRedLock 可以这样使用。

但是那和 Redis 集群还有啥关系啊!

所以依然没有解决我的问题,还是需要用户自己来“手工定位锁”。

手工定位锁,这个…… 我考虑了下,还是不用 RedLock 吧!

当然 DarrenJiang1990 同学应该是怀着打破砂锅问到底的心情,又来了一篇 issue。

github.com/redisson/re…

意思就是:不要关闭我的 issues,在 #2436 中说可以“手工定位锁”,但是我要怎么手工定位锁。

后来这个 issue 在 10 月才回复。

网络异常,图片无法展示
|


2、RedissonRedLock 被弃用

是的,没有看错,现在 RedissonRedLock 已经被启用了。

如果是看的英文文档,就会发现:

网络异常,图片无法展示
|

而中文文档,应该是没有及时更新。

来看看更新记录:

网络异常,图片无法展示
|


再找一找 issue:

github.com/redisson/re…

网络异常,图片无法展示
|


Redisson 的开发者认为 Redis 的红锁也存在争议(前文介绍的那个争议),但是为了保证可用性,RLock 对象执行的每个 Redis 命令执行都通过 Redis 3.0 中引入的 WAIT 命令进行同步。

WAIT 命令会阻塞当前客户端,直到所有以前的写命令都成功的传输并被指定数量的副本确认。如果达到以毫秒为单位指定的超时,则即使尚未达到指定数量的副本,该命令也会返回。 WAIT 命令同步复制也并不能保证强一致性,不过在主节点宕机之后,只不过会尽可能的选择最佳的副本(slaves)

网络异常,图片无法展示
|


源码在这一部分。

网络异常,图片无法展示
|

看源码,同时发送了一个 WAIT 1 1000 到 Redis。


结论


Redisson RedLock 是基于联锁 MultiLock 实现的,但是使用过程中需要自己判断 key 落在哪个节点上,对使用者不是很友好。

Redisson RedLock 已经被弃用,直接使用普通的加锁即可,会基于 wait 机制将锁同步到从节点,但是也并不能保证一致性。仅仅是最大限度的保证一致性。

目录
相关文章
|
7月前
|
NoSQL 调度 Redis
分布式锁—3.Redisson的公平锁
Redisson公平锁(RedissonFairLock)是一种基于Redis实现的分布式锁,确保多个线程按申请顺序获取锁,从而实现公平性。其核心机制是通过队列和有序集合管理线程的排队顺序。加锁时,线程会进入队列并等待,锁释放后,队列中的第一个线程优先获取锁。RedissonFairLock支持可重入加锁,即同一线程多次加锁不会阻塞。新旧版本在排队机制上有所不同,新版本在5分钟后才会重排队列,而旧版本在5秒后就会重排。释放锁时,Redisson会移除队列中等待超时的线程,并通知下一个排队的线程获取锁。通过这种机制,RedissonFairLock确保了锁的公平性和顺序性。
|
8月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
278 5
|
5月前
|
NoSQL Java Redis
基于Redisson和自定义注解的分布式锁实现策略。
在实现分布式锁时,保证各个组件配置恰当、异常处理充足、资源清理彻底是至关重要的。这样保障了在分布布局场景下,锁的正确性和高效性,使得系统的稳健性得到增强。通过这种方式,可以有效预防并发环境下的资源冲突问题。
275 29
|
8月前
|
负载均衡 NoSQL 算法
Redisson分布式锁数据一致性解决方案
通过以上的设计和实现, Redisson能够有效地解决分布式环境下数据一致性问题。但是, 任何技术都不可能万无一失, 在使用过程中还需要根据实际业务需求进行逻辑屏障的设计和错误处理机制的建立。
370 48
|
7月前
|
NoSQL 调度 Redis
分布式锁—5.Redisson的读写锁
Redisson读写锁(RedissonReadWriteLock)是Redisson提供的一种分布式锁机制,支持读锁和写锁的互斥与并发控制。读锁允许多个线程同时获取,适用于读多写少的场景,而写锁则是独占锁,确保写操作的互斥性。Redisson通过Lua脚本实现锁的获取、释放和重入逻辑,并利用WatchDog机制自动续期锁的过期时间,防止锁因超时被误释放。 读锁的获取逻辑通过Lua脚本实现,支持读读不互斥,即多个线程可以同时获取读锁。写锁的获取逻辑则确保写写互斥和读写互斥,即同一时间只能有一个线程获取写锁,
376 17
|
NoSQL 安全 调度
【📕分布式锁通关指南 10】源码剖析redisson之MultiLock的实现
Redisson 的 MultiLock 是一种分布式锁实现,支持对多个独立的 RLock 同时加锁或解锁。它通过“整锁整放”机制确保所有锁要么全部加锁成功,要么完全回滚,避免状态不一致。适用于跨多个 Redis 实例或节点的场景,如分布式任务调度。其核心逻辑基于遍历加锁列表,失败时自动释放已获取的锁,保证原子性。解锁时亦逐一操作,降低死锁风险。MultiLock 不依赖 Lua 脚本,而是封装多锁协调,满足高一致性需求的业务场景。
253 0
【📕分布式锁通关指南 10】源码剖析redisson之MultiLock的实现
|
7月前
|
算法 NoSQL Redis
分布式锁—4.Redisson的联锁和红锁
Redisson的MultiLock和RedLock机制为分布式锁提供了强大的支持。MultiLock允许一次性锁定多个资源,确保在更新这些资源时不会被其他线程干扰。它通过将多个锁合并为一个大锁,统一进行加锁和释放操作。RedissonMultiLock的实现通过遍历所有锁并尝试加锁,若在超时时间内无法获取所有锁,则释放已获取的锁并重试。 RedLock算法则基于多个Redis节点的加锁机制,确保在大多数节点上加锁成功即可。RedissonRedLock通过重载MultiLock的failedLocksLi
403 10
|
7月前
|
NoSQL Java Redis
分布式锁—6.Redisson的同步器组件
Redisson提供了多种分布式同步工具,包括分布式锁、Semaphore和CountDownLatch。分布式锁包括可重入锁、公平锁、联锁、红锁和读写锁,适用于不同的并发控制场景。Semaphore允许多个线程同时获取锁,适用于资源池管理。CountDownLatch则用于线程间的同步,确保一组线程完成操作后再继续执行。Redisson通过Redis实现这些同步机制,提供了高可用性和高性能的分布式同步解决方案。源码剖析部分详细介绍了这些组件的初始化和操作流程,展示了Redisson如何利用Redis命令和
|
9月前
|
安全
【📕分布式锁通关指南 07】源码剖析redisson利用看门狗机制异步维持客户端锁
Redisson 的看门狗机制是解决分布式锁续期问题的核心功能。当通过 `lock()` 方法加锁且未指定租约时间时,默认启用 30 秒的看门狗超时时间。其原理是在获取锁后创建一个定时任务,每隔 1/3 超时时间(默认 10 秒)通过 Lua 脚本检查锁状态并延长过期时间。续期操作异步执行,确保业务线程不被阻塞,同时仅当前持有锁的线程可成功续期。锁释放时自动清理看门狗任务,避免资源浪费。学习源码后需注意:避免使用带超时参数的加锁方法、控制业务执行时间、及时释放锁以优化性能。相比手动循环续期,Redisson 的定时任务方式更高效且安全。
532 24
【📕分布式锁通关指南 07】源码剖析redisson利用看门狗机制异步维持客户端锁
|
7月前
|
监控 NoSQL Java
分布式锁—2.Redisson的可重入锁
本文主要介绍了Redisson可重入锁RedissonLock概述、可重入锁源码之创建RedissonClient实例、可重入锁源码之lua脚本加锁逻辑、可重入锁源码之WatchDog维持加锁逻辑、可重入锁源码之可重入加锁逻辑、可重入锁源码之锁的互斥阻塞逻辑、可重入锁源码之释放锁逻辑、可重入锁源码之获取锁超时与锁超时自动释放逻辑、可重入锁源码总结。