简单锁 采用键值对存储,键是锁的标识,值是全局唯一值(如uuid)。
获取锁 1 2 3 4 5 6 7 8 9 10 11 12 13 14 local key = KEYS[1 ] local value = ARGV[1 ] local ttl = tonumber (ARGV[2 ]) or 0 if (redis.call('setnx' , key, value) == 1 ) then if (ttl > 0 ) then redis.call('expire' , key, ttl) end return 1 end return 0
释放锁 1 2 3 4 5 6 7 8 9 10 11 local key = KEYS[1 ] local value = ARGV[1 ] if (redis.call('get' , key) == value) then redis.call('del' , key) return 1 end return 0
运行效果 将获取锁和释放锁的代码分别保存到lock_aquire.lua和lock_release.lua文件。
1 2 $ vi lock_aquire.lua $ vi lock_release.lua
将两个lua脚本文件加载到redis中,分别返回一个sha值。
1 2 3 4 $ redis-cli script load "$(cat lock_aquire.lua) " "cc5c8c3fe44fb651fb06e4c39300749ced0ae22b" $ redis-cli script load "$(cat lock_release.lua) " "c6a18bc663c9d324644615321834667b914b8350"
在redis客户端中执行evalsha命令,传入步骤2生成的sha值。
1 2 3 4 5 6 7 8 redis> evalsha cc5c8c3fe44fb651fb06e4c39300749ced0ae22b 1 dist_lock 111111 (integer ) 1 redis> evalsha cc5c8c3fe44fb651fb06e4c39300749ced0ae22b 1 dist_lock 222222 (integer ) 0 redis> evalsha c6a18bc663c9d324644615321834667b914b8350 1 dist_lock 111111 (integer ) 1 redis> evalsha cc5c8c3fe44fb651fb06e4c39300749ced0ae22b 1 dist_lock 222222 (integer ) 1
可重入锁 采用Hash结构存储,只有一个字段,字段的键是全局唯一值(如uuid),代表锁的拥有者,字段的值是个计数器。每获取一次锁计数器加1,每释放一次锁计数器减1,当计数器减为0时删除锁。
获取锁 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 local key = KEYS[1 ] local value = ARGV[1 ] local ttl = tonumber (ARGV[2 ]) or 0 if (redis.call('exists' , key) == 0 ) then redis.call('hincrby' , key, value, 1 ) if (ttl > 0 ) then redis.call('expire' , key, ttl) end return 1 end if (redis.call('hexists' , key, value) == 1 ) then redis.call('hincrby' , key, value, 1 ) return 1 end return 0
释放锁 1 2 3 4 5 6 7 8 9 10 11 12 13 14 local key = KEYS[1 ] local value = ARGV[1 ] if (redis.call('hexists' , key, value) == 1 ) then if (redis.call('hincrby' , key, value, -1 ) < 1 ) then redis.call('del' , key) end return 1 end return 0
运行效果 将获取锁和释放锁的代码分别保存到lock_aquire.lua和lock_release.lua文件。
1 2 $ vi lock_aquire.lua $ vi lock_release.lua
将两个lua脚本文件加载到redis中,分别返回一个sha值。
1 2 3 4 $ redis-cli script load "$(cat lock_aquire.lua) " "464f5e1f5a94422063a0ed087e4e545dd7786d07" $ redis-cli script load "$(cat lock_release.lua) " "f33de5bbd21fcb322e226d1ebcb5a6fdd51f4f2f"
在redis客户端中执行evalsha命令,传入步骤2生成的sha值。
1 2 3 4 5 6 7 8 9 10 11 12 redis> evalsha 464f5e1f5a94422063a0ed087e4e545dd7786d07 1 dist_lock 111111 (integer ) 1 redis> evalsha 464f5e1f5a94422063a0ed087e4e545dd7786d07 1 dist_lock 222222 (integer ) 0 redis> evalsha 464f5e1f5a94422063a0ed087e4e545dd7786d07 1 dist_lock 111111 (integer ) 1 redis> evalsha f33de5bbd21fcb322e226d1ebcb5a6fdd51f4f2f 1 dist_lock 111111 (integer ) 1 redis> evalsha f33de5bbd21fcb322e226d1ebcb5a6fdd51f4f2f 1 dist_lock 111111 (integer ) 1 redis> evalsha 464f5e1f5a94422063a0ed087e4e545dd7786d07 1 dist_lock 222222 (integer ) 1
参考链接