【问题标题】:Caching and multi-thread synchronization with ReaderWriterLockSlim使用 ReaderWriterLockSlim 进行缓存和多线程同步
【发布时间】:2017-07-10 08:42:04
【问题描述】:

我有一个由一些网络服务客户端调用的网络服务。此 Web 服务返回库存的当前库存列表。这个列表可能很大,有 10K+ 的产品 ID,并且通过读取数据库中的数据来刷新列表需要相当长的时间(约 4 分钟)。我不想每次调用这个网络服务时都刷新列表,因为它可能会消耗我的数据库服务器上的太多资源,并且性能总是不是很好。

我打算做的是给库存清单一些生存时间价值,这意味着当客户要求库存清单时,如果数据没有过期,我会立即返回数据;如果数据已过时,我将从数据库中读取它,更新此列表数据及其生存时间值,然后将刷新的数据返回给 Web 服务客户端。由于可能有多个客户端调用此 Web 服务,看来我需要一个多线程同步(多读单写,ReaderWriterLockSlim 类?)来保护这个库存列表,但我没有'没有找到一个好的设计让这个 web 服务有好的性能:只有一个客户端刷新数据,如果数据还在 time-to 内,其他客户端不必重做工作-live frame 和 web-service 应该在 write 线程完成更新后尽快返回结果

我也想到了另外一个解决方案(也用ReaderWriterLockSlim类):创建一个单独的线程来定期刷新库存列表(write-thread每15分钟刷新一次数据),让所有的web - 服务客户端使用读取线程读取数据。这可能有效,但我不太喜欢它,因为这个解决方案仍然浪费网络服务器的资源。例如,如果没有客户的请求,系统仍然需要每 15 分钟刷新一次库存清单数据。

请提出一些解决方案。谢谢。

【问题讨论】:

  • For example, if there is no client's request, the system still has to refresh the inventory list data every 15 minutes. 您可以跟踪请求发生的最后一个 UTC 日期时间,并且仅当该日期在最后 15 分钟内时才进行刷新。 这确实意味着,如果负载在持续一段时间内处于低水平,数据可能会变得非常陈旧。
  • 如果没有客户的要求,我不必更新库存清单,因为没人关心它。只有当有客户端请求时,如果当前列表已过期,系统必须刷新数据,然后将更新结果返回给客户端。如果有两个请求同时检查列表,我们最终可能会更新两次过期列表,这不是我想要的。我想让第二个线程等待第一个线程完成更新以读取结果。所以我可能不得不使用一些双重多线程锁定。
  • 这行得通——第二个线程阻塞的唯一缺点。

标签: c# multithreading caching


【解决方案1】:

我建议使用MemoryCache

https://stackoverflow.com/a/22935978/34092 可用于检测项目何时过期。 https://msdn.microsoft.com/en-us/library/7kxdx246.aspx 也值得一读。

此时,您编写的代码的第一行(在CacheRemovedCallback 中)应该将值写回MemoryCache - 这将允许读者继续阅读它。

然后它应该获取最新数据,然后将新数据写入 MemoryCache(再次传入 CacheItemPolicy 以允许在删除最新版本时调用回调)。等等等等……

【讨论】:

    【解决方案2】:

    您是否曾经只运行一个服务实例?那么内存缓存对你来说就足够了。或者如果您不想自己实现锁,请使用 ConcurrentDictionary。

    如果您运行该服务的多个实例,建议使用 Redis 等进程外缓存。

    此外,您最终可以维护缓存列表,使其始终与数据库中的内容同步!?

    有很多不同的缓存厂商dotnet和asp.net和asp.net core有不同的解决方案。对于分布式缓存,也有许多不同的选项。只需选择最适合您使用的框架的即可。

    您还可以使用 CacheManager 之类的库来帮助您更轻松地实现所需内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-21
      • 2018-03-10
      • 2011-11-03
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      相关资源
      最近更新 更多