【问题标题】:Redis Multi Ensuring AtomicityRedis Multi 确保原子性
【发布时间】:2017-12-01 20:41:03
【问题描述】:

如果一个命令失败,redis 中是否有办法使“多”事务中的所有命令都失败。

例如。

<?php
//using phpredis
//connection made

$redis->set('c', 1);
$res = $redis->multi()
      ->get( 'b' )
      ->get( 'c' )
      ->exec();
?>

$res 将包含 1,false。 如果其中一个命令失败,redis 中有没有办法让 $res 返回 false 并让事务失败?

【问题讨论】:

    标签: php transactions redis atomic


    【解决方案1】:

    来自transactions 上的 redis 文档:

    请务必注意,即使命令失败,所有其他命令 队列中的命令被处理——Redis 不会停止 处理命令。

    根据this 文章,redis 事务似乎仅部分涵盖了 ACID 语义,并且没有等效的回滚,尽管可以使用discard 命令中止事务。

    【讨论】:

      【解决方案2】:

      回滚和丢弃之间的真正区别是什么?例如,在 SQL Server 中,在事务中,我检查每个语句的错误,然后有条件地中止事务。

      在这里,您可以使用 Redis 的 ERR 响应作为错误条件,例如 phpredis 可以正确处理。

      以下代码以检测失败的ZADD 为例。

      $redis = new Redis();
      $redis->connect('127.0.0.1',6379);
      $redis->multi();
      $redis->set('ch1',1978); //good command
      $f = $redis->zadd('ch2',1231); //this will fail
      if (!$f) {
          $redis->discard();
          echo "Transaction aborted";
      }
      else {
          $redis->exec();
          echo "Transaction committed";
      }
      

      【讨论】:

      • Redis 只会在 EXEC 命令明显无效时返回 ERR 响应 - 语法错误、不正确的键类型等。在上面的示例中,ZADD 没有t 有第三个参数,所以它是无效的。
      【解决方案3】:

      【讨论】:

        【解决方案4】:

        没有回滚,因为它对 Redis 没有多大意义。它带来的开销太不成比例了。

        Redis 操作失败的几率太低了。来自官方文档:

        事务中的错误

        在事务期间可能会遇到两种命令错误: 一个命令可能排队失败,所以在调用 EXEC 之前可能会出错。

        例如,命令可能在语法上是错误的(参数数量错误,命令名称错误,...),或者可能存在一些严重的情况,例如内存不足的情况(如果服务器配置为具有内存限制)使用 maxmemory 指令)。

        调用 EXEC 后命令可能会失败,例如,因为我们对具有错误值的键执行了操作(例如对字符串值调用列表操作)。

        这类错误是可以预防的,可以在开发过程中发现。

        您可以在这里阅读更多信息:https://redis.io/topics/transactions

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多