gpt4 book ai didi

redis - StackExchange.Redis:事务是否多次命中服务器?

转载 作者:行者123 更新时间:2023-12-03 06:36:47 32 4
gpt4 key购买 nike

当我通过 SE.Redis 执行事务 (MULTI/EXEC) 时,它会多次访问服务器吗?例如,

        ITransaction tran = Database.CreateTransaction();
tran.AddCondition(Condition.HashExists(cacheKey, oldKey));

HashEntry hashEntry = GetHashEntry(newKeyValuePair);

Task fieldDeleteTask = tran.HashDeleteAsync(cacheKey, oldKey);
Task hashSetTask = tran.HashSetAsync(cacheKey, new[] { hashEntry });

if (await tran.ExecuteAsync())
{
await fieldDeleteTask;
await hashSetTask;
}

这里我在事务中执行两个任务。这是否意味着我打了服务器 4 次? 1 表示 MULTI,1 表示删除,1 表示设置,1 表示执行?或者 SE.Redis 是否足够聪明,可以在本地内存中缓存任务并在我们调用 ExecuteAsync 时一次性发送所有内容?

最佳答案

它必须发送多个命令,但不会为每个命令支付延迟成本;具体来说,当您调用 Execute[Async] (而不是之前)它发出一个管道(全部在一起,不等待回复):

WATCH cacheKey                  // observes any competing changes to cacheKey
HEXIST cacheKey oldKey // see if the existing field exists
MULTI // starts the transacted commands
HDEL cacheKey oldKey // delete the existing field
HSET cachKey newField newValue // assign the new field

然后它需要支付延迟成本才能从 HEXIST 获取结果。 ,因为只有在知道了这一点时,它才能决定是否继续进行交易(发出 EXEC 并检查结果 - 如果 WATCH 检测到冲突,这可能是否定的),或者是否丢弃所有东西( DISCARD )。

所以;无论哪种方式,都会发出 6 个命令,但在延迟方面:由于需要在最终 EXEC 之前的决策点,您需要支付 2 次往返费用。/ DISCARD .然而,在许多情况下,这本身可能会被 HEXIST 的结果这一现实进一步掩盖。在我们进行检查之前,可能已经在返回给您的路上,特别是如果您有任何重要的带宽,例如大的 newValue .

然而!作为一般规则:你可以用 redis 做任何事情 MULTI/ EXEC : 可以通过使用 Lua 脚本来更快、更可靠且错误更少地完成。看起来我们实际上在这里尝试做的是:

for the hash cacheKey, if (and only if) the field oldField exists: remove oldField and set newField to newValue



我们可以在 Lua 中非常简单地做到这一点,因为 Lua 脚本从头到尾在服务器上执行,不会因竞争连接而中断。这意味着我们不需要担心诸如原子性之类的事情,即其他连接会改变我们正在使用的数据。所以:

var success = (bool)await db.ScriptEvaluateAsync(@"
if redis.call('hdel', KEYS[1], ARGV[1]) == 1 then
redis.call('hset', KEYS[1], ARGV[2], ARGV[3])
return true
else
return false
end
", new RedisKey[] { cacheKey }, new RedisValue[] { oldField, newField, newValue });

这里的逐字字符串文字是我们的 Lua 脚本,注意我们不需要单独的 HEXISTS/ HDEL更多 - 我们可以根据 HDEL 的结果做出决定.在幕后,图书馆执行 SCRIPT LOAD根据需要进行操作,因此:如果您多次执行此操作,则无需多次通过网络发送脚本本身。

从客户端的角度来看:您现在只需支付一次延迟费,我们不会重复发送相同的内容(原始代码发送了四次 cacheKey 和两次 oldKey)。

(关于选择 KEYSARGV 的注释:键和值之间的区别对于路由目的很重要,特别是在分片环境中,例如 redis-cluster;分片是基于键完成的,并且唯一的键这里是 cacheKey ;散列中的字段标识符不会影响分片,因此出于路由的目的,它们是值,而不是键 - 因此,您应该通过 ARGV 而不是 KEYS 来传递它们;这不会在 redis-server 上不会影响您,但在 redis-cluster 上这种差异非常重要,就好像您弄错了一样:服务器很可能会拒绝您的脚本,认为您正在尝试跨槽操作;多键 redis-cluster 上的命令仅在所有键都在同一个插槽上时才支持,通常通过“哈希标签”实现)

关于redis - StackExchange.Redis:事务是否多次命中服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62401901/

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