最近工作中要做一个秒杀系统,用户的秒杀次数、分享数、优惠券的余额等都存放在了redis中,所以需要对redis的操作保证原子性。
当然可以在服务器端做锁操作,不过更为方便的是在redis端操作。
于是想到了redis的lua脚本,lua脚本能够保证redis执行的原子性(当然如果lua脚本报错的话,无法回滚掉已执行的部分代码的)
lua学习:
redis中如果想要使用lua脚本,只需要调用eval命令即可。如果是在Java环境中,也有对应的eval(...)方法。
lua 中也分为局部变量和全局变量,不过redis为了防止数据污染,就限定了lua脚本中只允许使用局部变量
局部变量以local定义,比如:
local temp = keys[1]
eval 命令:
eval命令分为,脚本、key 数量,keys ,argv等,格式如下:
eval "local key = KEYS[1] local c = redis.call('set',KEYS[2],ARGV[1]) if key == 'a' then return c else return 1 end " 2 b a 3
"local key = KEYS[1] #定义局部变量,将外部设定的key赋值给key变量
local c = redis.call('set',KEYS[2],ARGV[1]) #将值赋值给key2 然后set到redis中,并给一个返回值
if key == 'a' then #判断传入的key
return c
else
return 1
end "
最终的返回值为1
利用lua来实现setnx并添加expire
local res ={} local key = KEYS[1] local ttl = tonumber(ARGV[1]) local k = redis.call('setnx',key,1) redis.call('expire',key,ttl) if k == 1 then res[1] = 'ok' else res[1] = 'no' end return res