StackExchange.Redis: 关于交易的几个问题

StackExchange.Redis: couple of questions about transactions

我有几个关于使用来自 StackExchange.Redis:

的交易的问题
  1. 是否允许在事务中执行可能针对集群环境中不同节点的命令?比如说,第一个命令的键有 {1} 主题标签,第二个命令的键有 {2} 主题标签。
  2. 交易的Execute()/ExecuteAsync()return什么时候false?仅当不满足设定条件时?不设置条件可以returnfalse吗?
  3. 如果发生某些网络或内部 Redis 错误,Execute()/ExecuteAsync() 会抛出还是只是 return false?我还应该检查命令的任务(假设命令完全正确并且通常不会抛出)还是它们会被取消?

遗憾的是the doc没有详细解释#2和#3。

  1. "Redis Cluster implements all the single key commands available in the non-distributed version of Redis. Commands performing complex multi-key operations like Set type unions or intersections are implemented as well as long as the keys all belong to the same node." https://redis.io/topics/cluster-spec

您不能使用多簇键发送多键操作。

  1. "交易过程中可能遇到两种命令错误:

命令可能无法排队,因此在调用EXEC之前可能会出错。例如,该命令可能在语法上是错误的(参数数量错误,命令名称错误,...),或者可能存在一些临界条件,如内存不足条件(如果服务器配置为使用 maxmemory 具有内存限制指令)。

调用 EXEC 后命令可能会失败,例如,因为我们对具有错误值的键执行操作(例如对字符串值调用列表操作)。" https://redis.io/topics/transactions

  1. 在 .Net 中,当你 运行 一个任务时,如果在其中抛出一个未处理的异常 - 它不会在任务之外冒泡,除非你使用 taskInstance.Wait() - 然后你会得到一个AggregateException 并需要检查 InnerExceptions 以了解实际异常。

我深入研究了 StackExchange.Redis 源代码并试用了驱动程序,以下是我的观察结果:

  • ITransaction 个实例上调用 op 方法时没有实际交互发生
  • 驱动程序仅在您调用 Execute()/ExecuteAsync()
  • 时才开始与 Redis 通信

答案似乎如下:

  1. 正如@royi-mindel 提到的,交易中的所有密钥必须指向同一个插槽。否则你会得到 "Multi-key operations must involve a single slot" 异常。
  2. Execute()/ExecuteAsync() returns false 在两种情况下:当事务因为不满足条件而被丢弃时,当驱动程序无法将命令排队时(例如因为服务器 OOM)。所有命令任务都将标记为已取消。另外 Execute()/ExecuteAsync() 不会 return false 如果其中一个命令在执行过程中失败(例如,由于类型错误操作)。
  3. 万一出现网络问题,Execute()/ExecuteAsync()会抛出异常,所有命令任务会保持在"waiting for activation"状态。

总而言之,只有在 Execute()/ExecuteAsync() returned true 时才应检查命令任务:每个任务都将包含结果或错误(参见 Exception 属性)。