Redis原子操作

发布时间 2023-11-20 16:03:34作者: kiper

Redis命令的原子操作

redis虽然是单线程,但是一个客户端发送的一组命令却不是原子操作。

redis自带的原子操作命令有incr {key}、decr {key}等,但是更为复杂的命令,比如先获取值,然后乘以2,最后置为新值这三步操作,有可能中间会有其他客户端的命令插入导致值已经变化,出现并发问题。

可以利用LUA脚本解决这个问题,比如常见的判断分布式锁是否为当前客户端的锁,判断成功才进行释放操作。

if redis.call('get',KEYS[1])==ARGV[1]
then
    return redis.call('del',KEYS[1])
else
    return 0
end

利用Redis实现的分布式锁

JDK自带的锁只锁协调一个实例中的临界区并发调用,但是分布式锁可以跨越实例上的限制。利用Redis天生单线程执行命令的特性,可以很简单的实现分布式锁。

首先获取一个随机的字符串作为锁的值,并利用原子命令set {key} {val} nx ex {time}同时设置值和过期时间即可。需要释放锁的时候,利用前文中的LUA脚本完成锁的释放操作。

LUA脚本中判断值是为了避免这样一种情况,线程A执行时卡顿了,导致A加的锁过期自然解锁,此时线程B重新加锁后,线程A继续执行,把线程B的锁给释放掉了。通过加锁时赋予一个独一的随机值,可以避免这种情况的发生。