gpt4 book ai didi

.net - StackExchange Redis AddOrUpdate 处理(乐观并发)

转载 作者:行者123 更新时间:2023-12-05 06:27:59 25 4
gpt4 key购买 nike

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

我的要求是“如果缓存项不存在则添加,如果未更改则更新”(即乐观并发)。这个例子帮助了 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 事务中?

最佳答案

坦率地说,您可能更喜欢 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 语义。

关于.net - StackExchange Redis AddOrUpdate 处理(乐观并发),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54771449/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com