仅作为笔记
SETNX
SETNX KEY_NAME VALUE
在指定的 key 不存在时,为 key 设置指定的值。
返回值
设置成功,返回 1 。 设置失败,返回 0
GETSET
GETSET KEY_NAME VALUE
设置指定 key 的值,并返回 key 的旧值。
返回值
返回给定 key 的旧值。 当 key 没有旧值时,即 key 不存在时,返回 nil 。
当 key 存在但不是字符串类型时,返回一个错误。
redis执行redis脚本
参数说明
EVAL script numkeys key [key ...] arg [arg ...]
script: 参数是一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数。 numkeys: 用于指定键名参数的个数。 key [key ...]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。 arg [arg ...]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
方法一: SETNX(不推荐)
加锁(非原子):
SETNX lock <current Unix time + lock timeout>
返回 1,客户端加锁成功
返回 0,客户端加锁失败,代表key已经被设置过
GET lock
检查锁是否过期:- 没有过期则sleep一会并retry
- 如果已经过期,则尝试获取锁. 调用
GETSET lock <current Unix time + lock timeout>
基于当前时间设置过期时间.注意: 这里因为SETNX
和GETSET
之间有窗口期,所以在这个期间内有可能被别的客户端抢走锁,所以要判断GETSET
的返回值(之前设置的旧的时间戳,其实这里是有空窗期的,会导致判断GETSET
的返回值的时候,虽然是过期的,同时别的客户端也会判断是过期的)
- 若旧的时间戳已经过期,则代表加锁成功
- 若还未过期(说明这期间被其他客户端抢占并更新了时间戳),加锁失败,需要等待重试
解锁(非原子):
GET lock
判断是否过期,过期则DEL lock
(但是GET
和DEL
之前的空窗期可能别的锁已经获得锁了,在这里调用DEL
则在别的客户端不知情的情况下解除锁的占用)
方法二: SET NX PX
加锁(原子):
SET key unique_value NX PX 1000
时间单位毫秒,只有在key
不存在才会执行成功 (unique_value是唯一的,保证自己的锁只能自己释放)
解锁(原子):
eval "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 key unique_value
if redis.call('get',KEYS[1]) == ARGV[1] then
return redis.call('del',KEYS[1])
else
return 0
参数为 1 key random_value