我想用StackExchange.Redis做一个基本的监视。如果在交易期间更改了密钥,则会失败。
StackExchange.Redis已经很好地抽象了一个"条件" api,它支持" Equals"的概念。和#34;存在"。
这真的很不错,但我想做的事情就像" Unchanged"。我可能会遗漏一些东西,但就此而言,我对此并不明显。
是否可以执行以下操作:
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的工作方式是不可能的?
答案 0 :(得分:2)
WATCH
未直接暴露的原因是因为SE.Redis如何设计为在单个连接上复用来自不同调用堆栈的命令。这使得任何事务工作都必须非常严格管理。
我不清楚“未改变”的目的是什么本身,而不是与某些已知值相比 - 否则你只是创造了竞争条件。肯定可以添加对它的支持,但我真的想先了解预期的用例。你能解释一下吗?
重新编辑;你最喜欢的例子(最后一个)根本不可能 with 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强制您在事务之前获取值的路径,然后允许您比较该值以断言它不变。相同的结果;方法略有不同,但它是多路复用器安全的。有关该主题的更多信息see here。