predis事务的使用

场景:设置一个key并且使用expireat命令设置过期时间,最好保证其操作的原子性。

打算使用redis的事务(Redis::transaction()方法)来保证多条命令执行的原子性,却引发了错误: Predis\NotSupportedException: Cannot initialize a MULTI/EXEC transaction over aggregate connections

产生的原因,这里描述的很清楚:

github.com/predis/pred…

大体的意思就是:使用了集群,又涉及了多个键的事务,但是这多个键不具有相同的哈希标签,由此会分发到不同的redis节点处理,导致出现该问题。

解决办法:

使用lua脚本来把多条命令包含进去,lua脚本的执行,redis是保证其原子性操作。

下面是一个示例(设置值并同时设置过期时间,php代码):

$lua = <<< 'LUA'
            -- local为声明局部变量
            local key,value,time = KEYS[1],ARGV[1],ARGV[2]
            
            redis.call("set", key, value)
            
            local result = redis.call("expireat", key, time)

            return result
LUA;

        Redis::eval($lua,1,’test_key‘,'test_value','2021-11-09 22:21:14');
复制代码

版本

  • laravel 5.5.50
  • predis 1.1.1
  • redis 5.0.3