【问题标题】:Redis C# - Using Incr value in a transactionRedis C# - 在事务中使用 Incr 值
【发布时间】:2020-09-19 14:54:14
【问题描述】:

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

下面是我需要的东西。

            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# redis stackexchange.redis


    【解决方案1】:

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

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

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

    我不在电脑前,但我猜脚本看起来像:

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

    【讨论】:

    • 这里的最佳做法是什么?是否有可以在 .NET Core 应用程序中用于将 C# 写入 Lua 的库?我在哪里保存脚本。我可以像存储过程一样将它写入 Redis/
    • @JinsPeter 上面显示的方法应该做到这一点;该库处理所有SCRIPT LOAD 等语义,因此它不会每次都发送整个正文。如果您自己处理负载(不推荐,由于卸载问题):库检测您是否正在发出 SHA 哈希,并做出相应反应。这是 redis 文档:redis.io/commands/eval - 您只需将脚本和键/值传递给 ScriptEvaluate
    • @MarkGravell 我使用 StackExchange.Redis 作为我的 redis 库。而上面的 lua 脚本正是我需要的。但是从应用的角度来看。所以你推荐EVAL(LuaScript.ScriptEvaluate)而不是EVALSHA(LoadedLuaScript.ScriptEvaluate)?从评论看不是很清楚
    • @JinsPeter 是的,这看起来确实有点不完整,以至于它可能会误导; 实际上发生的是:如果脚本字符串一个SHA,它直接使用EVALSHA;否则,库会跟踪它知道的脚本——如果它认为没有加载脚本,则库(如果可以,并非总是如此)自动发出 SCRIPT LOAD;一旦确认,它将使用 EVALSHA - 直到那时:EVAL。它还检测到来自 EVALSHA 的错误,表明它已被卸载,并重新发出 SCRIPT LOAD 等。
    • @JinsPeter 或更简单地说:图书馆让它“正常工作”:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 2014-01-10
    • 1970-01-01
    • 2019-11-01
    • 2019-01-01
    • 1970-01-01
    相关资源
    最近更新 更多