我试图了解哪个是最佳缓存策略,以便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响应。这是正确的假设吗?
在这种情况下,客户端会轻易获得过时的数据,并会影响客户端看到和使用的数据的整体一致性。
解决这个问题需要什么,并确保任何时候都不会将过时的客户记录数据返回给客户?
非常感谢!
答案 0 :(得分:3)
缓存失效是要解决的hard problem。至少我有三种方法可以解决这个问题。它们的复杂程度和过期记录的有效期仍然有所不同。
最简单的答案是所有前端服务器必须在返回“304 Not Modified”之前调用数据库来验证etag。如果有许多更新或从数据库下载记录的成本很高,这可能是最好的。
如果有时可以发回旧值,则可以在缓存的项目上设置到期时间。
另一个选择是当1个前端服务器看到更新时,它需要告诉其他前端服务器使该缓存项过期(可能通过调用webservice?)。这允许较长的缓存持续时间,但如果有大量更新,则可能过于繁琐。
答案 1 :(得分:1)
+ @ David列表的另一个解决方案:
可能的群集缓存实施包括: couchbase , redis群集。 最受欢迎的非群集实现是 memcached 。
答案 2 :(得分:0)
与Google发布的this文章一样,您可以使用分层缓存来解决某些情况下的缓存失效问题,特别是对于静态资产。
根据资产的指纹(附加)命名资产并使顶层不可缓存是这里的基本想法。