redis 分布式式加锁
假的
先 通过redis template get lock
如果为空 再通过set 操作给 lock 加锁也就是存上一个key
这种会导致 两次操作redis 如果线程并发的时候会有延迟lock状态
也就是多个线程get lock 的时候 setlock 还未成功。导致lock 失效
正确的方法是
使用redis 的原子操作 也就是setnx key value redistemplate 的是 setifabsent 方法
这个的好处是 一步操作 就可以 将key set到reids中并且可以知道当前key是否之前就存在 也就是说之前的
if(get(lock))
set(lock)
eles
doing
改为
if(setifabsent(lock))
doing
这样利用redis的高性能可以实现分布式锁
这样操作也会有一个问题 就是由于系统异常到导致最终没有执行finally 中的delete lock
导致死锁的问题
这种问题 需要在setifabsent 中添加过期时间 来解决 如果超时未释放资源 redis 自动释放
但这种有回导致另一个问题
就是业务未执行成功的时候 redis的lock 已经被释放了 那么lock失效 引发并发问题
解决这种问题有两种思路
- 一种就是与业务和技术讨论设置一个最大过期时间
- 另一种就是通过使用守护线程 daemon thread 来守护lock的过期时间 入还有一秒过期就自动延长五秒
推荐使用第二种 那么守护线程是什么呢?什么时候关闭 什么时候创建呢? - 守护线程 也就是一个线程 以线程的创建方式创建 但值得注意的是 它的生命周期是由被守护的线程执行状态来确定的 所以可以使用while(true)的方式 守护其运行状态(其中可设定一定时间的sleep),并且暴露其stop方法可以调用停止运行
- 守护线程的创建时机 在被守护线程创建