我想用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的工作方式无法做到这一点?
之所以WATCH未直接公开,是因为SE.Redis设计为在单个连接上多路复用来自不同调用堆栈的命令。这使得必须 非常 严格地管理任何事务工作。
WATCH
我不清楚的东西相当的宗旨,以“不变”是 由本身 ,无以伦比一些已知值- 否则,你只是建立一个竞争状态。绝对有可能添加对此的支持,但我真的很想先了解预期的用例。你可以解释吗?
重新编辑;您的首选示例(最后一个) 对于redis 来说根本不可能- 与SE.Redis无关;如果在GET内部进行MULTI运算,直到EXEC完成时才能得到答案-因此您不可能使用中的值SET: 该值尚不可用 。
GET
MULTI
EXEC
SET
如果不是用于多路复用,则可以对第二个示例重新排序(基于SE.Redis的功能):
WATCH key val = GET key MULTI val = val + 1 SET key $val EXEC
这是 通常的 用法WATCH:您先 观察 要查询的内容,然后知道{key}在此循环中没有更改(或者至少事务将中止;没有不一致的状态)。但是,WATCH 多路复用器不能很好地发挥作用 ,这就是SE.Redis迫使您沿着 事务处理之前 获取值的路径进行操作的原因,然后允许您比较该值以断言该值是不变的。结果相同;略有不同的方法,但是它是多路复用器安全的。有关该主题的更多信息,请参见此处。
{key}