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