我们在使用 Redis 时,不可避免地会遇到并发访问的问题,比如说如果多个用户同时下单就会对缓存在 Redis 中的商品库存并发更新。一旦有了并发写操作,数据就会被修改,如果我们没有对并发写请求做好控制,就可能导致数据被改错,影响到业务的正常使用(例如库存数据错误,导致下单异常)
常见的方式有三种
自增、自减命令 ,把 get、+1 ,set 3 个操作,封装为一个
业务场景:计数器、计时器
设置过期时间 ,把 set expire 命令封装微一个
业务场景:用户缓存、分布式锁
对于比较复杂的业务逻辑,简单的命令不可以满足,我们可以使用 lua 脚本,把多个命令封装进去执行,redis 会把 lua 脚本作为一个整体执行,执行过程不会被打断
业务场景:限制某个客户端在一定时间范围内的访问次数,比如每分钟点赞次数,爆款商品的购买限流
//获取ip对应的访问次数
current = GET(ip)
//如果超过访问次数超过20次,则报错
IF current != NULL AND current>20 THEN
ERROR "exceed 20 per second'
ELSE
//如果访问次数不足20次,增加一次访问计数
value =INCR(ip)
//如果是第一次访问,将键值对的过期时间设置为60s后
IF value == 1 THEN
EXPIRE(ip,60)
END
//执行其他操作
DO THINGS
END
这段代码如果存在a 和 b并发访问,a 访问 0 次, 加 1 ,访问0 次,加 1 ,set 过期时间 这一步就会错误,可以使用 lua 脚本放,封装这一块判断
local current
current = redis.call("incr",KEYS[1])
if tonumber(current)== lthen
redis.call("expire",KEYS[1],60)
end
执行命令
redis-cli --eval lua.script keys ,args