// lua 脚本编写
// 加锁操作 如果锁不存在或者当前请求锁的uuid字段存在 则进行加一 (重入性)
KEYS[1] // -- 分布式锁的key
ARGV[1] // -- 锁的唯一标识,通常是线程ID或调用者标识
ARGV[2] // -- 锁的过期时间,单位为毫秒
if redis.call('exists', KEYS[1]) == 0 //锁不存在
or redis.call('hexists', KEYS[1], ARGV[1]) == 1 // 当前请求有锁 进入函数(或新开线程)无需额外申请锁
then
redis.call('hincrby',KEYS[1], ARGV[1], 1)
redis.call('expire',KEYS[1], ARGV[2])
return true
else
return false
end
//解锁操作
if redis.call("hexists",KEYS[1], ARGV[1]) == 0 then // 无锁 无需解锁
return false
else if redis.call("hincrby",KEYS[1], ARGV[1], -1) == 0 then // 锁存在且是自己请求的锁 进行减一操作,如果减为0 则解锁(删key)
retrun redis.call("DEL",KEYS[1])
else
return 0
本文是基于redis缓存实现分布式锁,其中使用了setnx命令加锁,expire命令设置过期时间并lua脚本保证事务一致性。Java实现部分基于JIMDB提供的接口。
这一篇文章拖了有点久,虽然在项目中使用分布式锁的频率比较高,但整理成文章发布出来还是花了一点时间。在一些移动端、用户量大的互联网项目中,经常会使用到 Redis 分布式锁作为控制访问高并发的工具。