JAVA 面试总结-Redis分布式锁
- 模拟抢券场景
- 通过下面方法添加Synchronized锁来防止上述情况,
- 如果上面是单体服务没有问题,但是如果项目是集群部署,会出现下面的问题,因为Synchronized是属于本地的锁
- 端口8080和8081同时访问,那么两个线程会同时加锁
- 这时候我们需要用分布式锁
- Redis 分布式锁实现原理
- Redis实现分布式锁如何合理的控制锁的有效时长?
- 1.根据业务执行时间预估,2.给锁续期,但是第一种根据业务执行的时间预估依然可能会出现问题,所以我们采用第二种方案给锁续期,但是我们要自己再开一个线程一直关注这个锁吗?Redis 分布式锁就可以实现
- 加锁,设置过期时间等操作都是基于lua脚本完成
- 主从一致性
- 红锁
模拟抢券场景
通过下面方法添加Synchronized锁来防止上述情况,
如果上面是单体服务没有问题,但是如果项目是集群部署,会出现下面的问题,因为Synchronized是属于本地的锁
端口8080和8081同时访问,那么两个线程会同时加锁
这时候我们需要用分布式锁
8080端口在进行线程1的时候,进行加锁,此时8081的进行访问的时候获取互斥锁失败,可以保证数据一致
Redis 分布式锁实现原理
为什么要设置过期时间?如果不设置过期时间的话,有可能导致死锁的问题。
Redis实现分布式锁如何合理的控制锁的有效时长?
1.根据业务执行时间预估,2.给锁续期,但是第一种根据业务执行的时间预估依然可能会出现问题,所以我们采用第二种方案给锁续期,但是我们要自己再开一个线程一直关注这个锁吗?Redis 分布式锁就可以实现
下面这个线程加锁成功的话,跟上面的流程是一样的,如果加锁不成功,就会循环,不断尝试获取锁,但是也不会一直循环,有设置阈值,循环次数达到阈值就会停止
具体代码:
加锁,设置过期时间等操作都是基于lua脚本完成
add1 方法加锁 ,Value.value = 1, 之后调用add2 方法加锁,Value.value = 2, add2 释放锁 Value.value-1变成1 ,之后add1 释放锁 Value.value-1变成0
只有同一个线程才会重入
主从一致性
假如现在在写入数据到主节点,这时候主节点宕机了,会有一个从节点变成主节点,当有请求来了,继续写入数据,也会尝试获取锁,因为之前的数据没同步过来,这时候就会造成两个线程同时持有同一把锁,但是这样就没有互斥性了,业务还在执行就可能会产生脏数据,因此在Redis中还提供了另外一种锁——红锁
红锁
其中 n 代表redis中节点的数量,创建锁的个数要大于等于节点的一半才行,来解决主从不一致的问题,但是这种方法实现复杂,性能查并且运维繁琐。
Redis 的思想是AP思想,保证数据最终一致,但是如果必须保证完全实时一致,就需要用CP思想,用zookeeper