存储库接口是否应该公开一个 clear() 方法来清除实现的缓存?

Should a repository interface expose a clear() method to clear the cache of the implementation?

我对存储库模式有疑问。我正在从事一个分布式项目,其中数据保存在内存中,但有一个数据库用于数据的持久性。为了扩展系统,数据在应用程序的多个实例之间进行分片。出于这个原因,每当任何节点出现问题时,数据都会从数据库重新加载并使用分布式队列重新分片。

我们创建了一个存储库接口,以便域与它对话以处理数据。该接口的实现使用一个映射作为内部缓存,并使用 Hibernate 与数据库对话。

因为每当创建或删除应用程序实例以开始重新分片时都必须清除缓存,我在 repo 中公开了一个方法来实现这个目的。这是正确的方法吗?这不是强制接口公开与实现内部相关的方法吗?另一种解决方案是将缓存注入负责触发刷新的服务,但这意味着泄漏有关持久层实现的信息。

有什么想法吗?

谢谢。

编辑

关于该应用程序的更多信息。进行分片的原因是为了能够在数据增长的情况下扩展应用程序。它需要订阅不同的频道,每秒最多发送 2 条消息,而这些频道最多可达数千条。对于收到的每条消息,它都需要遍历所有数据,找到与消息中的信息匹配的数据,然后为每个数据发送通知。为了能够扩展这一点,数据被跨实例分片,目前是两个实例,因此每个实例都会处理它拥有的数据。

数据是由用户创建的,为此创建了一些 REST 端点。从这个意义上说,它就像一个简单的应用程序,客户端可以在其中创建、更新、删除和获取它创建的数据。存储库公开了典型的 CRUD 操作和方法以根据特定信息进行查询,并且实现负责将数据添加到缓存和数据库,并根据请求从其中一个或另一个获取数据。应用程序中有一些更复杂的情况,因为在缓存未命中的情况下,我们不能简单地从数据库中获取数据并将其放入缓存中,因为这意味着,如果数据不存在,则必须有另一个集群中的实例,它在自己的缓存中包含数据。为了处理这个问题,我们有用于重定向请求的队列和主题。

因此我们需要清除缓存。每次集群的拓扑结构发生变化时,这意味着要么我们必须重新平衡缓存中的数据以防有新节点,要么我们需要再次从数据库中获取数据,因为其中一个缓存有下降;消沉。由于我们不知道到底丢失了什么数据,我们清除缓存并从数据库中重新填充它们,使用一个节点作为数据加载器和一个分布式队列来分片数据。 这项工作完成得非常快,因此我们在此期间拒绝客户的任何请求。该应用程序没有那么多来自客户端的并发请求,问题在于我们必须跟上的订阅渠道。

您确实不想公开 clear() 方法。

假设您有两项服务。您所描述的存储库和集群管理器,它了解集群状态及其更改时间。

现在您可以让集群管理器使用存储库 API 并添加代码以在拓扑发生变化时调用所有需要的操作。 但是,只有从存储库实现到集群管理器的依赖关系,而不是相反。集群管理器不需要知道存储库即可向其他客户端提供服务。

唯一的问题是,调用是相反的,集群管理器需要调用存储库。要解决这个问题,请定义一个事件(例如 TopologyChanged),它是集群管理器 API 的一部分,并让存储库实现告诉集群管理器它想要得到通知。

旁注:

有些产品已经可以执行此类操作,例如Apache Ignite、Hazelcast、Infinispan。