redis原子命令和 lua 脚本解决并发问题

目录

      • 使用单命令原子操作
        • incr、decr
        • setex
      • 使用 lua 脚本封装复杂命令微原子操作

我们在使用 Redis 时,不可避免地会遇到并发访问的问题,比如说如果多个用户同时下单就会对缓存在 Redis 中的商品库存并发更新。一旦有了并发写操作,数据就会被修改,如果我们没有对并发写请求做好控制,就可能导致数据被改错,影响到业务的正常使用(例如库存数据错误,导致下单异常)

常见的方式有三种

使用单命令原子操作

incr、decr

自增、自减命令 ,把 get、+1 ,set 3 个操作,封装为一个
业务场景:计数器、计时器

setex

设置过期时间 ,把 set expire 命令封装微一个
业务场景:用户缓存、分布式锁

使用 lua 脚本封装复杂命令微原子操作

对于比较复杂的业务逻辑,简单的命令不可以满足,我们可以使用 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

你可能感兴趣的:(#,Redis,redis,lua,数据库)