65.9K
CodeProject 正在变化。 阅读更多。
Home

SaintModeCache.Net

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (3投票s)

2016年9月25日

CPOL

4分钟阅读

viewsIcon

11658

SaintModeCache 是一个线程安全的内存缓存包装器,用于性能优化。它能够在缓存过期后继续提供过时内容,同时通过一个非阻塞的单线程重新填充缓存。

引言

SaintModeCache.Net 是受 Varnish 圣人模式缓存启发的库。圣人模式是指在缓存过期后,缓存继续提供过时内容。当源内容不可用时,就会发生这种情况,并且只要缓存无法刷新,就会一直如此。

为 .NET 创建的 SaintModeCache 库遵循类似的原则,但应用于数据层而不是 Varnish 的 HTML 缓存。

当与访问频繁的慢速或不可靠数据服务集成时,它非常有用,可以保护用户体验免受加载缓慢的影响。一旦数据被缓存,它就会保留在内存中,并在过期时通过一个后台线程进行刷新。这可以确保网站始终保持响应。

该库的主要优点如下:

  • 保护用户体验免受运行缓慢的进程影响
  • 允许在缓存刷新之前使用过时数据
  • 防止缓存未命中导致依赖服务或数据库过载

安装

要安装 SaintModeCache.Net,请在程序包管理器控制台中运行以下命令。

PM> Install-Package SaintModeCache.Net

演示站点

请参阅 SaintCacheMode.Net Demo 站点上的 SaintModeCache.Net 示例。

这聚合了多个 RSS 订阅源,这些订阅源正在使用 SaintModeCache 在后台刷新。没有其他缓存实现,所有请求都实时在服务器端渲染。

缓存你,很简单

SaintModeCache.Net 易于使用,可以包装任何数据访问方法。它的工作方式与其他缓存类似,并在底层使用 MemoryCache

要利用圣人模式,在从缓存请求数据时始终提供更新委托。该委托仅在缓存未命中时调用。这确保调用者始终同步接收数据,尽管有时可能是过时的。好吧,你不能什么都拥有!

首先,设置一个 static 引用以实例化的缓存来持久化内存中的数据。

static SaintModeCache Cache = new SaintModeCache();

接下来,开始使用圣人模式的所有优势来获取和缓存数据。

var cacheKey = "customer123"; 
var cacheTimeInSeconds = 60; 
var customerModel = Cache.GetOrCreate(cacheKey, 
                          (key, cancelToken) => slowUnreliableService.GetCustomerModel(key),
                          cacheTimeInSeconds);

当缓存为空时,该方法将阻塞所有调用者,并允许一个线程从慢速不可靠的服务中获取数据。

一旦更新委托完成,缓存的数据将立即返回给所有调用者。60 秒后,对同一缓存键的下一次请求将触发一个后台线程来更新缓存,但同时返回当前缓存的值。在后台更新缓存后,后续的调用者将收到更新后的数据。

保持线程安全

SaintModeCache.Net 的关键在于确保只有一个线程可以访问刷新缓存的函数。为了实现这一点,它通过后台线程触发按需刷新,并继续向调用者提供过时数据。它使用锁定来确保只有一个刷新线程成功,这可以防止在缓存过期且网站负载较高时数据源过载。锁定作用于当前缓存键,允许多个数据获取并行进行。

如果由于数据尚不可用而导致缓存未命中,它将阻塞对同一缓存键的所有请求,直到一个线程提供可缓存的数据供所有请求使用。这同样可以防止在负载较高时数据源过载,并确保调用者始终收到数据。

内部锁定

每个缓存键的锁定实现使用 string.Intern 和缓存键本身。这是一种非常强大的技术,因为它允许跨多个线程甚至 AppDomain 对唯一的 string 进行锁定。

string.Intern 返回 .NET 内部池中 string 的单个引用。这确保了相同值的给定 string 只有一个引用。对未内部化的 string 进行锁定是不够的,因为它只会锁定确切的 string 实例。

例如,以下代码会在使用特定 myLock 实例的 2 个请求之间进行锁定。

  string myLock = "myLockStr";
  lock (myLock) {
     // do something
  }

然而,以下使用 string.Intern 的代码将在所有执行相同 string 值的代码之间进行锁定。

  lock (string.Intern("myLockStr")) {
     // do something
  }

还可以使用以下代码尝试访问锁而不进行阻塞。这允许库尽早终止不成功的刷新线程。

 if (Monitor.TryEnter(lockObj))
 {
    try {
      // I have the lock

    } finally {
      Monitor.Exit(lockObj);
    }
 } else {
    // I don't have the lock
 }

摘要

SaintModeCache.Net 为 .NET 应用程序中的数据缓存提供了一个快速简便的解决方案,并且可以用来补充其他技术。随着丰富沉浸式体验的趋势不断增加,管理近乎实时数据的性能挑战也随之增加。

要了解有关该库的更多信息,请访问以下链接:

© . All rights reserved.