文章目錄
- 引言
- 詳解緩存的設計和演進
- 基于緩存存儲運算結果
- 鎖分段散列減小鎖粒度
- 異步化提升處理效率
- 原子化避免重復運算
- 小結
- 參考
引言
本文將基于并發編程和算法中經典的哈希取模、鎖分段、 異步化、原子化。這幾個核心設計理念編寫逐步推演出一個相對高效的緩存工具,希望對你有所啟發。
我是 SharkChili ,Java 開發者,Java Guide 開源項目維護者。歡迎關注我的公眾號:寫代碼的SharkChili,也歡迎您了解我的開源項目 mini-redis:https://github.com/shark-ctrl/mini-redis。
為方便與讀者交流,現已創建讀者群。關注上方公眾號獲取我的聯系方式,添加時備注加群即可加入。
詳解緩存的設計和演進
基于緩存存儲運算結果
我們有一批數據需要通過運算才能獲得結果,而每一次運算大約耗時是500ms
,所以為了避免重復運算導致的等待,我們希望對應數據第一次運算的結果直接緩存到容器中,后續線程可直接通過容器獲得結果:
于是我們就有了第一個版本,利用緩存避免非必要的重復計算,從而提升程序在單位時間內的吞吐量
public class ComputeCache {public final Map<Integer, Integer> cache = new HashMap<>();public synchronized int compute(int arg) {if (cache.containsKey(arg)) {//若存在直接返回結果return cache.get(arg);} else {//若不存在則計算后緩存并返回int result = doCompute(arg);cache.put(arg, result);return result;}}//模擬耗時的計算private int doCompute(int key) {ThreadUtil.sleep(500);return key << 1;}public synchronized int size() {return cache.size();}}
我們利用下面這段單元測試來驗證緩存的性能和正確性,這里筆者也簡單介紹一下幾個比較核心的點:
- 聲明本機CPU核心數+1的線程數執行并發運算
- 利用倒計時門閂控制線程并發流程起止,保證準確感知所有運算任務結束后,執行耗時統計
- 利用容器中最直觀且容易檢查出錯誤的屬性size進行比對判斷我們的緩存是否正確
最終在筆者的機器下5000
并發的耗時大約是26765ms
,整體還是不太符合我們的預期:
//初始化緩存工具<