与etags和多服务器设置的一致性?

时间:2013-11-12 23:24:11

标签: caching distributed-caching distributed-system

我试图了解哪个是最佳缓存策略,以便REST API层允许查询和更新客户注册数据库。我们目前有3个前端服务器都与中央数据库服务器通信。

这个想法是将etag返回给调用客户端,etag与客户记录版本ID匹配(在帐户的任何更改时更新的哈希值),只有在收到的etag与版本匹配时才接受更新调用id存储在数据库中。

假设客户端为负载均衡器路由到服务器1的客户记录执行GET。服务器1没有缓存客户记录,因此将查询数据库,在本地缓存记录并返回记录作为包括etag标题的呼叫响应。

如果第二个客户端到达并为同一个客户记录路由到服务器2执行相同的GET,则服务器2也将在本地缓存该条目并返回相同的etag标头。

我们假设现在第一个客户端已经通过服务器1对同一记录执行了更新调用。服务器1缓存会更新最新的记录详细信息,第一个客户端返回一个新的etag。

此后,第二个客户端执行条件获取调用,提供与接收到的etag设置的“If-None-Match”标头。该请求将再次命中服务器2.我的假设是服务器2仍将缓存旧的etag并将向客户端返回304 Not Modified响应。这是正确的假设吗?

在这种情况下,客户端会轻易获得过时的数据,并会影响客户端看到和使用的数据的整体一致性。

解决这个问题需要什么,并确保任何时候都不会将过时的客户记录数据返回给客户?

非常感谢!

3 个答案:

答案 0 :(得分:3)

缓存失效是要解决的hard problem。至少我有三种方法可以解决这个问题。它们的复杂程度和过期记录的有效期仍然有所不同。

  1. 最简单的答案是所有前端服务器必须在返回“304 Not Modified”之前调用数据库来验证etag。如果有许多更新或从数据库下载记录的成本很高,这可能是最好的。

  2. 如果有时可以发回旧值,则可以在缓存的项目上设置到期时间。

  3. 另一个选择是当1个前端服务器看到更新时,它需要告诉其他前端服务器使该缓存项过期(可能通过调用webservice?)。这允许较长的缓存持续时间,但如果有大量更新,则可能过于繁琐。

答案 1 :(得分:1)

+ @ David列表的另一个解决方案:

  1. 使用集中式缓存。它应该解决你的问题。 尽管它比本地缓存效率低,但在大多数情况下仍然比查询数据库更快。
  2. 可能的群集缓存实施包括: couchbase redis群集。 最受欢迎的非群集实现是 memcached

答案 2 :(得分:0)

与Google发布的this文章一样,您可以使用分层缓存来解决某些情况下的缓存失效问题,特别是对于静态资产。

根据资产的指纹(附加)命名资产并使顶层不可缓存是这里的基本想法。