首页 > 解决方案 > Redis C# - 在事务中使用 Incr 值

问题描述

我正在尝试使用 Redis INCR 并将增量值用作 C# 中使用 StackExchange.Redis 的哈希中的字段。这个问题与我需要的类似,但在 Node.js 中。

下面是我需要的东西。

            ITransaction transation = m_connection.GetDatabase()
                                                  .CreateTransaction();
            Task<long> incrementTask = transation.StringIncrementAsync(sequenceNumberRedisKey);


            if (await transation.ExecuteAsync())
            {
                long sequenceNumber = await incrementTask;
                await transation.HashSetAsync(responseRedisKey, sequenceNumber, response);
            }

请注意,这sequenceNumber是我打算在事务中执行的第一个操作的结果。

代码似乎在我执行任何操作之前就执行并提交了事务。

  1. 这是在一个事务中执行多个操作的方式吗?
  2. 这是我可以在操作 2 (HashSetAsync) 中使用操作 1 (StringIncrementAsync) 的结果的方式吗?
  3. 如果 HashSetAsync 返回 false,如何回滚序列号增量?
  4. 为什么没有明确的提交?

标签: c#redisstackexchange.redis

解决方案


redis MULTI/EXEC 单元有一个基本特性,这意味着您在操作期间无法获得结果。因此,有两种常见的方法可以满足您的要求:

  1. 使用 Lua ( ScriptEvaluate[Async]); Lua 脚本在服务器上从头到尾执行,高效,并避免与往返时间(延迟或带宽)或来自其他连接的竞争相关的所有问题
  2. 使用一个读取当前值的乐观循环,然后在 SE-Redis 中创建一个事务,添加一个你刚刚读取的值相同的约束,并在事务内部执行副作用;库将协调必要的 WATCH 等机制以使其健壮,但如果约束条件无效(即库返回false),您需要从头开始重做所有事情

坦率地说,这些天我总是会引导人们选择选项 1;如果服务器端 Lua 脚本不可用,选项 2 只是“吸引人”(我使用该术语完全不正确)。

我不在 PC 上,但我猜脚本看起来像:

local id = redis.call("incr", KEYS[1])
redis.call("hset", KEYS[2], tostring(id), ARGV[1])
return id

推荐阅读