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

如何使用spymemcached实现原子操作“setif缺席”

邵星光
2023-03-14

我正在使用Memcached(使用spymemcached作为客户端)缓存从远程服务器接收的响应。我的程序逻辑很简单:

  • 如果请求的资源缓存在Memcached,请立即返回缓存;
  • 如果没有,请连接到远程服务器,缓存它,然后返回结果。

这个程序就像是,

Object cachedResource = spyMemcachedClient.get(RESOURCE_KEY);
if (cachedResource != null) {
    return cachedResource;
} else {
    Object remoteResource = getTheResourceFromTheRemoteServer();
    spyMemcachedClient.set(RESOURCE_KEY, EXP_TIME, remoteResource);
    return remoteResource;
}

但是我注意到,由于同时会有许多并发请求,有可能两个线程都发现cachedresourcenull,因此它们都调用GetThereSourceFromThereMoteServer,这是我不希望的。

那么,我该如何避免这件事。spymemcached中是否有类似concurrentmap.putif缺席的原子操作。(顺便说一下,该程序将部署在多个实例上,这意味着不可能使用像Lock这样的Java并发实用程序来实现这一点。)

共有1个答案

端木明贤
2023-03-14

memcached中有add命令可以执行您想要的操作(命令列表)。为了避免调用两次或更多次GetThereSourceFromThereMoteServer,您应该使用memcached(结合AddDelete命令)来模拟写锁。因此,只有在同一特定密钥(RESOURCE_KEY_LOCK)上成功调用add的线程才应该调用getThereSourceFromThereMoteServer并将其放入缓存。其他线程应等待并再次调用get(RESOURCE_KEY)

 类似资料:
  • 在使用 ConcurrentHashMap 时,ConcurentHashMap 通过 CAS 保证了操作的线程安全。但是当我们需要进行多个操作和复合操作时,ConcurentHashMap 并不能保证操作的原子性: get 和 put 分别是线程安全的,然而当我们先 get 后 put 操作时,从 get 到 put 的过程中间,其他线程可能已经修改了这个key对应的值。 ConcurrentH

  • 主要内容:常用的原子操作命令维护原子性的推荐方法是保留所有相关信息,并将这些信息使用嵌入式文档的形式更新到文档中,这将确保单个文档的所有更新都是原子的。假设我们已经创建了一个名为 productDetails 的集合,并在其中插入了一个文档,如下所示: 在上面的文档中,我们将购买产品的客户的信息嵌入到 product_bought_by 字段中。当有新客户购买该产品时,我们首先会使用 product_available 字段

  • 问题内容: 我正在使用Python通过一次操作将大块文本写入文件: 如果脚本被中断,所以文件写入未完成,我希望没有文件,而不是部分完成的文件。能做到吗? 问题答案: 将数据写入临时文件,并且在成功写入数据后,将文件重命名为正确的目标文件,例如 根据文档http://docs.python.org/library/os.html#os.rename 如果成功,重命名将是原子操作(这是POSIX要求)

  • 我在想。如果我有一个int变量,我想在我所有的线程中同步-难道我不能保留一个位来知道值是否正在更新吗? 为了避免写入操作以块形式执行,这意味着线程可能正在访问中间写入值,这是不正确的,或者更糟糕的是,覆盖它,导致它完全错误,我希望线程首先被告知正在写入变量。我可以简单地使用一个原子操作来写入新值,这样其他线程就不会干涉,但是这个想法看起来并不那么愚蠢,我想先使用基本的工具。 如果我只做一个小操作呢

  • 启动C 20时,原子的操作有等待操作和通知操作。但我不知道它们到底是怎么工作的。cppreference说: 执行原子等待操作。表现为它重复执行以下步骤: 比较此的值表示形式- 这些函数保证仅在值发生更改时返回,即使底层实现错误地解除了阻塞。 我不太明白这两个部分是如何相互关联的。这是否意味着如果值没有更改,那么即使我使用了notify\u one()/方法,函数也不会返回?这意味着该操作在某种程

  • 乐观锁与悲观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时间片之间,需要进行cpu切换,也就是会发生进程的切换。切换涉及到清空寄存器,缓存数据。然后重新加载新的thread所需数据。当一个线程被挂起时,加入到阻塞队列,在一定的时间或条件下,在通过notify(),notifyAll()唤醒回来。 在某个资源不可用的时候,就将