现在?试,?般都会聊聊分布式系统这块的东?。通常?试官都会从服务框架(Spring Cloud、Dubbo)聊起,?路聊到分布式事务、分布式锁、ZooKeeper 等知识。
所以咱们这篇?章就来聊聊分布式锁这块知识,具体的来看看 Redis 分布式锁的实现原理。
说实话,如果在公司?落地?产环境?分布式锁的时候,?定是会?开源类库的,?如 Redis分布式锁,?般就是? Redisson 框架就好了,?常的简便易?。
?家如果有兴趣,可以去看看 Redisson 的官?,看看如何在项?中引? Redisson 的依赖,然后基于 Redis 实现分布式锁的加锁与释放锁。
下?给?家看?段简单的使?代码?段,先直观的感受?下:
```java
RLock rlock = redission.getLock("mylock");
rlock.lock();
rlock.unlock();
怎么样,上?那段代码,是不是感觉简单的不?!
此外,?家还?持 redis 单实例、redis 哨兵、redis cluster、redis master-slave 等各种部署架构,都可以给你完美实现。
为啥要? lua 脚本呢?
因为??坨复杂的业务逻辑,可以通过封装在 lua 脚本中发送给 redis,保证这段复杂业务逻辑?的原?性。
那么,这段 lua 脚本是什么意思呢?
KEYS[1] 代表的是你加锁的那个 key,?如说:
RLock lock = redisson.getLock(“myLock”);
这?你??设置了加锁的那个锁 key 就是 “myLock”。
ARGV[1] 代表的就是锁 key 的默认?存时间,默认 30 秒。
ARGV[2] 代表的是加锁的客户端的 ID,类似于下?这样:
8743c9c0-0795-4907-87fd-6c719a6b4586:1
给?家解释?下,第?段 if 判断语句,就是? “exists myLock” 命令判断?下,如果你要加锁的那个锁 key 不存在的话,你就进?加锁。
如何加锁呢?很简单,?下?的命令:
hset myLock 8743c9c0-0795-4907-87fd-6c719a6b4586:1 1
上述就代表 “8743c9c0-0795-4907-87fd-6c719a6b4586:1” 这个客户端对 “myLock” 这个锁key 完成了加锁。
接着会执? “pexpire myLock 30000” 命令,设置 myLock 这个锁 key 的?存时间是 30 秒
(2)锁互斥机制
那么在这个时候,如果客户端 2 来尝试加锁,执?了同样的?段 lua 脚本,会咋样呢?
很简单,第?个 if 判断会执? “exists myLock” ,发现 myLock 这个锁 key 已经存在了。
接着第?个 if 判断,判断?下,myLock 锁 key 的 hash 数据结构中,是否包含客户端 2 的 ID,
但是明显不是的,因为那?包含的是客户端 1 的 ID。
所以,客户端 2 会获取到 pttl myLock 返回的?个数字,这个数字代表了 myLock 这个锁
key 的剩余?存时间。?如还剩 15000 毫秒的?存时间。
此时客户端 2 会进??个 while 循环,不停的尝试加锁。
(3)watch dog ?动延期机制
客户端 1 加锁的锁 key 默认?存时间才 30 秒,如果超过了 30 秒,客户端 1 还想?直持有这把锁,怎么办呢?
简单!只要客户端 1 ?旦加锁成功,就会启动?个 watch dog 看?狗,他是?个后台线程,会每隔 10 秒检查?下,如果客户端 1 还持有锁 key,那么就会不断的延?锁 key 的?存时间。
(4)可重?加锁机制
那如果客户端 1 都已经持有了这把锁了,结果可重?的加锁会怎么样呢?
第?个 if 判断肯定不成?, “exists myLock” 会显示锁 key 已经存在了。
第?个 if 判断会成?,因为 myLock 的 hash 数据结构中包含的那个 ID,就是客户端 1 的那个ID,也就是 “8743c9c0-0795-4907-87fd-6c719a6b4586:1”此时就会执?可重?加锁的逻辑,他会?:incrby myLock 8743c9c0-0795-4907-87fd-6c71a6b4586:1 1通过这个命令,对客户端 1 的加锁次数,累加 1。
(5)锁释放机制
如果执? lock.unlock() ,就可以释放分布式锁,此时的业务逻辑也是?常简单的。
其实说?了,就是每次都对 myLock 数据结构中的那个加锁次数减 1。
如果发现加锁次数是 0 了,说明这个客户端已经不再持有锁了,此时就会?:
“del myLock” 命令,从 redis ?删除这个 key。
然后呢,另外的客户端 2 就可以尝试完成加锁了。
这就是所谓的分布式锁的开源 Redisson 框架的实现机制。
?般我们在?产系统中,可以? Redisson 框架提供的这个类库来基于 redis 进?分布式锁的加锁与释放锁。
(6)此种?案 Redis 分布式锁的缺陷
其实上?那种?案最?的问题,就是如果你对某个 redis master 实例,写?了 myLock 这种锁key 的 value,此时会异步复制给对应的 master slave 实例。
但是这个过程中?旦发? redis master 宕机,主备切换,redis slave 变为了 redis master。
接着就会导致,客户端 2 来尝试加锁的时候,在新的 redis master 上完成了加锁,?客户端 1也以为??成功加了锁。
此时就会导致多个客户端对?个分布式锁完成了加锁。
这时系统在业务语义上?定会出现问题,导致各种脏数据的产?。
所以这个就是 redis cluster,或者是 redis master-slave 架构的主从异步复制导致的 redis 分布式
锁的最?缺陷:在 redis master 实例宕机的时候,可能导致多个客户端同时完成加锁。
下一篇我们聊聊 zookeeper实现分布式锁
Servlet中操作文件详解及实例 因为Servlet本来就是一个.Java文件,因此servlet中...
2月15日消息,据媒体报道,微软似乎正致力于新的电池管理页面改进,使得该页面支...
redis常用命令有: 1、连接操作命令; 2、持久化命令; 3、远程服务控制命令; 4...
本文转载自微信公众号「码农读书」,作者码农读书 。转载本文请联系码农读书公众...
声明由于作者水平有限本文难免有错误和不准确之处本人也很想知道这些错误恳望读...
对简单应用,可采用JSP+BAEN,对复杂的应用系统,应采用JSP+EJB,SERVLET变的无...
VSCode 创建一个插件,如何创建一个插件,VS Code 的插件既然是一个 Node.js 应...
使用Ajax可以异步获取数据,可以更高效地渲染页面。 但也存在这一些问题: 再刷...
本章目录 1.面向过程和面向对象的初步认识 2.类的引入 3.类的定义 4.类的访问限...
近日一则短视频在手机圈内非常火内容是关于对honor荣耀CEO赵明的采访。视频中赵...