rest - 何时以及如何更新缓存

标签 rest caching architecture

我有一个服务A和一个服务B

服务A是一个REST API,它在数据库中存储服务B所需的一些相关信息。

服务B处理大量流量,并不断消耗来自 Kafka 主题的消息。每条消息都需要来自服务A的一些信息。但这些信息很少改变,最多每天改变一次。

因此,为了避免不断访问 REST API 来获取很少更改的信息,我将实现一个缓存。 (不使用缓存还会带来始终查询数据库的问题)。服务B将首先访问缓存,如果没有所需的数据,则只会访问A一次。

问题来了。

如果服务A更新其信息,我需要立即更新缓存。

最好的方法是什么?

1) 我可以在 REST API 中实现一些东西,让 B 注意到它需要更新他的 chache,但就关注点分离和封装而言, 还不错A 知道 B 处理内部缓存吗? (我认为是)

2)我可以在B中实现一个池(并让B检查信息是否每X次更改)或每X次更新缓存。但这样我就有无法立即更新信息的风险。

3) 也许在 A 中缓存此信息?至少我避免查询数据库,但不访问 API :/

有没有更好的方法来处理这个问题?

谢谢!

最佳答案

这是一个一致性保证的问题,是分布式系统的核心问题。

您的场景包含三个服务:A、B 和数据库。 如果 B 在任何情况下都不得使用过时的数据,那么您有两个选择:

  1. 所有读取都将命中数据库(A 或 B 处没有缓存)。数据库内置的机制,例如数据库内部缓存、磁盘缓存和 RAID 镜像,可能会缓解一些磁盘 I/O 瓶颈。
  2. 将数据缓存在 A(或 B)处,并在缓存和数据库之间强制执行强一致性,这意味着每次写入都将在数据库和缓存之间的分布式事务内完成(或者通过使用其他一些共识协议(protocol)来完成)提供强一致性保证)

第一个选项不需要任何努力,并且对于一定的工作负载来说可以很好地工作,但如果 B 处的数据入口需要数据库可以抑制的更多吞吐量,则会成为严重的瓶颈。

第二个选项实现起来相当复杂,会减慢数据更改速度,使系统复杂化并损害其整体可用性:如果 A 出现故障,则数据库中的数据无法更改;如果在事务中发生故障,则数据将无法从数据库中读取(!)

好消息是,大多数系统不需要如此强大的一致性保证,并且在特定情况下偶尔使用过时的数据是可以的。

如果您的系统属于这种情况,则有多种方法可以使缓存失效。就我个人而言,我会同意 Jose Martinez 的建议,即使用消息队列系统,并结合发布/订阅模式:服务 B 将向发布/订阅发布一条“数据已更改”消息(该消息将包含有关哪些数据项的信息)完全更改),服务 A 将是处理“数据更改”消息的订阅者,并在消息到达时使其缓存失效。

补充要点:

B 内部的缓存乍一看似乎可以提供强一致性,但事实是您可能需要扩展 B,以便您将拥有 B 的多个实例,每个实例都有自己的缓存,需要使其失效和同步。

您可以使用其他服务来保存缓存数据(Redis、Memcached 等),这将允许您将缓存数据的责任分开(B 可以使其无效,A 可以直接从中读取数据),但它不会改变一致性困境的本质。

关于rest - 何时以及如何更新缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45992917/

相关文章:

java - Spring-boot中使用缓存抽象的缓存故障转移机制

java - 我应该为每种数据库查询创建新实体吗?

compilation - 动态链接和静态链接的指令点值

rest - 以 RESTful 方式建模更复杂的实体关系(框和节点)

java - Spring Security Rest Web 应用程序和 Spring Security

java - 寻找一次读取的内存缓存

具有网络图像缓存的Android Listview

Laravel 5.0 应用结构

rest - 使用静态文档 Swagger

java - Jersey (网络服务): the advantages of StreamingOutput and the best way for create downloading API