C# 如何继续并将其作为MULTI命令的一部分?
总之,我试图调用C# 如何继续并将其作为MULTI命令的一部分?,c#,.net,asynchronous,redis,stackexchange.redis,C#,.net,Asynchronous,Redis,Stackexchange.redis,总之,我试图调用ITransaction.SetPopAsync(…),并作为底层MULTIRedis原子操作的一部分执行其他写操作 我曾尝试执行SetPopAsync(…)调用Task.ContinueWith,并在回调中执行所谓的其他写入操作,但当我发现这些操作是在底层MULTI操作结束后执行(即ITransaction.ExecuteAsync()时)时,我感到惊讶finishs) 也许我弄错了,但我觉得只有在我将LUA脚本加载到Redis并从C#调用它时,这个原子操作才能完成 对于我的案
ITransaction.SetPopAsync(…)
,并作为底层MULTI
Redis原子操作的一部分执行其他写操作
我曾尝试执行SetPopAsync(…)
调用Task.ContinueWith
,并在回调中执行所谓的其他写入操作,但当我发现这些操作是在底层MULTI
操作结束后执行(即ITransaction.ExecuteAsync()时)时,我感到惊讶
finishs)
也许我弄错了,但我觉得只有在我将LUA脚本加载到Redis并从C#调用它时,这个原子操作才能完成
对于我的案例,有没有其他解决方案可以在C#和StackExchange.Redis
库中完全实现
更多信息。。。
我发现有一个关于这个主题的特定文档
现在我更困惑了,因为*如果执行整个spop
而它不是MULTI
命令的一部分,并且在spop
之后创建其他键时,系统会发生什么情况,导致数据损坏
所以。。。我是否错过了一些可以让我执行整个spop
并确保所有其他操作都将完成并持久化的操作
一个示例场景。。。
正如@BerinLoritsch在这里的一些评论中所要求的那样,我将在这里抛出一个伪代码,使用Redis命令来给出一个示例:
MULTI
key1MemberValue = spop key1 1
sadd key2 key1MemberValue
zadd key3 1 key1MemberValue
EXEC
注意:我不能使用
smove
,因为我不知道现实世界中的set成员。我需要随机弹出一个。现在,实际上在我的特殊情况下,有另一种方法可以解决同样的问题,它允许我使用原子性来执行操作
不要使用spop
,而是使用Redis命令检查以下伪代码:
time = [current time]
member = zrangebyscore key1 -inf +inf limit 0 1
zrem key1 member
zadd key2 time member
zadd key3 time member
现在,这里的最佳解决方案似乎是调用上述代码列表命令的LUA脚本,因为Redis是单线程的,一次可以执行一个操作,LUA脚本本身就是一个操作,如果我想确保其他操作不会尝试弹出相同的set
值,我觉得应该这样做
此外,我必须将规则集转换为排序集。由于Redis在复制和集群环境中避免数据损坏的限制,您不能在非确定性命令之后调用写命令,无论是读操作还是写操作。多亏了
zrangebyscore
(它可能是zrange
,zrevrange
,zrevrangebyscore
),因为它是确定性的,所以我可以模拟pop操作并仍然使用集合语义。最终,您需要理解redis multi/exec块与ADO.NET事务不同。从根本上说,在redis中,以下(问题中)是不可能的:
因为您从spop
得到的结果是:排队
。这就是全部。只有执行EXEC
,您才能得到任何答案,因此您不能在MULTI
中的sadd
/zadd
中使用此值
在原始的redis中,您可以想象的是涉及到手表;然而,所有这一切意味着,如果另一个连接改变了WATCH
-ed键,MULTI
/EXEC
块被放弃,而不是被执行;您仍然会有spop
-ped
所以从根本上说:是的,如果您希望在没有竞争连接失效状态的情况下实现这一点:您必须通过Lua和EVAL
/EVALSHA
-或者需要更改条件
API。看到一段代码片段,了解您至少要做的事情的关键部分,可能会有很大帮助。@BerinLoritsch我相信这是正确的确实,SO需要代码片段,但问题与特定情况无关。更重要的是,MULT
是一种原子执行,您不能依赖返回值的写操作,继续该值在整个MULT
中执行其他操作command@BerinLoritsch查看我的问题的更新。。。我制作了一个简单的伪代码,为您提供了整个原子操作的示例,或者至少是我想要实现的。如果另一个连接在srandmember
和multi
之间弹出成员,会发生什么?您可能需要一些包含监视的内容才能有力地完成此操作。就SE.Redis而言,我怀疑我可以添加一个条件.SetContains
,这就足以作为一个前置条件(这将成为WATCH{key};SISMEMBER{key}{value};MULTI;{blah};EXEC;
,并在MULTI
之前添加一些代码来验证SISMEMBER
的结果)有关条件
等的更多内容:@marcGravel我明白了。但我的结论错了吗?我的意思是,如果我在LUA脚本中使用EVALSHA
,它应该足够健壮?@MarcGravel你知道为什么在LUA脚本中不允许使用multi
。@MarcGravel事实上,我相信我做的和这个问题一样,但我使用的是srandmember
,这也会让我想到同样的问题,如一些帖子所述,感谢您的努力;)最后,既然我们得出了相同的结论——EVAL/EVALSHA方法——至少我觉得我走在了正确的轨道上@MatíasFidemraizer它也可以通过WATCH
来实现,但Lua可能是实现和获得正确答案的最简单方法。。。想想吻。。。是的,每当服务启动时都必须加载脚本不是KISS,但解决方案本身就是KISSanyway@Matíasfidemrazer您在标签中提到SE.Redis;如果只使用ScriptEvaluate
传递Lua,它将自动执行
MULTI
key1MemberValue = spop key1 1
sadd key2 key1MemberValue
zadd key3 1 key1MemberValue
EXEC