如何使用 StackExchange.Redis 做基本的 WATCH

Ben*_*lde 6 .net c# redis stackexchange.redis

我想用 StackExchange.Redis 做一个基本的观察。如果在事务期间更改密钥,则失败。

StackExchange.Redis 很好地将其抽象为“条件”api,它支持“相等”和“存在”的概念。

这真的很好,但我只想做一些“不变”之类的事情。我可能会遗漏一些东西,但目前我对如何做到这一点并不明显。

是否可以执行以下操作:

var transaction = redis.CreateTransaction();
transaction.AddCondition(Condition.StringUnchanged("key")); //the API here could maybe be simplified
var val = transaction.StringGet("key"); //notably, this is not async because you would have to get the result immediately - it would only work on watched keys
transaction.StringSetAsync("key", val + 1);
transaction.Execute();
Run Code Online (Sandbox Code Playgroud)

或者甚至可能更好的版本(可以做同样的事情):

var transaction = redis.CreateTransaction();
var val = transaction.Watch("key"); //this would return the value!
transaction.StringSetAsync("key", val + 1);
transaction.Execute();
Run Code Online (Sandbox Code Playgroud)

目前,我理解这样做的唯一方法是按照以下方式做一些事情:

var val = redis.StringGet("key");
var transaction = redis.CreateTransaction();
transaction.AddCondition(Condition.StringEqual("key", val));
transaction.StringSetAsync("key", val + 1);
transaction.Execute();
Run Code Online (Sandbox Code Playgroud)

从阅读 SE.Redis 代码的尝试中,我理解将其转换为类似的内容(不确定这有多准确):

val = GET key
WATCH key
MULTI
val = val + 1
SET key $val
checkVal = GET key
(then if checkVal != val:) UNWATCH
(otherwise:) EXEC
Run Code Online (Sandbox Code Playgroud)

我仍在进一步了解 Redis,但我不太确定这样做的好处是什么。你不希望最终结果更像这样吗?:

WATCH key
MULTI
val = GET key
val = val + 1
SET key $val
EXEC
Run Code Online (Sandbox Code Playgroud)

或者这是不可能的 SE.Redis 工作方式?

Mar*_*ell 4

未直接公开的原因WATCH是 SE.Redis 的设计方式是在单个连接上复用来自不同调用堆栈的命令。这使得任何事务工作都需要非常严格的管理。

我不清楚“不变”本身的目的是什么,而不与某些已知的值进行比较 - 否则你只是在创建竞争条件。添加对它的支持肯定是可能的,但我真的很想首先了解预期的用例。你可以解释吗?


重新编辑;您喜欢的示例(最后一个)根本不可能用 redis 实现- 与 SE.Redis 无关;如果您在 a 中执行GETa MULTI,则在完成之前您不会得到答案EXEC- 因此您不可能使用 a 中的值SET它还不可用

如果不是为了多路复用,您可以稍微重新排序第二个示例(基于 SE.Redis 的做法):

WATCH key
val = GET key
MULTI
val = val + 1
SET key $val
EXEC
Run Code Online (Sandbox Code Playgroud)

这是典型的用法WATCH:你提前观察你正在查询的东西,然后你知道它{key}在这个循环期间没有改变(或者至少,事务将中止;没有不一致的状态)。但是,WATCH 与多路复用器配合使用效果不佳,这就是为什么 SE.Redis 强制您在事务之前获取值,然后允许您比较该值以断言它没有更改。结果相同;方法略有不同,但它是多路复用器安全的。有关该主题的更多信息,请参阅此处