標籤:
緩衝的英文名稱叫做 Cache,是個法國詞彙,每個字元裡都流淌著高貴的血統。緩衝的概念最早來源於1967年的一篇電子工程期刊論文,論文作者將「Cache」賦予了「safe keeping storage」的概念,用於電腦領域。
緩衝最早出現主要是為了老大哥 CPU 服務的,為了減少 CPU 訪問記憶體所需平均時間,增加了緩衝技術。隨著硬體技術和作業系統的發展,這部分技術牢牢地掌握在一些巨型晶片公司手裡,那裡的程式員每天遊走在 CPU、Cache、SRAM、、write-through 和 write-back 之間,彷彿掌控著天地間每一個流動位元組的意義,自信而優雅,我們把他們叫做文藝程式員。如果你想做一個文藝程式員,請用 Google 百度一下「CPU 緩衝」,如果你不會用 Goolge,那麼,最好離文藝遠一點。
普通程式員需要關注什麼類型的緩衝呢?比如磁碟緩衝、Web 緩衝、網路緩衝、分布式緩衝,等等,這些是我們在開發系統軟體和互連網服務時常常要用到的技術。那麼,二逼程式員呢?哦,他們只要知道用 Hashtable 做緩衝就夠了。
緩衝的意義是什嗎?簡單來說,緩衝是儲存資料的一個臨時場所,由於擷取未經處理資料的代價太大了,所以,我們會把一些使用頻繁的資料放到一個更容易讀取,操作更快的池子(一般是記憶體)裡,為這些資料分門別類,打上標籤,這樣使用者發來請求的時候,我們先在緩衝池裡進行快速檢索,如果拿到資料就直接返回給使用者;如果沒有,再去資料庫或其他介質擷取未經處理資料返給使用者,同時把該資料打上標籤,放入緩衝池。
就像你開了一個鞋店,店裡永遠會存放一部分熱銷和新款的皮鞋,如果客戶每次看鞋買鞋的時候,你都要說等一哈,庫房就在五公裡外,我去去就回。等你熱氣騰騰跑完一個十公裡回來,你發現,連女消費者都走了。
網路世界也是一樣,如果沒有緩衝,使用者所有的請求都會直接穿透層層網路,打到資料庫和磁碟 IO 上,隨著資料量的增加,使用者每次請求的時間會越來越長,這樣的後果是,磁碟不高興,資料庫不高興,使用者也不高興,然後就是資料庫率先罷工,使用者離你而去,你,依然木有女朋友。
既然緩衝這麼重要,擁有大量使用者的互連網應用都應該增加快取服務了,那麼是不是搞個 Hashtable 就可以了呢?我們可以先瞭解一些緩衝的術語。
使用者發起了一個熱點資料的請求,系統接收到這個請求之後,就需要根據使用者的資料資訊(key)去緩衝池裡尋找資料,如果根據使用者提供的 Key 找到了這個條目,並返回給使用者,這個過程叫一次快取命中。
如果在緩衝裡沒找到需要的資料,在緩衝空間還有閒置情況下,系統會去未經處理資料源(一般是資料庫)擷取資訊,返回給使用者,並把資料條目儲存到緩衝中,以備不時之用。如果緩衝空間已經達到上限,那麼就要根據緩衝替代策略,把舊的資料對象銷毀,把新的對象放入緩衝池。
對於快取服務的設計來說,命中率高的緩衝系統,效能越好,命中率高,消耗的時間和資源越少。所以快取服務並不是簡單的搭建一個 Memcached、Ehcache 或 Redis 就可以了,相關的技術,應用在合適的業務情境中,才能最大化的利用緩衝的價值。
上述情境中,緩衝沒有命中的時候,系統會從未經處理資料源中擷取資料,一般是資料庫或檔案系統,然後再把資料放入緩衝池中。這個過程需要的時間和空間,就是緩衝成本。
一般為了避免緩衝成本過高,系統初始化的時候,會同時進行緩衝池的初始化,把我們需要的,已知的資料儘可能多的提前放入緩衝池,這樣可以最大程度的提升快取命中率,降低緩衝成本。
當緩衝中的資料需要更新的時候,說明緩衝中的資料已經失效了,這時候就需要有相關的服務進行即時的資料更新,同時要保證資料的一致性,不能讓系統拿到已經失效的資料到處去招搖撞騙,這種情況,系統和使用者的內心,都是拒絕的。
編程小球們初入江湖的時候,一般會覺得記憶體是可以無限使用了,看到伺服器上標著 64G 記憶體這樣金光閃閃的配置之後,他們更覺得「廣闊天地,大有可為」,於是在系統裡 new 出了一個又一個的 Hashtable,然後不停的往裡面加入資料讀出資料,事實上,如果是三少系統(使用者少、資料少,功能少),這樣做一時半會還真出不了系統問題。如果是系統級的快取服務,要考慮的事情就比較多了。
每個緩衝產品,一般都會有一個類似 maxmemory 的最大記憶體使用量參數,這個參數肯定是小於實體記憶體的。一旦快取資料達到上限,而又出現緩衝沒有命中的情況時,系統就會踢出一些老弱病殘的快取資料,加入新條目。判斷老弱病殘的標準是什麼呢?這就是替代策略。最理想的做法當然是把最沒用的資料踢出去,但是,做到最理想永遠是最難的,就像你永遠想找到團隊裡最沒用的那一個將其淘汰掉,但執行的時候總是極其艱難。因為除了資料,還有情緒。
幸好,資料沒情緒,我們可以通過演算法搞定這件事。
常用的一些演算法包括:FIFO、LFU、LRU、LRU2、ARC等。
FIFO 就是先進先出,一種非常簡單的演算法,快取資料達到上限的時候,最先進入緩衝的資料會最先被踢出去。很多老員工看到這一條都義憤填膺,所以,這個演算法註定是不被喜歡的,但是由於它簡單直接,很多開發人員喜歡。嗯,有些企業老闆也比較喜歡。Second Chance 和 CLock 是基於 FIFO 的改進,演算法更加先進合理,也更複雜,裡寫了也沒人看,感興趣的話,Google「緩衝演算法 CLock」等。
LFU 的全稱是 Least Frequently Used,最少使用演算法,系統會為每個對象計算使用頻率,最不常用的緩衝對象會被踢走,簡單粗暴。缺點是,一個傳統工業時代曾經被重用過的老員工,在互連網時代沒用了,由於其前期使用頻率很高,吃老本,所以資料會一直儲存在緩衝系統中,反而是後起之秀,往往會遭遇到誤殺的不公正待遇。差評。
LRU 的全稱是 Least Recently Used,也就是最近最少使用演算法。基本思路是,如果一個資料最近一段時間被使用的頻率很少,那將來被用到的可能性也會很低。看到這兒,那些近期沒什麼開發工作單位的童靴,你們要小心了。好評。
LRU2 和 ARC 都是基於 LRU 的改進,有興趣的可以上網查查。
很多我們耳熟能詳的緩衝產品,比如 Memcached、Redis、Ehcache、OSCache等,都參考了類似的演算法,要麼進行加強,要麼進行簡化,目標就是提升緩衝的命中率,降低緩衝成本。
瞭解了這些夠不夠?當然不夠,你還需要進行大量的實踐和業務驗證,才能找到最合適你的系統的緩衝策略。另外,當你的資料量、訪問量和可靠性要求越來越高的時候,你還需要考慮分布式緩衝,以提升緩衝容量和擴充性。但是緩衝分布了,又帶來更多的問題,比如單點失效,命中率,並發,資料同步等等。這樣寫起來就木有完了是不是?所以給大家推薦兩篇文章:
一種基於「哨兵」的分布式緩衝設計:
[http://blog.lichengwu.cn/architecture/2015/06/14/distributed-cache/]
分布式緩衝的一起問題:
http://timyang.net/data/cache-failure/
原文連結:http://chijianqiang.baijia.baidu.com/article/148570
cashe(緩衝)【轉】