MemoryCache 有一個好用但比較少去碰觸的功能,那就是當你的 cache 過期時,怎麼透過事件來通知你做後續的處理
cache expired 需要透過事件通知在實際生活上有很多應用情境,比如即時刷新最新比賽記錄,暫存只設定 30 秒,當超過這個時間就會自動把最新結果廣播給所有用戶
但今天我的情境是將 cache 當成一個批次處理的概念,也就是我希望在 5 分鐘內蒐集資訊,當超過 5 分鐘的快取時間後,我就將這個批次拿到的所有資料寫到 db
MemoryCache 裡的 CacheItemPolicy 有提供了一個 RemovedCallback 的事件函式,可以很方便的讓你去處理當 cache key expired 時要怎麼處理
使用方式也非常簡單,以下例子為傳入 key 跟 欲設定的過期秒數,若過期的話希望執行什麼樣的 callback 函式
static ObjectCache _cache = MemoryCache.Default;
public static void Set(string key, int expiredSeconds)
{
var policy = new CacheItemPolicy();
var cacheTime = new TimeSpan(0, 0, expiredSeconds);
policy.AbsoluteExpiration = DateTimeOffset.Now.Add(cacheTime);
policy.RemovedCallback = new CacheEntryRemovedCallback(OnExpire);
_cache.Set(key, key + "_value", policy);
}
public static void OnExpire(CacheEntryRemovedArguments cacheEntryRemovedArguments)
{
//process in db
var expired_value = cacheEntryRemovedArguments.CacheItem.Value;
Console.WriteLine($"Key [{cacheEntryRemovedArguments.CacheItem.Key}] Expired. Reason: {cacheEntryRemovedArguments.RemovedReason.ToString()} {DateTime.Now.ToString("HH:mm:ss")}");
}
主函式的互動部份則是讓操作者輸入 cache key 的值,以及要過期的秒數,並加以觀察過期後的事件輸出
static void Main(string[] args)
{
while (true)
{
Console.WriteLine($"input key");
var key = Console.ReadLine();
if (key == "")
break;
var isExist = _cache.Contains(key);
if (isExist)
{
Console.WriteLine($"Get from cache: {_cache[key].ToString()} {DateTime.Now.ToString("HH:mm:ss")}");
}
else
{
Console.WriteLine("input time(secs) to be expired");
var expiredTime = int.Parse(Console.ReadLine());
Set(key, expiredTime);
Console.WriteLine($"cache set done {DateTime.Now.ToString("HH:mm:ss")}");
}
}
}
測試
在 16:30:02 建立了 cache,並設定於 10 秒後過期,所以理當會在 16:30:12 過期
17:30:02 正常取到值
17:30:04 正常取到值
17:30:05 正常取到值
17:30:06 正常取到值
17:30:07 正常取到值
*17:30:12 過期
17:30:20 自動觸發 expired callback 事件
在 callback 的執行上是以 10 秒為一週期,如果在 16:20:12 過期之後沒有取值的任何動作,則 callback 的執行會在 16:20:20 這個時間點才會被執行
於此,我們可以再做另一個實驗證實這一點
17:38:33 建立 cache, 10 秒後過期,將於 17:38:43 過期,在上面的例子,如果不做取值的任何動作,將會在 17:38:50 回收時才會觸發事件
17:38:34 正常取到值
17:38:35 正常取到值
17:38:37 正常取到值
17:38:42 正常取到值
*17:38:43 過期
17:38:44 取值後發現 cache 已過期,觸發 expired callback 事件
參考來源