【问题标题】:StackExchange Redis AddOrUpdate handling (optimistic concurrency)StackExchange Redis AddOrUpdate 处理(乐观并发)
【发布时间】:2019-02-19 17:03:20
【问题描述】:

我正在尝试使用 StackExchange.Redis 来实现事务添加或更新逻辑。我查看了 GitHub 上的 https://stackexchange.github.io/StackExchange.Redis/Transactions.html 示例,但这指的是“如果不存在则添加”过程,这实际上只是故事的一部分。

我的要求是“如果缓存项不存在则添加,如果没有更改则更新”(即乐观并发)。这个例子对https://github.com/StackExchange/StackExchange.Redis/issues/885 有帮助,但它只使用一个条件,就像 Github 上的交易示例一样。

我对 redis 事务的测试表明您不能添加多个条件,因此这种方法似乎有效:

            var committed = await _redisDatabase.StringSetAsync(key, value, expiry, When.NotExists, flags);
            if (committed)
            {
                return committed;
            }

            var txn = _redisDatabase.CreateTransaction();

            txn.AddCondition(Condition.StringEqual(key, value));
            txn.StringSetAsync(key, value, expiry, when, flags);

            committed = await txn.ExecuteAsync();

            return committed;

即假设它不存在,如果存在则尝试更新...总是需要调用When.NotExists,因为第二部分可能会失败,因为对象已更改或它不存在..所以您需要第一次调用你知道第二个由于过时而失败。

这会在第一次调用时生成一个 SETNX,然后是附加的 WATCH、GET、MULTI 和 SET 命令....是否可以将其组合到一个 Redis 事务中?

【问题讨论】:

    标签: .net stackexchange.redis


    【解决方案1】:

    坦率地说,您可能更喜欢 Lua (EVAL/EVALSHA) 而不是事务 (MULTI/EXEC)。这也很容易使用 - 例如,这是一个只递增键的哈希(从不递减),或者如果它丢失则创建新的哈希条目:

    var keys = new RedisKey[] { key };
    var values = new RedisValue[] { subscriptionId, lastUpdate };
    
    _redis.GetDatabase(db).ScriptEvaluate(@"
    if redis.call('hsetnx', KEYS[1], ARGV[1], ARGV[2]) == 0 then
      local old = redis.call('hget', KEYS[1], ARGV[1])
      if tonumber(old) < tonumber(ARGV[2]) then
        redis.call('hset', KEYS[1], ARGV[1], ARGV[2])
      end
    end", keys, values);
    

    还有一个替代 API,它与一些帮助器做同样的事情,使它看起来更像 SQL,但我更喜欢上面带有 KEYSARGV 的版本,因为我可以直接通过 redis-cli 测试它。

    您的版本可以做类似的事情,但在调用 set 之前在 Lua 中测试旧的预期值。

    解释一下:这里的'hsetnx' 设置散列值,如果它已经存在;如果失败 (== 0),那么我们获取现有值,比较它,如果需要,最后调用 hset

    有关详细信息:请参阅EVAL 文档。如果您需要取回值,ScriptEvaluate API 也可以处理 return 语义。

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      • 2012-10-15
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多