Redis缓存 - 如何避免竞争条件?

时间:2014-08-10 06:48:55

标签: node.js redis

我想使用redis缓存数据库查询。现在,单个API端点中的伪代码如下所示:

GET /data
  1. 检查对象是否在REDIS缓存中(通过cacheKey)
  2. 如果它在缓存中,只需将其返回给客户端
  3. 如果它不在缓存中,则从DB
  4. 获取数据
  5. 将数据写入REDIS缓存(在cacheKey中)
  6. 将数据返回给客户
  7. 我正在缓存不经常更改的objets,所以我将expiration设置为24h。问题是我想要更新这样的对象。伪代码如下所示:

    PUT /data
    
    1. 更新数据库
    2. 中的数据
    3. 将数据写入缓存(或只是将缓存设置为空/删除表单缓存)
    4. 问题是,在将新数据写入缓存(或缓存已被删除)后,仍然GET /data可以用旧数据覆盖缓存中的新数据。如果在GET /data的第2点之后执行第4点表单PUT /data,就会发生这种情况。

      是否有任何机制可以防止用缓存中的旧数据覆盖新数据?

2 个答案:

答案 0 :(得分:3)

如果PUT将新数据放入缓存中,并将其放入数据库(直写缓存),则可以使用SET / {{1在从HSET写入缓存时,从PUTSETNX / HSETNX写入缓存时。由于GET仅在密钥不存在时才会写入缓存,因此通常GET会成功。但是如果其他人(可能是SETNX)出现并在此期间设置了密钥,则PUT将失败,因为该密钥已经存在,并且您将获得所需的结果。< / p>

如果SETNX只是删除了要由下一个PUT重新填充的缓存中的数据,我认为您无法提供比现有更好的保证。从数据库中检索数据后,数据将存在一个到期时间,这并非严格错误,只是比您想要的更糟糕。

答案 1 :(得分:3)

@hobbs建议的NX方法仍有竞争条件。我将使用围绕您的GET工作流的WATCH / MULTI / EXEC块添加它,以实现类似事务的行为。

使用仅限NX的方法,仍然有可能在3到4之间,PUT会阻碍。