天天看點

無縫的緩存讀取:雙存儲緩存政策起承轉結

最近在做一個WEB的資料統計的優化,但是由于資料量大,執行一次SQL統計要比較長的時間(一般700ms算是正常)。

正常的做法隻要加個緩存就好了。

但是同時業務要求此資料最多1分鐘就要更新,而且這一分種内資料可能會有較多變化(而且原系統不太易擴充)。

也就是說緩存1分鐘就要失效重新統計,而且使用者通路這頁還很是頻繁,如果使用一般緩存那麼使用者體驗很差而且很容易造成逾時。

看到以上需求,第一個進入我大腦的就是從前做遊戲時接觸到的DDraw的雙緩沖顯示方式。

無縫的緩存讀取:雙存儲緩存政策起承轉結

在第一幀顯示的同時,正在計算第二幀,這樣讀取和計算就可以分開了,也就避免了讀取時計算,提高了使用者體驗。

我想當然我們也可以将這種方式用于緩存的政策中,但這樣用空間換取時間的方式還是得權衡的,因為并不是所有時候都值得這麼做,但這裡我覺得這樣做應該是最好的方式了。

注:為了可以好好示範,本篇中的緩存都以IEnumerable的形式來存儲,當然這個文中原理也可以應用在WebCache中。

這裡我使用以下資料結構做為存儲單元:

有了這個資料結構我們就可以将資料實作兩份存儲。再利用一些讀寫政策就可以實作上面我們講的緩存方式。

整個的緩存我們使用如下緩存類來控制:

這裡我隻實作了插入一個緩存,以及讀取的方法。

我讀取緩存單元的邏輯是這樣的

無縫的緩存讀取:雙存儲緩存政策起承轉結

從2個不同緩存讀取當然是很容易了,但是比較複雜的就是向緩存寫入的過程:

無縫的緩存讀取:雙存儲緩存政策起承轉結

這裡讀取資料以及寫入緩存時我使用了一個委托,在其它線程中僅在需要執行時才會執行。

這裡除了首次寫入緩存占用主線程時間(讀取要等待)以外,其它時間都可以無延時的讀取,實作了無縫的緩存。

但我們在委托中要操作緩存的元素Medium,是以要傳遞參數進其它線程,是以我這裡使用了一個輔助類來傳遞參數進入其它線程:

這樣我們就實作了在另個線程讀取資料的過程,這樣就在任何時候讀取資料時都會無延時直接讀取了。

最後我們寫一個主函數來測試一下效果

得到如下資料:

無縫的緩存讀取:雙存儲緩存政策起承轉結

這樣就實作了平滑的讀取緩存資料而沒有任何等待時間

當然這裡還有些問題,比如說傳遞不同參數時的解決方法,但是由于我僅是在一個統計時需要這種緩存提高性能,是以暫沒有考慮通用的傳參方式。

如果大家對這個話題感興趣,歡迎讨論。

示例下載下傳: