[ASP.NET] 如果將快取“滑動過期時間”設定為1秒會怎樣?

renke發表於2021-09-09

今天編寫了一個採用ASP.NET Caching的元件,在為它編寫Unit Test的過程中發現了一個有趣的問題,接下來我透過一個簡單的例項說明這個問題。我們在一個控制檯應用中編寫了如下一段程式,這個段程式很簡單:我們透過HttpRuntime的靜態屬性Cache得到表示當前快取的Cache物件,並呼叫其Insert方法對當前的時間實施快取。需要注意的是,我們採用“滑動時間”過期策略,並將這個滑動時間設定為1秒。

   1: class Program

   

   2: {

   

   3:     static void Main(string[] args)

   

   4:     {

   

   5:         string key = Guid.NewGuid().ToString();

   

   6:         HttpRuntime.Cache.Insert(key, DateTime.Now, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 1) );

   

   7:         for (int i = 0; i < 5; i++)

   

   8:         {

   

   9:             Console.WriteLine(HttpRuntime.Cache.Get(key)??"N/A");

   

  10:             Thread.Sleep(500);

   

  11:         }

   

  12:     }

   

  13: }

接下來我們在一個for迴圈中提取快取的時間並將其顯示在控制檯上,每次迭代之後會有0.5秒的休眠時間。根據快取針對滑動時間過期策略,由於我們每隔0.5秒會讀取快取,所以在這段時間內快取是不會過期的。但是如下所示的執行結果告訴我們,新增的快取在1秒之後過期了。

   1: 4/1/2014 2:51:12 PM

   

   2: 4/1/2014 2:51:12 PM

   

   3: N/A

   

   4: N/A

   

   5: N/A

是否是ASP.NET快取機制錯了什麼問題呢?其實不是,真正的原因是我們將滑動過期時間範圍設定得太小了。為了證實這一點,我們按照如下的方式將這個時間設定為2秒。

   1: class Program

   

   2: {

   

   3:     static void Main(string[] args)

   

   4:     {

   

   5:         string key = Guid.NewGuid().ToString();

   

   6:         HttpRuntime.Cache.Insert(key, DateTime.Now, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 2) );

   

   7:         for (int i = 0; i < 5; i++)

   

   8:         {

   

   9:             Console.WriteLine(HttpRuntime.Cache.Get(key)??"N/A");

   

  10:             Thread.Sleep(1000);

   

  11:         }

   

  12:     }

   

  13: }

再次執行我們的程式後會的如下所示的輸出結果,我們可以看到新增的快取並沒有過期。

   1: 4/1/2014 2:59:15 PM

   

   2: 4/1/2014 2:59:15 PM

   

   3: 4/1/2014 2:59:15 PM

   

   4: 4/1/2014 2:59:15 PM

   

   5: 4/1/2014 2:59:15 PM

透過檢視相關原始碼,我們發現這個問題的根源所在:如果我們呼叫Cache的Insert或者Add方法時指定了其slidingExpiration引數,針對該快取項的每次提取操作,系統都會修改快取項的過期時間(當前時間+slidingExpiration)。但是過期時間的修改是由前提的:它要求這個slidingExpiration引數指定的時間必須大於設定的最小時間,這個時間對應著內部型別CacheExpires具有如下定義的靜態只讀屬性TimeSpan MIN_UPDATE_DELTA ,我們可以看到它的時間跨度正是1秒。所以如果我們指定的slidingExpiration引數小於1秒,實際上起不到“滑動過期 ”的作用。當然,在真實的專案中我們並不會將滑動時間設定的如此之短。

   1: internal sealed class CacheExpires

   

   2: {

   

   3:     //其他成員

   

   4:     internal static readonly TimeSpan MIN_UPDATE_DELTA = new TimeSpan(0, 0, 1);

   

   5: }

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/430/viewspace-2817876/,如需轉載,請註明出處,否則將追究法律責任。

相關文章