【Redis】Redis常见面试题(1)
文章目录
- 【Redis】Redis常见面试题(1)
- 1. 为什么要用分布式锁
- 2. Redis如何实现分布式锁
- 3. Redis接受多个请求模拟演示
- 4. 使用Redis实现分布式锁会存在什么问题
- 4.1 一个锁被长时间占用
- 4.2 锁误删
之前学到的锁,在分布式,微服务是不适用的,因为之前的锁针对的是本地线程,而分布式是跨机器的
而Redis作为一个独立的三方系统,其天生的优势就是可以作为一个分布式系统来使用,因此使用Redis实现的锁都是分布式锁!
Redis实现分布式锁可以通过setnx(set if not exists)命令实现,当我们使用setnx创建键值成功则表明加锁成功,否则即加锁失败(需要等待锁释放,自旋/挂起等等…);del删除键值,表示锁释放
获得锁:
127.0.0.1:6379> setnx lock1 true
再次获得这把锁:
就是个普通键值对~
释放锁
127.0.0.1:6379> del lock1
再次释放锁:
那么我们用两个命令行操作redis,模拟两个线程,讲解Redis分布式锁的一些相关问题
- 白
- 黑
两个命令行“同时”尝试获取锁,总有一个会获取到锁
黑色命令行选择自旋等待锁:
直到白色命令行释放锁:
黑色命令行才获取到锁:
怎么处理:
setnx 和 expire搭配使用,不太好,因为这样这条语句就是非原子性的,如果超时时间设置上之前奔溃了,依旧解决不了问题
Redis 2.6.12 版本之后,提供了一个强大的功能,可以让这个操作是原子操作:
127.0.0.1:6379> set lock true ex 30 nx
由于这个键值对是公共可见的,所以一个线程是可以释放别的线程的锁的!从代码上我们不会出现刻意的删除别的线程的锁的恶劣行为,但是会有一些不可避免的偶然事件场景下,会出现这个问题:
这有点像,ABA的问题,参考此文章的aba模块:【JavaEE】多线程进阶问题-锁策略and死锁,CAS操作,Synchronized原理_s:103的博客-CSDN博客
解决方法与之类似,(添加一个属性:一个标识或者版本号),保证释放锁是自己刚才抢到的锁!
白色线程设置white,黑色线程设置black
也就是刚才的第四步,白色线程在释放锁之前,进行判断锁的归属:
ok,白色线程知道了,不能释放
但是并不是完全没有问题,这个操作是两步的,非原子性操作!
解决方案:
感兴趣的同学可以自行学习:
Redisson · GitHub
文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭!