阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

细说Redis分布式锁

387次阅读
没有评论

共计 3402 个字符,预计需要花费 9 分钟才能阅读完成。

谈起 Redis 锁,下面三个,算是出现最多的高频词汇:
  • Setnx
  • Redlock
  • Redisson

Setnx

其实目前通常所说的 Setnx 命令,并非单指 Redis 的 setnx key value 这条命令。
一般代指 Redis 中对 set 命令加上 nx 参数进行使用,set 这个命令,目前已经支持这么多参数可选:
细说 Redis 分布式锁
当然了,就不在文章中默写 API 了,基础参数还有不清晰的,可以蹦到官网:https://redis.io/commands/set
细说 Redis 分布式锁
上图是笔者画的 Setnx 大致原理,主要依托了它的 key 不存在才能 set 成功的特性,进程 A 拿到锁,在没有删除锁的 Key 时,进程 B 自然获取锁就失败了。
那么为什么要使用 PX 30000 去设置一个超时时间?
是怕进程 A 不讲道理啊,锁没等释放呢,万一崩了,直接原地把锁带走了,导致系统中谁也拿不到锁。
细说 Redis 分布式锁
就算这样,还是不能保证万无一失。
如果进程 A 又不讲道理,操作锁内资源超过笔者设置的超时时间,那么就会导致其他进程拿到锁,等进程 A 回来了,回手就是把其他进程的锁删了,如图:
细说 Redis 分布式锁
还是刚才那张图,将 T5 时刻改成了锁超时,被 Redis 释放。
进程 B 在 T6 开开心心拿到锁不到一会,进程 A 操作完成,回手一个 del,就把锁释放了。
当进程 B 操作完成,去释放锁的时候(图中 T8 时刻):
细说 Redis 分布式锁
找不到锁其实还算好的,万一 T7 时刻有个进程 C 过来加锁成功,那么进程 B 就把进程 C 的锁释放了。
以此类推,进程 C 可能释放进程 D 的锁,进程 D……(禁止套娃),具体什么后果就不得而知了。
所以在用 Setnx 的时候,key 虽然是主要作用,但是 value 也不能闲着,可以设置一个唯一的客户端 ID,或者用 UUID 这种随机数。
当解锁的时候,先获取 value 判断是否是当前进程加的锁,再去删除。伪代码:
细说 Redis 分布式锁
这回看起来是不是稳了。
相反,这回的问题更明显了,在 finally 代码块中,get 和 del 并非原子操作,还是有进程安全问题。
细说 Redis 分布式锁
为什么有问题还说这么多呢?
第一,搞清劣势所在,才能更好的完善。
第二点,其实上文中最后这段代码,还是有很多公司在用的。
大小项目悖论:大公司实现规范,但是小司小项目虽然存在不严谨,可并发倒也不高,出问题的概率和大公司一样低。——鲁迅
细说 Redis 分布式锁
那么删除锁的正确姿势之一,就是可以使用 Lua 脚本,通过 Redis 的 eval/evalsha 命令来运行:
细说 Redis 分布式锁
通过 Lua 脚本能保证原子性的原因说的通俗一点:
就算你在 Lua 里写出花,执行也是一个命令(eval/evalsha)去执行的,一条命令没执行完,其他客户端是看不到的。
那么既然这么麻烦,有没有比较好的工具呢?就要说到 Redisson 了。
介绍 Redisson 之前,笔者简单解释一下为什么现在的 Setnx 默认是指 set 命令带上 nx 参数,而不是直接说是 Setnx 这个命令。
因为 Redis 版本在 2.6.12 之前,set 是不支持 nx 参数的,如果想要完成一个锁,那么需要两条命令:
细说 Redis 分布式锁
即放入 Key 和设置有效期,是分开的两步,理论上会出现 1 刚执行完,程序挂掉,无法保证原子性。
但是早在 2013 年,也就是 7 年前,Redis 就发布了 2.6.12 版本,并且官网(set 命令页 [1]),也早早就说明了“SETNX,SETEX,PSETEX 可能在未来的版本中,会弃用并永久删除”。
笔者曾阅读过一位大佬的文章,其中就有一句指导入门者的面试小套路,具体文字忘记了,大概意思如下:
说到 Redis 锁的时候,可以先从 Setnx 讲起,最后慢慢引出 set 命令的可以加参数,可以体现出自己的知识面。
如果有缘你也阅读过这篇文章,并且学到了这个套路,作为本文的笔者我要加一句提醒:
请注意你的工作年限!首先回答官网表明即将废弃的命令,再引出 set 命令七年前的“新特性”,如果是刚毕业不久的人这么说,面试官会以为自己穿越了。
你套路面试官,面试官也会套路你。——vt ・沃兹基硕德

Redisson

Redisson 是 Java 的 Redis 客户端之一,提供了一些 API 方便操作 Redis。
但是 Redisson 这个客户端可有点厉害,笔者在官网截了仅仅是一部分的图:
细说 Redis 分布式锁
这个特性列表可以说是太多了,是不是还看到了一些 JUC 包下面的类名,Redisson 帮我们搞了分布式的版本,比如 AtomicLong,直接用 RedissonAtomicLong 就行了,连类名都不用去新记,很人性化了。
锁只是它的冰山一角,并且从它的 wiki[2] 页面看到,对主从,哨兵,集群等模式都支持,当然了,单节点模式肯定是支持的。
本文还是以锁为主,其他的不过多介绍。
Redisson 普通的锁实现源码主要是 RedissonLock 这个类,还没有看过它源码的盆友,不妨去瞧一瞧。
源码中加锁 / 释放锁操作都是用 Lua 脚本完成的,封装的非常完善,开箱即用。
这里有个小细节,加锁使用 Setnx 就能实现,也采用 Lua 脚本是不是多此一举?笔者也非常严谨的思考了一下:这么厉害的东西哪能写废代码?
细说 Redis 分布式锁
其实笔者仔细看了一下,加锁解锁的 Lua 脚本考虑的非常全面,其中就包括锁的重入性,这点可以说是考虑非常周全,我也随手写了代码测试一下:
细说 Redis 分布式锁
的确用起来像 JDK 的 ReentrantLock 一样丝滑,那么 Redisson 实现的已经这么完善,RedLock 又是什么?

RedLock

细说 Redis 分布式锁
RedLock 的中文是直译过来的,就叫红锁。
红锁并非是一个工具,而是 Redis 官方提出的一种分布式锁的算法。
就在刚刚介绍完的 Redisson 中,就实现了 redLock 版本的锁。也就是说除了 getLock 方法,还有 getRedLock 方法。
笔者大概画了一下对红锁的理解:
细说 Redis 分布式锁
如果你不熟悉 Redis 高可用部署,那么没关系。RedLock 算法虽然是需要多个实例,但是这些实例都是独自部署的,没有主从关系。
RedLock 作者指出,之所以要用独立的,是避免了 redis 异步复制造成的锁丢失,比如:主节点没来的及把刚刚 set 进来这条数据给从节点,就挂了。
有些人是不是觉得大佬们都是杠精啊,天天就想着极端情况。其实高可用嘛,拼的就是 99.999……% 中小数点后面的位数。
回到上面那张简陋的图片,红锁算法认为,只要 (N/2) + 1 个节点加锁成功,那么就认为获取了锁,解锁时将所有实例解锁。流程为:
  1. 顺序向五个节点请求加锁
  2. 根据一定的超时时间来推断是不是跳过该节点
  3. 三个节点加锁成功并且花费时间小于锁的有效期
  4. 认定加锁成功
也就是说,假设锁 30 秒过期,三个节点加锁花了 31 秒,自然是加锁失败了。
这只是举个例子,实际上并不应该等每个节点那么长时间,就像官网所说的那样,假设有效期是 10 秒,那么单个 Redis 实例操作超时时间,应该在 5 到 50 毫秒(注意时间单位)。
还是假设我们设置有效期是 30 秒,图中超时了两个 Redis 节点。那么加锁成功的节点总共花费了 3 秒,所以锁的实际有效期是小于 27 秒的。
即扣除加锁成功三个实例的 3 秒,还要扣除等待超时 Redis 实例的总共时间。
看到这,你有可能对这个算法有一些疑问,那么你不是一个人。
回头看看 Redis 官网关于红锁的描述 [3]。
就在这篇描述页面的最下面,你能看到著名的关于红锁的神仙打架事件。
细说 Redis 分布式锁
即 Martin Kleppmann 和 Antirez 的 RedLock 辩论。一个是很有资历的分布式架构师,一个是 Redis 之父。
官方挂人,最为致命。
开个玩笑,要是质疑能被官方挂到官网,说明肯定是有价值的。
所以说如果项目里要使用红锁,除了红锁的介绍,不妨要多看两篇文章,即:
  • Martin Kleppmann 的质疑贴:http://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
  • Antirez 的反击贴:http://antirez.com/news/101

总结

看了这么多,是不是发现如何实现,都不能保证 100% 的稳定。
程序就是这样,没有绝对的稳定,所以做好人工补偿环节也是重要的一环,毕竟:技术不够,人工来凑~
相关链接:
  1. https://redis.io/commands/set
  2. https://github.com/redisson/redisson/wiki/Table-of-Content
  3. https://redis.io/topics/distlock
原文链接:https://juejin.cn/post/6844904082860146695
正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-12-03发表,共计3402字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7986197
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的 Nano Banana Pro?附赠邪修的用法 前言 大家好,我是星哥,今天来介绍谷歌的 ...
Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集 在云原生体系中,Prometheus 已成为最主流的监控与报警...
安装Black群晖DSM7.2系统安装教程(在Vmware虚拟机中、实体机均可)!

安装Black群晖DSM7.2系统安装教程(在Vmware虚拟机中、实体机均可)!

安装 Black 群晖 DSM7.2 系统安装教程(在 Vmware 虚拟机中、实体机均可)! 前言 大家好,...
多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞定

多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞定

多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞...
每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年 0.99 刀,拿下你的第一个顶级域名,详细注册使用 前言 作为长期折腾云服务、域名建站的老玩家,星哥一直...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个 AI 智能体 — 跟创业大佬对话 前言 智能体(Agent)已经成为创业者和技术人绕...
12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换...
星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

  星哥带你玩飞牛 NAS-16:不再错过公众号更新,飞牛 NAS 搭建 RSS 对于经常关注多个微...
150元打造低成本NAS小钢炮,捡一块3865U工控板

150元打造低成本NAS小钢炮,捡一块3865U工控板

150 元打造低成本 NAS 小钢炮,捡一块 3865U 工控板 一块二手的熊猫 B3 工控板 3865U,搭...
星哥带你玩飞牛NAS硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话?

星哥带你玩飞牛NAS硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话?

星哥带你玩飞牛 NAS 硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话? 前言 在选择 NAS 用预...