文章出處

今天編寫了一個采用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: }

文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()