Redis分布式锁——分析篇
大家好! 写这篇博客的目的是分析一下Redis分布式锁的使用,做到知其然知其所以然。
The real target is that I was asked the Redis锁 usage in the interview. And I cann’t answer it.
真正目的是因为在面试中被问到多线程这块怎么实现的,当时只是看了下代码是用Redis锁实现的,至于具体的细节。自己回答的都感觉脸红。
【一】What is the Redis Distribute Lock 什么是Redis分布式锁
锁:
个人理解:在一定时间内对某个对象某个事物某个空间拥有使用权所有权的保证。
百度百科:
例证:
咱们大家上厕所时,都要讲厕所门上的插销插上。此时这个插销就代表了使用当前这个厕所的锁。这个厕所目前由你独享,其他人不可进入。
Java中的锁的存放位置:
常用的锁:
偏向锁、轻量级锁、重量级锁、自旋锁、读写锁、公平非公平锁…
以及一些无锁操作:volatile、CAS …
以上所说的这些锁是保证在同一个JVM中里的各个线程对共享资源的互斥。
当有多个JVM时,上面的锁保证不了互斥。比如订单服务部署在5台服务器上,服务器A的线程a与服务器B上的线程b同时下订单,此时上面的锁就保证不了互斥了。
eg:
场景1:两人都要上厕所(小灰和小白),小白走到厕所门口,发现门开着,直接就进去并锁上门。小灰有点肚子痛,只有一个厕所,只能等待,不巧的是,小白有点头晕,昏过去了。小灰陷入了无比痛苦的等待中!!!
场景2:这个场景需要充分假设:A任务未执行完,锁到期了,B任务获得执行时间,A执行完,进行解锁操作(其实删的是B的锁)
场景3:保证任务执行时间大于锁有效时间。继续回到上厕所中,电子锁加了红外感应。在每次锁到期的时候,红外感应会看看当前还有没有人在,有的话,锁继续延迟;没有的话,则自动释放锁。
分布式锁就是为了解决上述场景123而生。
实现:
- 数据库
- Memcached(add命令)
- Redis(setnx命令)
- Zookeeper(临时节点)
- 等等
【二】How can we use the Redis Lock 我们如何使用它
场景1:通过加锁的有效时间解决。
场景2:通过加请求ID解决谁上的锁谁来解
场景3:通过延长锁的有效期解决
具体代码片段可移步至此:
博客:添加链接描述
GitHub:添加链接描述
【说明一】
:if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('expire',KEYS[1],ARGV[2])
else return 0 end
这段脚本当在Redis库中能查到值,正面业务还在执行,此时就需要将锁进行延时。
【说明二】
【三】Why use the Redis Lock 为什么使用Redis分布式锁
- 解决了多JVM下的数据的同步问题。
具有以下特性:
- 互斥性:在任意一个时刻,只有一个客户端持有锁。
- 无死锁:即便持有锁的客户端崩溃或者其他意外事件,锁仍然可以被获取。
- 容错:只要大部分Redis节点都活着,客户端就可以获取和释放锁
参考文章:
小灰讲什么是分布式锁?
redis系列:基于redis的分布式锁
周志明大大的《深入理解JVM》