***{轉自:緩存設計的一些思考}***算法
互聯網架構中緩存無處不在,某廠牛人曾經說過:」緩存就像清涼油,哪裏不舒服,抹一下就行了」。高品質的存儲容量小,價格高;低品質存儲容量大,價格低,緩存的目的就在於」擴充」高品質存儲的容量。本文探討緩存相關的一些問題。sql
LRU替換算法緩存
緩存的技術點包括內存管理和替換算法。LRU是使用最多的替換算法,每次淘汰最久沒有使用的元素。LRU緩存實現分爲兩個部分:Hash表和LRU鏈表,Hash表用於查找緩存中的元素,LRU鏈表用於淘汰。內存常以Slab的方式管理。數據結構
上圖是Memcache的內存管理示意圖,Memcache以Slab方式管理內存塊,從系統申請1MB大小的大塊內存並劃分爲不一樣大小的Chunk,不一樣Slab的Chunk大小依次爲80字節,80 * 1.25,80 * 1.25^2, …。向Memcache中添加item時,Memcache會根據item的大小選擇合適的Chunk。多線程
Oceanbase最初也採用LRU算法,只是內存管理有些不一樣。Oceanbase向系統申請2MB大小的大塊內存,插入item時直接追加到最後一個2MB內存塊的尾部,當緩存的內存量太大須要回收時根據必定的策略整塊回收2MB的內存,好比回收最近最少使用的item所在的2MB內存塊。這樣的作法雖然不是特別精確,可是內存管理簡單,對於系統初期頗有好處。架構
緩存鎖nosql
緩存須要操做兩個數據結構:Hash表和LRU鏈表。多線程操做cache時須要加鎖,比較直接的作法是總體加一把大鎖後再操做Hash表和LRU鏈表。有以下的優化思路:優化
LIRS思想spa
Cache有兩個問題:一個是前面提到的下降鎖粒度,另外一個是提升精準度,或者稱爲提升命中率。LRU在大多數狀況下表現是不錯的,可是有以下的問題:.net
之因此會出現上述一些比較極端的問題,是由於LRU只考慮訪問時間而沒有考慮訪問頻率,而LIRS在這方面作得比較好。LIRS將數據分爲兩部分:LIR(Low Inner-reference Recency)和HIR(High Inner-reference Recency),其中,LIR中的數據是熱點,在較短的時間內被訪問了至少兩次。LIRS能夠當作是一種分級思想:第一級是HIR,第二級是LIR,數據先進入到第一級,當數據在較短的時間內被訪問兩次時成爲熱點數據則進入LIR,HIR和LIR內部都採用LRU策略。這樣,LIR中的數據比較穩定,解決了LRU的上述兩個問題。LIRS論文中提出了一種實現方式,不過咱們能夠作一些變化,如能夠實現兩級cache,cache元素先進入第一級cache,當訪問頻率達到必定值(好比2)時升級到第二級,第一級和第二級均內部採用LRU進行替換。Oracle Buffer Cache中的Touch Count算法也是採用了相似的思想。
SSD與緩存
SSD發展很快,大有取代傳統磁盤之勢。SSD的發展是否會使得單機緩存變得毫無必要咱們無從得知,目前,Memory + SSD + 磁盤的混合存儲方案仍是比較靠譜的。SSD使用能夠有以下不一樣的模式:
固然,隨着SSD的應用,我想減小緩存鎖粒度的重要性會愈來愈突出。
總結&推薦資料
到目前爲止,咱們在SSD,緩存相關優化的工做仍是比較少的。從此的一年左右時間,咱們將會投入必定的精力在系統優化上,相信到時候再來總結的時候認識會更加深入。我想,緩存相關的優化工做首先要作的是根據需求制定一個大體的評價標準,接着使用實際數據作一些實驗,最終可能會同時保留兩到三種實現方式或者配置略微有所不一樣的緩存實現。緩存相關的推薦資料以下:
[1] Touch Count Algorithm. http://youyus.com/wp-content/uploads/resource/Shallahamer%20TC4a.pdf