【问题标题】:Data Repository using MemoryCache使用 MemoryCache 的数据存储库
【发布时间】:2017-01-26 21:44:22
【问题描述】:

我构建了一个自制数据实体存储库,其中包含一个按类型定义保留策略(例如绝对或滑动到期)的工厂。该策略还将缓存类型指定为 httpcontext 请求、会话或应用程序。 MemoryCache 由所有 3 种缓存类型中的缓存代理维护。无论如何,我有一个与存储库绑定的数据实体服务,它为我们的主数据实体加载和保存。这个想法是您使用实体存储库,并且不需要关心实体是否被缓存或从其数据源(在本例中为 db)检索。

一个明显的假设是您需要同步加载/保存事件,因为您需要在从数据源加载实体之前保存缓存的实体。

所以我今天正在调查生产中的数据完整性问题... :)

今天我读到,从 MemoryCache 中删除的实体与 CacheItemRemovedCallback 事件触发之间可能存在很长的间隔(默认为 20 秒)。我对加载和保存数据操作的简单锁定是不够的。此外,CacheItemRemovedCallback 位于 HttpContext 之外的它自己的上下文中,这让事情变得有趣。这意味着我需要将回调函数设为静态,因为我可能会将已处置的实例分配给事件。

因此,一旦我意识到可能存在差距,即我的数据实体不再存在于缓存中,但可能没有保存到它的数据源中,这可能会解释 5000 个中的 3 个损坏订单。在填写长表格时在主数据实体上执行超出策略 20 分钟滑动到期的工作将很容易。这意味着如果他们碰巧在到期的同一时刻提交了加载(通过请求上下文)和保存(通过缓存过期回调)之间的有趣竞争条件。

使用简单的锁就是掷骰子,保存或加载会赢吗?显然,我们需要在下一次从数据源 (db) 加载之前进行保存。理想情况下,当一个项目从缓存中过期时,它会自动写入它的数据源。当实体从缓存中消失但过期的回调尚未触发时,加载操作可能会进入。在这种情况下,将无法在缓存中找到实体,因此将默认从数据源加载。但是,由于保存操作可能尚未开始,从而导致数据完整性损坏,并且可能会破坏您现在保存的缓存数据。

为了完成同步,我需要一个命名的信号锁,所以我选择了 EventWaitHandle。每个用户创建一个

我还有一个冗余,它超时并通过保存操作记录每 10 秒块。正如我所说,默认值意味着从 MemoryCache 中删除实体之间的 20 秒和意识到触发事件进而保存实体之间的时间。

感谢所有跟随我的漫谈的人。鉴于同步要求的性质,EventWaitHandle 锁是最佳解决方案吗?

【问题讨论】:

  • 可能使用MemoryCache这种方式不是很好的设计。
  • 在复杂程度达到一定程度后,人们总是倾向于将某项设计称为糟糕的设计。但是,我认为跨线程处理缓存并不是不合理的,需要同步所述线程也不是不合理的。关于 MemoryCache,我怀疑是否值得尝试发明一个更好的。我很想听听相反的论点,或者替代方案,或者关于更好的同步机制。
  • 也许redis 可以帮助你。

标签: multithreading repository signals memorycache event-wait-handle


【解决方案1】:

为了完整起见,我想发布我为解决该问题所做的工作。我对设计进行了多项更改,以创建一个更整洁的解决方案,它不需要命名同步对象,并允许我使用简单的锁。

首先,数据实体存储库是存储在请求缓存中的单例。存储库的这个前端与缓存本身是分离的。我将其更改为驻留在会话缓存中,这在下面变得很重要。

其次,我将过期实体的事件更改为通过上面的数据实体存储库进行路由。

第三,我将 MemoryCache 事件从 RemovedCallback 更改为 UpdateCallback**。

最后,我们将它们与数据实体存储库中的常规锁绑定在一起,这是用户的会话和无间隙的到期事件路由,允许锁覆盖加载和保存(到期)操作。


** 这些事件很有趣,因为 A)您不能同时订阅两者,B)在从缓存中删除项目之前调用 UpdateCallback,但在显式删除项目时不会调用它(又名 myCache.Remove (实体)不会调用事件,但 UpdateCallback 会)。我们决定是否将该项目从我们不关心的缓存中强制删除。当用户更换公司或清除他们的购物清单时,就会发生这种情况。所以这些场景不会触发事件,因此实体可能永远不会保存到数据库的缓存表中。尽管出于调试目的可能很好,但不值得使用具有 100% 覆盖率的 RemovedCallback 来处理实体存在的不确定状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多