一、分布式锁
本质就是实现一个线程在 Redis 中占坑, 用完了,再 del 释放坑
问题1: 程序出现异常, 导致 del 指令未被调用
解决1: 设置一个过期时间
问题2:expire 得不到执行,导致死锁
解决2:
最初:使用 Redis 社区提供分布式锁
最终: Redis 2.8 版本中加入了 set 指令的扩展参数,使得 setnx 和 expire 指令可以一起执行
set lock:codehole true ex 5
问题3:超时问题,未执行完,就释放锁了
解决3: 较长时间的任务,不用 Redis 分布式锁
为 set 指令的 value 设置随机数,释放锁时匹配随机数是否一致 (匹配和删除不是原子操作,需要使用 Lua 脚本)
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
二、可重入性
可重入性:线程在持有锁的情况下再次请求加锁( ReentrantLock)。
Redis 分布式锁实现可重入 : 对客户端的 set 方法进行包装,使用线程的 Threadlocal 变量存储当前持有锁的计数。
不推荐在客户端实现使用可重入锁,它加重了客户端的复杂性
在编写业务方法时注意在逻辑结构上进行调整就可以,如下: