处理内存缓存中的旧数据

11
假设使用内存缓存(如redis/memcache)的策略是:
  1. 读取:客户端将首先尝试从缓存中读取。如果缓存未命中,则从数据库中读取数据并将其放入缓存。

  2. 写入:先更新数据库,然后删除缓存条目。

假设发生以下序列:
  1. 客户端A从缓存中读取数据未命中。
  2. 客户端A从数据库中读取数据。
  3. 客户端B更新数据库中相同的条目。
  4. 客户端B删除缓存中(不存在的)条目。
  5. 客户端A将(过期的)条目放入缓存中。
  6. 客户端C将会从缓存中读取到过期的数据。
是否有避免这种情况的策略? 我知道我们可以为每个缓存条目设置一个过期时间,但在某些情况下,仍可能读取到过期的数据,这可能是不可取的。
2个回答

5
你可以对缓存数据进行版本控制,并保持每个版本不可变。每次数据库中的数据更改时,您都需要增加一个整数版本列。缓存键必须包含版本号。客户端首先可以查找当前版本号,然后再访问缓存。
由于缓存操作是非事务性的,因此保持缓存一致性非常困难。没有通用的方法可以防止你提到的问题。理想情况下,你希望原子地将写入在数据库和缓存中可见,但这仅在特殊情况下才可能实现。就像我建议的方案一样。

4
如果你每次都需要查询数据库来获取缓存键,那么缓存层还有益吗? - Horatiu Jeflea
@HoratiuJeflea 是的,如果您用一个更简单的访问替换了一个复杂的查询(或一组查询)。37信号使用这种技术为Basecamp创建事务一致的缓存。 - usr

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接