[轉發][非原創]oschina上的一種雙快取思路
舉個例子:oschina 的首頁,訪問量很高,這個頁面必須得快取,oschina 使用的是 ehcache。
一般我們的快取偽碼如此:
List<T> objs = (List<T>)CacheManager.get(cache_region, key);
if(objs == null)
{
objs = database_query(beanClass, sql, params);
CacheManager.set(cache_region, key, (Serializable)objs);
}
return objs;
問題是一旦快取失效需要從資料庫重新載入資料的時候,大量的併發資料庫訪問會導致響應超級慢,也就是所謂的雪崩。
目前我們對這個問題的處理方法,我簡單的說一下思路,具體的程式碼等有空再整理出來
假設我們前面舉的例子中所使用的快取region(region1),設定了自動失效時間為5分鐘,相當於說每5分鐘就會有一次發現訪問首頁很卡。因此引入了第二個快取 region (region2) ,這個快取的物件不會自動失效,也就說該區域的資料長期有效。
region2 的配置:
<cache name="icache-global"
maxElementsInMemory="100"
eternal="true"
overflowToDisk="true"
/>
引入了第二個長效的region後,資料的讀取流程是這樣的:
- 從 region1 讀取資料,有則直接返回
- region1 沒資料則啟動資料更新執行緒(下面介紹),然後從 region2 讀資料,有則返回
- region2 也沒有資料
這種情況屬於系統剛剛啟動,快取還沒有填充資料的情況,沒辦法,這時候肯定會卡,或者你應該在系統啟動的時候,自行填充一下資料,很簡單,我一般在tomcat啟動後,用命令訪問下首頁就有了快取資料。
這樣做的目的是為了正常的快取失效後,無需等待重新從資料庫中獲取資料,而是直接在 region2 中獲取資料並返回。因此對使用者來講,不會感覺請求被堵塞。
雖然請求順暢了,但是資料還得更新,因此重要的還是啟動資料更新執行緒是如何處理的。
執行緒本身所執行的方法很簡單,無非就是到資料庫中讀取資料,然後將資料填充到 region1 ,但記得要同時填充到 region2,以確保下次快取失效時,獲取得到的是最新的資料。
就這麼簡單,其實也可以工作,但會有一個問題:假設快取失效的時候,同時來了100個請求,那麼這100個請求會同時啟動100個資料更新執行緒,這100個資料更新執行緒會到資料庫執行同樣的SQL語句獲得同樣的結果,因此這種做法對資料庫的壓力並沒有降低。
於是我需要線上程的執行方法裡做一些調整,下面是偽碼:
String data = CacheManager.get(String.class, region1, key);
if(data == null){
ReentrantLock lock = g_locks.get(key);
if(!lock.tryLock())
return null;
try
{
//1. 執行SQL查詢獲取資料
//2. 資料填充到 region1
//3. 資料填充到 region2
}
finally
{
lock.unlock();
}
}
首先還是要判斷下快取資料是否已存在,然後使用了一個 ReentrantLock 鎖物件來控制不讓多餘的執行緒去執行資料更新過程。
這只是個大體的思路,僅供參考,目前已經在 oschina 上使用。
別提什麼頁面靜態化,我對那個一點都不感冒。
相關文章
- 快取淘汰、快取穿透、快取擊穿、快取雪崩、資料庫快取雙寫一致性快取穿透資料庫
- 快取問題(一) 快取穿透、快取雪崩、快取併發 核心概念快取穿透
- HTTP快取是怎樣的一種存在HTTP快取
- 快取與資料庫雙寫一致性幾種策略分析快取資料庫
- 開發可能會用到的三種快取key快取
- (轉)快取更新的套路快取
- 說一下幾種常用的前端快取前端快取
- 轉載快取快取
- 另一種快取,Spring Boot 整合 Ehcache快取Spring Boot
- Android動態請求許可權的工具類(轉載、非原創)Android
- 新增發快遞上門取件的介面-快遞鳥預約上門取件API對接API
- 我是誰?|一名雙非、大齡青年的轉行之路
- 快取與資料庫的雙寫一致性快取資料庫
- 雲上的分散式快取分散式快取
- 使用快取(Cache)的幾種方式,回顧一下~~~快取
- HTTP三種快取方式HTTP快取
- 【原創】分散式之一行程式碼解決快取擊穿問題分散式行程快取
- Git常用命令(非原創)Git
- 【譯】關於四種快取的故事快取
- [原創]一種通用DLL劫持技術研究
- 快取更新的四種策略及選取建議快取
- 資料庫與快取雙寫一致性資料庫快取
- 快取問題(四) 快取穿透、快取雪崩、快取併發 解決案例快取穿透
- MyBatis快取機制(一級快取,二級快取)MyBatis快取
- Mybatis的快取——一級快取和原始碼分析MyBatis快取原始碼
- 一種跳板機的實現思路
- HybridCache:一種簡單的native與webview共享快取的設計WebView快取
- Mybatis 一級快取和引發的問題MyBatis快取
- 一種軟體加密思路加密
- 【Redis場景2】快取更新策略(雙寫一致)Redis快取
- Redis雙寫一致性與快取更新策略Redis快取
- 淺談快取寫法(一):快取的雪崩和穿透快取穿透
- 不知道這4種快取模式,敢說懂快取嗎?快取模式
- SpringBoot快取管理(一) 預設快取管理Spring Boot快取
- Java高併發快取架構,快取雪崩、快取穿透之謎Java快取架構穿透
- 如何保證快取與資料庫的雙寫一致性?快取資料庫
- PHP 資料採集的一種思路PHP
- mybatis快取之一級快取(一)MyBatis快取
- 快取與資料庫雙寫一致性 深度分析快取資料庫