一尘不染

如何使用StackExchange.Redis进行基本WATCH

redis

我想用StackExchange.Redis做一个基本的观察。如果在交易过程中更改了密钥,它将失败。

StackExchange.Redis将其很好地抽象为“ Condition” 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();

甚至可能是更好的版本(可以做相同的事情):

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

目前,我了解的唯一方法是按照以下方式进行操作:

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

从阅读SE.Redis代码的尝试中,我知道可以理解为类似这样的内容(不确定其准确性):

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

我仍在学习有关Redis的更多信息,但是我不确定这有什么好处。您不希望最终结果像这样吗?:

WATCH key
MULTI
val = GET key
val = val + 1
SET key $val
EXEC

还是SE.Redis的工作方式无法做到这一点?


阅读 312

收藏
2020-06-20

共1个答案

一尘不染

之所以WATCH未直接公开,是因为SE.Redis设计为在单个连接上多路复用来自不同调用堆栈的命令。这使得必须 非常 严格地管理任何事务工作。

我不清楚的东西相当的宗旨,以“不变”是 由本身 ,无以伦比一些已知值-
否则,你只是建立一个竞争状态。绝对有可能添加对此的支持,但我真的很想先了解预期的用例。你可以解释吗?


重新编辑;您的首选示例(最后一个) 对于redis 来说根本不可能-
与SE.Redis无关;如果在GET内部进行MULTI运算,直到EXEC完成时才能得到答案-因此您不可能使用中的值SET该值尚不可用

如果不是用于多路复用,则可以对第二个示例重新排序(基于SE.Redis的功能):

WATCH key
val = GET key
MULTI
val = val + 1
SET key $val
EXEC

这是 通常的 用法WATCH:您先 观察
要查询的内容,然后知道{key}在此循环中没有更改(或者至少事务将中止;没有不一致的状态)。但是,WATCH 多路复用器不能很好地发挥作用
,这就是SE.Redis迫使您沿着 事务处理之前
获取值的路径进行操作的原因,然后允许您比较该值以断言该值是不变的。结果相同;略有不同的方法,但是它是多路复用器安全的。有关该主题的更多信息,请参见此处

2020-06-20