我有服务 A 和服务 B 。
服务 A 是一个REST API,用于在数据库中存储服务 B 所需的一些相关信息。
服务 B 处理大量流量,并且不断消耗来自Kafka主题的消息。每条消息都需要来自服务 A 的一些信息。但是这些信息很少改变,最多只会改变每天的时间。
因此,为了避免经常访问REST API以获取很少更改的信息,我将实现缓存。 (不使用缓存也会给出始终查询数据库的问题)。服务 B 将首先点击缓存,如果它没有所需的数据,它只会点击 A 一次。
问题就在这里。
如果服务 A 更新其信息,我需要立即更新缓存 。
这样做的最佳方式是什么?
1)我可以在REST API中实现一些东西,让 B 注意到它需要更新他的chache,但是在关注点和封装方面的分离方面,
2)我可以在 B 中实现一个池(并且在每X次更新信息时进行B检查)或者每隔X次更新一次缓存。但是这样我就有可能无法立即更新信息 。
3)此信息可能是 A 中的缓存?至少我避免查询数据库,但没有点击API:/
有没有更好的方法来解决这个问题?
谢谢!
答案 0 :(得分:1)
这是一致性保证的问题,它是分布式系统中的核心问题。
您的方案包含三项服务:A,B和数据库。 如果B在任何情况下都不得使用陈旧数据,那么您有两种选择:
第一个选项不需要付出任何努力,并且对于某个工作负载可以正常工作,但如果B处的数据入口需要更多的数据库可以保留的吞吐量,它将成为一个严重的瓶颈。
第二个选项实现起来非常复杂,会减慢数据更改使系统复杂化并损害其整体可用性:如果A发生故障,则数据无法在数据库中更改;它在事务中发生故障,然后数据将无法从数据库中读取(!)
好消息是,大多数系统不需要如此强大的一致性保证,并且在特定情况下偶尔使用陈旧数据也可以。
如果您的系统属于这种情况,则有几种方法可以使缓存失效。我个人认为Jose Martinez的建议是使用消息排队系统,结合发布/订阅模式:服务B会向pub / sub发布“数据已更改”消息(该消息将包含有关哪些数据项的信息)确切地改变了),服务A将是订阅者处理“数据已更改”的消息并在其到达时使其缓存无效。
补充要点:
B内部的缓存看起来似乎可以提供强大的一致性,但事实是您可能需要扩展B,因此您将拥有多个B实例,每个实例都有自己的缓存,需要进行无效和同步。
您可以使用整个其他服务来保存缓存数据(Redis,Memcached等),这样您就可以将其职责分配给缓存数据(B可以使其无效,A可以直接从中读取),但它不会改变一致性困境的本质。
答案 1 :(得分:0)
基于此声明:"如果服务A更新其信息,我将需要立即更新缓存",那么根据我的经验,您的两种选择将是某种形式的分布式缓存:
希望有所帮助!
答案 2 :(得分:0)
在@ CapnSchwenk的回答中添加第三个要点...