Mediatr - 使缓存无效/更新的正确位置在哪里

Posted

技术标签:

【中文标题】Mediatr - 使缓存无效/更新的正确位置在哪里【英文标题】:Mediatr - Where is the right place to invalidate/update cache 【发布时间】:2019-05-27 14:51:46 【问题描述】:

这个问题源于我问过的关于太多接口、QCRS 和 Mediatr 库(请求/响应)的另一个问题

Mediatr: reducing number of DI'ed objects

我已经创建了一堆命令和查询,并且我有一堆行为,其中一个是缓存行为,对于每个查询,在实际对数据库执行查询之前检查缓存的值。到目前为止,这工作得很好,但是当我有一个 UpdateSomethingCommand 时会出现 delim,一旦我更新了数据库中的底层对象,我想用成功保存到数据库的内容来刷新缓存。

我的问题是具体何时真正更新缓存:

    在 UpdateSomethingCommandHandler 中(这可能会破坏 SOLID 主体) 在 UpdateSomethingCommandHanlder 中调用另一个专门用于更新缓存的命令(不确定这是一个好的设计原则) 引入另一种专门用于更新缓存的行为(尚不知道如何处理) 有更好的解决方案吗?

【问题讨论】:

至于#2,不,你不应该这样做。看看这个页面的底部:jimmybogard.com/mediatr-9-0-released 【参考方案1】:

我们对使用 MediatR 的项目也有类似的需求,最终将缓存合并到调解器管道中,包括您描述的缓存失效。

基本前提是我们在管道中插入了两种不同的行为,一种用于缓存来自请求的响应,另一种用于使缓存的来自不同请求的请求响应无效。

这两种行为之间存在一些相互作用,因为它们需要交换缓存密钥才能使正确的请求无效。

我最近将其中的一些工作放到了一个独立的库中,理论上可以将其按原样放入任何使用 MediatR 的项目中。在您的情况下,您可能只想查看我们在此处使用的技术并根据需要重新创建它们。

我不会在这里和现在重复所有内容,而是将您指向项目页面,在主页上的“入门”链接下有一些文档: https://github.com/Imprise/Imprise.MediatR.Extensions.Caching

在我看来,缓存失效使整个过程变得非常简单明了,但在某些情况下,我们需要更好地控制失效发生的时间。在这些情况下,我们采取的另一种方法是将ICache<TRequest, TResponse> cache 注入INotificationHandlers,然后根据需要手动调用_cache.Remove(key);。然后,从您知道应该使无效的任何请求中,只需提出由INotificationHandler 处理的通知,例如_mediator.Publish(SomethingUpdated);

【讨论】:

【参考方案2】:

我的建议是使用一种缓存行为,该行为作用于实现某种 ICacheableRequest 标记接口的请求,并将缓存无效作为相应更新/删除命令处理程序中的一个步骤(就像您在第 1 点中提到的那样)。

如果您选择创建无效器行为,则会出现一些问题。

首先,不清楚该命令是否使缓存无效。每当我需要检查更新/删除实体时发生了什么时,我只需遵循命令处理程序,通过创建单独的缓存失效器没有副作用(更难遵循)。

其次,即使将失效代码放在单独的文件中更好地遵循 SRP,您也必须选择放置缓存失效器类的位置。它是在缓存查询旁边还是在使缓存无效的命令处理程序旁边?

第三,在许多情况下,您将没有足够的关于用于在关联命令中缓存请求的密钥的信息,您只能在 CommandHandler 中获得该信息以及任何其他额外的无效条件。

【讨论】:

以上是关于Mediatr - 使缓存无效/更新的正确位置在哪里的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Retrofit 和 OKHttp 在下一次请求时使缓存路由无效/强制更新?

如何使Apache Ignite缓存中的对象无效

使数据缓存的特定区域无效而不刷新其内容

如何正确地使 Symfony2 应用程序的生产缓存无效?

使用 TTL 与主动发送请求以使密钥无效以使缓存中的密钥无效的优缺点是啥?

使 OS 磁盘读取缓存无效