当前位置: 首页 > 知识库问答 >
问题:

使用Booksleve和Redis进行检查和设置(CAS)操作

濮阳耀
2023-03-14

Booksleve是否支持CAS操作(即Redis WATCH命令)?例如,如何实现以下内容?

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

当多个线程试图用相同的数据修改相同的对象时,我需要这样做来避免竞争条件。

共有1个答案

羊舌琛
2023-03-14

在nuget目前,我不这么认为。原因是Booksleve通常打算用作多路复用器,这使得“手表”无法使用。我可以补充一句,在操作期间,您必须将使用限制为单个调用方(每个Booksleve连接)。

这一点现在已经改变;如果我们希望手动实现incr(根据您的示例),我们可以使用:

// note this could be null if the old key didn't exist
var oldVal = await connection.Strings.GetInt64(db, key);

var newVal = (oldVal ?? 0) + 1;
using (var tran = connection.CreateTransaction())
{
    // check hasn't changed (this handles the WATCH, a checked GET,
    // and an UNWATCH if necessary); note tat conditions are not sent
    // until the Execute is called
    tran.AddCondition(Condition.KeyEquals(db, key, oldVal));

    // apply changes to perform assuming the conditions succeed
    tran.Strings.Set(db, key, newVal); // the SET

    // note that Execute includes the MULTI/EXEC, assuming the conditions pass
    if (!await tran.Execute()) return null; // aborted; either a pre-condition
                                         // failed, or a WATCH-key was changed
    return newVal; // successfully incremented
}

显然,您可能希望在重复的(在正常范围内)循环中html" target="_blank">执行它,这样,如果它由于watch而被中止,您可以从头开始重做。

这与您的示例略有不同,实际上是这样的(假设初始Get和第二个Get之间的值没有更改):

val = GET mykey
newval = (val ?? 0) + 1
WATCH mykey
chk = GET mykey // and verifies chk == val as part of the Execute
MULTI
SET mykey $newval
EXEC

注意,如果watchexec之间的值发生了更改,则exec仍然可以报告取消;或者(如果在两个get之间更改):

val = GET mykey
newval = (val ?? 0) + 1
WATCH mykey
chk = GET mykey // and verifies chk == val as part of the Execute
UNWATCH

区别是多了一个get,但这是它能够与多路复用器一起工作的唯一方式--也就是说,使execute得到优化,以可靠地快速,从而不会影响其他调用方。

 类似资料:
  • 下面是一个在前缀值为“bar”的键“foo”上调用脚本的示例(在redis-cli中): 我认为这种使用模式可能是这样的情况:您希望同时存储一个“Geofence令牌”和一个带有键的值...如果并发客户端持有正确的Geofence令牌,则允许它们尝试更新该值。 这看起来像是代替watch/multi/exec语义的安全使用模式吗?(似乎您可以获取当前值,在本地代码中拆分隔离令牌,构建一个新值,然后

  • 问题内容: 我只是想了解Redis / Lua脚本,我想知道是否有人看到以下代码有问题。 我尝试实现非常简单的“ CAS”语义:使用单个键和两个参数来调用它。它将检查服务器上与该键关联的值是否 以 第一个参数 开头 ,如果是,则将设置键的新值设置为第二个参数并返回1,否则返回0;否则返回0。如果键与字符串以外的其他某种类型的数据相关联,则Redis将返回并返回错误,就像您对这样的键/值组合尝试执行

  • 嘿,我有一个非常愚蠢的问题,我不明白为什么它不能像预期的那样工作。因此,我使用viewpager和FragmentStatePagerAdapter制作了一个多片段布局(每个布局都有一些不同的问题)。当我打开承载所有这些片段的屏幕时,我正试图使用网络呼叫恢复以前的状态(标记所有已回答的问题)。但是,如果用户看不到我的片段,它似乎无法更新单选按钮/复选框的选中状态。 有人知道我能做些什么来实现我的愿

  • 我在mysql表中有一个int列,用于存储与状态相关的位。我对基于状态字段中是否设置了一个或多个位的查询感兴趣。 我尝试了以下方法:

  • 我有一个FlinkV1.2的设置,3个JobManager,2个TaskManager。对于后端状态和检查点以及zookeeper storageDir,我想使用S3桶而不是hdfs 我没有安装hadoop。不确定是否需要这样做,以及是否需要这样做,应该如何/在哪里安装/配置它? 编辑:在使用以下hadoop xml(core-site.xml)配置Flink之后,我并不真正理解IAM部分,而且我

  • 使用spray时,我一直遇到相同的设计问题,即在Akka中执行一些异步(tell)操作之后,如何为请求找到spray http请求的原始上下文。 我使用的是Net-a-Porter actor per request模型。它创建了一个子执行元,我指定该子执行元来处理每个请求,该子执行元由另一个包含正确请求上下文的执行元进行封装。