Cache 和 Buffer 都是緩存,主要區別是什麼?


不知道為什麼這問題突然火了,更新一個一句話總結:

cache 是為了彌補高速設備和低速設備的鴻溝而引入的中間層,最終起到**加快訪問速度**的作用。

而 buffer 的主要目的進行流量整形,把突發的大數量較小規模的 I/O 整理成平穩的小數量較大規模的 I/O,以**減少響應次數**(比如從網上下電影,你不能下一點點數據就寫一下硬碟,而是積攢一定量的數據以後一整塊一起寫,不然硬碟都要被你玩壞了)。

=======================

以下觀點屬於程老大,無節操默寫:

1、Buffer(緩衝區)是系統兩端處理速度平衡(從長時間尺度上看)時使用的。它的引入是為了減小短期內突發I/O的影響,起到流量整形的作用。比如生產者——消費者問題,他們產生和消耗資源的速度大體接近,加一個buffer可以抵消掉資源剛產生/消耗時的突然變化。

2、Cache(緩存)則是系統兩端處理速度不匹配時的一種折衷策略。因為CPU和memory之間的速度差異越來越大,所以人們充分利用數據的局部性(locality)特徵,通過使用存儲系統分級(memory hierarchy)的策略來減小這種差異帶來的影響。

3、假定以後存儲器訪問變得跟CPU做計算一樣快,cache就可以消失,但是buffer依然存在。比如從網路上下載東西,瞬時速率可能會有較大變化,但從長期來看卻是穩定的,這樣就能通過引入一個buffer使得OS接收數據的速率更穩定,進一步減少對磁碟的傷害。

4、TLB(Translation Lookaside Buffer,翻譯後備緩衝器)名字起錯了,其實它是一個cache.


倆英文單詞,不先看看本義嗎?雖然都是抽象單詞,但在各個地方都有具象的應用。

Buffer常見的是這個:

(來源:train stop buffer bumper)

對,就是鐵道端頭那個巨大的彈簧一類的東西。作用是萬一車沒停住,撞彈簧上減速慢,危險小一些。叫緩衝

Cache常見的是這個:

(來源:https://upload.wikimedia.org/wikipedia/commons/6/68/Bear_caches.jpg)

沒錯,就是一種保管箱。看到右邊那個被銹掉的Food Cache沒?這是部署在森林裡的存應急物資的保管箱。功能是把你需要用的東西放在更容易拿到的地方。雖然常用準確翻譯叫緩存,但個人以為意思表達的不對,丟了一半的功能。台灣的翻譯更好,叫快取

相信看完這些應該不用我說區別了?

哎呀還是賣弄一下吧。

簡單說,Buffer的核心作用是用來緩衝,緩和衝擊。比如你每秒要寫100次硬碟,對系統衝擊很大,浪費了大量時間在忙著處理開始寫和結束寫這兩件事嘛。用個buffer暫存起來,變成每10秒寫一次硬碟,對系統的衝擊就很小,寫入效率高了,日子過得爽了。極大緩和了衝擊。

Cache的核心作用是加快取用的速度。比如你一個很複雜的計算做完了,下次還要用結果,就把結果放手邊一個好拿的地方存著,下次不用再算了。加快了數據取用的速度。

所以,如果你注意關心過存儲系統的話,你會發現硬碟的讀寫緩衝/緩存名稱是不一樣的,叫write-buffer和read-cache。很明顯地說出了兩者的區別。

當然很多時候宏觀上說兩者可能是混用的。比如實際上memcached很多人就是拿來讀寫都用的。不少時候Non-SQL資料庫也是。嚴格來說,CPU里的L2和L3 Cache也都是讀寫兼用——因為你沒法簡單地定義CPU用它們的方法是讀還是寫。硬碟里也是個典型例子,buffer和cache都在一塊空間上,到底是buffer還是cache?

不過仔細想一下,你說拿cache做buffer用行不行?當然行,只要能控制cache淘汰邏輯就沒有任何問題。那麼拿buffer做cache用呢?貌似在很特殊的情況下,能確定訪問順序的時候,也是可以的。簡單想一下就明白——buffer根據定義,需要隨機存儲嗎?一般是不需要的。但cache一定要。所以大多數時候用cache代替buffer可以,反之就比較局限。這也是技術上說cache和buffer的關鍵區別。

——————

補充1:不要誤解Buffer就是用來寫的,Cache就是用來讀的。讀可以用Buffer嗎?當然可以,比如你想一批一批地處理讀取而非有啥處理啥的時候,就可以用讀buffer。寫當然也可以用cache,比如你的寫入有很高的隨機性的時候。具體什麼場景用Buffer什麼場景用Cache要根據場景的具體需要決定。

補充2:不要誤解Cache或Buffer就一定是內存或者存在什麼高速媒介上的東西。只要相對高速即可。我完全可以在硬碟上存Cache,比如有些遊戲會在運行時建立預編譯的shader(暴露年齡),這本質上就是一種cache,它存在速度緩慢的硬碟上,因為讀硬碟依舊比重新編譯要快。Buffer也同理,例如NTFS文件系統自己就有Logging Buffer,這個甚至明確拒絕放在任何易失緩存里。


Cache 是有 source of truth 的,裡面的數據如果沒有了可以去 source of truth 重新獲取,最多就是浪費一下性能而已。Buffer 不一定存在 source of truth,往裡面寫的東西寫不下了或者丟了就永久丟了。


cache還有一個就是用來保持冗餘的、可以被重複計算的、計算後的數據的,這個你叫buffer就不行。


要問Cache和Buffer的區別,首先要問另一個問題:為何會存在Cache和Buffer?

為了提速。

從功能上看,PC挺簡單的,就是「輸入輸出」設備:參數輸入進設備(比如滑鼠點擊),經過計算(CPU),把結果輸出到目標設備(比如印表機、顯示器、網路)。

我們當然希望PC的速度越快越好,如果說有什麼因素在拖慢PC的速度,那也就是在2個過程上起作用:「計算」以及「輸入/輸出」。

在「計算」上,我們都知道I5肯定比I3快,I9肯定比I5快,這種速度差拼的是純硬體性能,為了提速,除了花錢購買高端硬體,別無他法。

另一方面,在「輸入/輸出」(也就是I/O)的過程中拖慢PC的因素,卻可以不用花錢就可以解決。這些因素包括I/O過程本身的延遲,以及高速設備與低速設備交互時的等待延遲。Cache和Buffer就是從這2個方向上以軟體的方法,以不花錢的方法給PC提速。

舉栗說明。

假設某地發生了自然災害(比如地震),居民缺衣少食,於是派救火車去給若干個居民點送水。

救火車到達第一個居民點,開閘放水,老百姓就拿著盆盆罐罐來接水。

假如說救火車在一個居民點停留100分鐘放完了水,然後重新儲水花半個小時,再開往下一個居民點。這樣一個白天來來來回回的,也就是4-5個居民點。

但我們想想,救火車是何等存在,如果把水龍頭完全打開,其強大的水壓能輕易衝上10層樓以上, 10分鐘就可以把水全部放完。但因為居民是拿盆罐接水,100%打開水龍頭那就是給人洗澡了,所以只能打開一小部分(比如10%的流量)。但這樣就降低了放水的效率(只有原來的10%了),10分鐘變100分鐘。

那麼,我們是否能改進這個放水的過程,讓救火車以最高效率放完水、儘快趕往下一個居民點呢?

方法就是:在居民點建蓄水池。

救火車把水放到蓄水池裡,因為是以100%的效率放水,10分鐘結束然後走人。居民再從蓄水池裡一點一點的接水。

我們分析一下這個例子,就可以知道Cache的含義了。

救火車要給居民送水,居民要從救火車接水,就是說居民和救火車之間有交互,有聯繫。

但救火車是「高速設備」,居民是「低速設備」,低速的居民跟不上高速的救火車,所以救火車被迫降低了放水速度以適應居民。

為了避免這種情況,在救火車和居民之間多了一層「蓄水池(也就是Cache)」,它一方面以100%的高效和救火車打交道,另一方面以10%的低效和居民打交道,這就解放了救火車,讓其以最高的效率運行,而不被低速的居民拖後腿,於是救火車只需要在一個居民點停留10分鐘就可以了。

所以說,蓄水池是「活雷鋒」,把高效留給別人,把低效留給自己。把10分鐘留給救火車,把100分鐘留給自己。

從以上例子可以看出,所謂Cache,就是「為了彌補高速設備與低速設備之間交互時的等待延遲」而設立的一個中間層。因為在現實里經常出現高速設備要和低速設備打交道,結果被低速設備拖後腿的情況。

回到PC。CPU速度很快,但CPU執行的指令是從內存取出的,計算的結果也要寫回內存,但內存的響應速度跟不上CPU。

CPU跟內存說:你把某某地址的指令發給我。內存聽到了,但因為速度慢,遲遲不見指令返回,這段時間,CPU只能無所事事的等待了。這樣一來,再快的CPU也發揮不了效率。

怎麼辦呢?在CPU和內存之間加一塊「蓄水池」,也就是Cache(片上緩存),這個Cache速度比內存快,從Cache取指令不需要等待。

當CPU要讀內存的指令的時候先讀Cache再讀內存,但一開始Cache是空著的,只能從內存取,這時候的確是很慢,CPU需要等待。

但從內存取回的不僅僅是CPU所需要的指令,還有其它的、當前不需要的指令,然後把這些指令存在Cache里備用。

CPU再取指令的時候還是先讀Cache,看看裡面有沒有所需指令,如果碰巧有就直接從Cache取,不用等待即可返回(命中),這就解放了CPU,提高了效率。(當然不會是100%命中,因為Cache的容量比內存小)

CPU的Cache,可以有好幾層,而且還分數據Cache和指令Cache。

也許你會問,既然Cache的響應速度快,CPU不需要等待,那為啥還要用「慢速」的內存條呢?直接用Cache不就得了?這是因為在具體製造上有困難,大Cache不但成本無法接受,而且容量大了延遲也會上升。

磁碟緩存也是Cache。剛才說內存是慢速設備,所以需要片上緩存,但這個「慢」是相對於CPU而言的,相對於機械硬碟HDD,內存的速度可快多了。

對於磁碟的讀寫操作,在很久以前,讀寫過程需要CPU參與,後來出現了「DMA/直接內存訪問"就不再需要CPU了,但即使如此,高負荷、長時間的磁碟讀寫也非常的耗時,因為磁碟是機械旋轉部件,其讀寫速度相比CPU和內存條的二進位電壓變化速度,那就是蒸汽機和火箭速度的差別。

為了加快數據的讀寫速度,在磁碟和內存之間也插入一層Cache(Windows在內存里劃分出一塊區域作為Cache,硬碟也有板載Cache。)

寫入數據的時候先寫入到Cache里;因為Cache很快,所以數據很快就寫入。

比方說,1G的數據,如果直接寫入硬碟需要10秒,但寫入Cache(也就是系統內存)只需要1秒。

這樣一來用戶就有了系統速度很快的「幻覺」。但這只是障眼法,數據暫存在Cache里並沒有被真正寫入磁碟,等系統空閑的時候再慢慢寫入。

同理,在讀數據的時候,除了所需的數據,還有一堆目前不需要的數據也都被讀出來放到內存的Cache里。下次再讀的時候,如果恰巧Cache里有所需的數據就可直接讀入(命中),這就避免了從慢速的HDD讀數據的尷尬。用戶的體驗同樣也是速度很快。(同樣不會100%命中,因為RAM的容量遠小於硬碟容量)

PC有16G的內存,磁碟Cahce佔用了3.59G,這是動態的,會自動調整大小

硬碟也內置了Cache。某品牌硬碟的廣告強調了大緩存的優勢

以上舉了3個栗子:蓄水池、CPU的Cache、磁碟的Cache

Cache是為了解決什麼問題?高速與低速設備通信時,因為低速設備響應緩慢的原因,造成高速設備的性能優勢無法發揮,所以需要Cache給高速設備降低延遲,加快速度!

那麼buffer呢? 是從另一個方向降低延遲,與上面的原因不同,該延遲來自於IO過程本身

請允許我再次舉起栗子。

比如說吐魯番的葡萄熟了,要用大卡車裝葡萄運出去賣。

但問題是,卡車距離葡萄園很遠,於是就需要在葡萄園和卡車之間往返多次才能把卡車裝滿。往返所需要的時間就是I/O延遲,比如往返各15分鐘,總共半小時。

果園的姑娘採摘葡萄,難道是摘一串葡萄,就花15分鐘跑到卡車旁邊放進去么?如果是這樣,100串葡萄就需要往返100次,所需要的時間就是100X15X2分鐘,那是何其漫長!

所以聰明的做法就是暫時把100串葡萄放入一個籮筐,再以籮筐為單位倒入卡車,一籮筐(100串)葡萄的往返延遲是半小時。

由此可見,「籮筐」把輸入參數暫時集中放在一起,不是「一條一條」,而是「一股腦」地提供給下家處理。這就大大降低了I/O的次數,也就降低了I/O延遲,提高了速度。

這個籮筐,就是Buffer。

I/O次數過多,除了會造成很大的延遲之外,也會有其它的問題。

以BT為例,BT下載需要長時間的掛機,電腦就有可能24小時連軸轉,但BT下載的數據是碎片化的,體現在硬碟寫入上也是碎片化的,因為硬碟是機械定址器件,定址/寫入的過程會帶來機械運動,長時間的小碎片寫入會造成硬碟長時間高負荷的機械運動,造成硬碟過早老化損壞,當年有大量的硬碟因為BT下載而損壞。

於是新出的BT軟體在內存里開闢了Buffer,數據暫時寫入Buffer,攢到一定的大小(比如512M)再一次性寫入硬碟,這種「化零為整」的寫入方式因為大大減小了定址/寫入次數,所以就降低了硬碟的負荷。

這就是:為了完成最終目標:把數據寫入硬碟空間,需要暫時寫入Buffer的空間

再以編程為例,假設要實現一個功能:接受用戶鍵入的字元串,並賦值給一個字元串變數

其過程如下:

1:在內存中開闢一個」鍵盤緩衝區「接受用戶鍵入的字元串

2:把緩衝區中的字元串copy到程序中定義的字元串變數指向的內存空間(也就是賦值過程)

也就是說,為了完成最終目標:把字元串放入字元串變數指向的空間,需要暫時把字元串放入「鍵盤緩衝區」的空間。


buffer:緩衝

將數據緩衝下來,解決速度慢和快的交接問題;速度快的需要通過緩衝區將數據一點一點傳給速度慢的區域。例如:從內存中將數據往硬碟中寫入,並不是直接寫入,而是緩衝到一定大小之後刷入硬碟中。

A buffer is something that has yet to be "written" to disk.

cache:緩存

實現數據的重複使用,速度慢的設備需要通過緩存將經常要用到的數據緩存起來,緩存下來的數據可以提供高速的傳輸速度給速度快的設備。例如:將硬碟中的數據讀取出來放在內存的緩存區中,這樣以後再次訪問同一個資源,速度會快很多。

A cache is something that has been "read" from the disk and stored for later use.

總結:

buffer是用於存放將要輸出到disk(塊設備)的數據,而cache是存放從disk上讀出的數據。二者都是為提高IO性能而設計的。


首先謝謝你的邀請。

是這樣的,其實Cache和Buffer,物理上講都是RAM。邏輯上講,你把Cache叫成Buffer,或者把Buffer叫成Cache,都沒有錯。

不過Buffer多用於編程方面,Cache多用於非編程方面的叫法。比如為某程序分配一段Buffer,而一般沒有說為某程序分配一段Cache的,但是你可以說這個程序有Cache,或者說Cache是泛指,Buffer是特指。見仁見智。而對於磁碟陣列來講,Buffer=Cache。

另外,從本質上講,Buffer是「緩衝」,而Cache是「緩存」,即Buffer中的數據是一定要在短時間內被處理的,而Cache則可以作為一個數據的長期的容器而其中的數據不一定非要被立刻處理。


cache :表示已讀取的數據(快取)

buffer:表示要寫入的數據 (緩存)


看了前面一整頁感覺只有 @vczh 和 @唐生 回答比較模糊的說到了我認為的關鍵點,大部分回答說的基本上都是一些表面上的區別。

回答舉生活中例子的,基本上都只是舉了個例子並沒有給出一個如何精確區分buffer和cache的標準。高票答案說cache是用來處理速度不匹配而buffer是用來處理速度平衡的,恕我直言完全沒看明白這兩者的區別是什麼。

回答說buffer是寫的,cache是讀的,我感覺從實踐角度上來說已經比較接近事實了,更準確的說法似乎應該是buffer有讀buffer和寫buffer,但是cache基本上只用來讀,不太會有專門的寫cache(經@Sigma網友提醒,這裡有些讓人誤解,數據寫回的時候當然也是經過cache的,我是想說很少回出現一個cache是專門為了寫操作而設計的,一般都是以讀為主)。

出現這種區別的最核心的因素在於:buffer的概念是buffer里存的都是有價值的數據,而cache的邏輯有點類似一人得道雞犬升天

具體解釋一下,無論是讀buffer還是寫buffer,buffer里的所有數據都是你將來確定要用到的,不會有你沒有請求的數據在buffer中。而cache的策略就不一樣了,你讀一次數據,它會把你這次請求的數據身邊的一堆數據一起放在cache中,無論你是否會需要到這些數據。這就是為什麼有些答案中提到buffer一般是用隊列實現,而cache一般要支持隨機訪問,並且有命中率的概念的核心原因。


參考 @cloak shining 的說法:

Buffer是臨時性的,是兩個同時輸出/輸入交換數據的的一個緩存口,首先它是臨時性的,用完可以扔掉,如@cloak shining 所說,是用來抵消掉兩者之間的突然性波動。或者減少過於斷續短小的輸入導致輸出頻繁響應,影響輸出響應。

Cache偏近是永久性的,更像將輸入的數據保存下來,輸出如果需要的數據已經存在,就不需要直接再一次拉輸入,而是直接拉已經保存下來的,尤其完成一次輸入時要耗時極長時。


Buffer:你先等等,搶墳去嗎?

Cache:待會兒還用得著,先別扔。



一個是哈希,一個是隊列

一個是二八法則,一個是速度匹配

一個是冷熱置換,一個隨用隨清


Buffer是緩衝,cache是緩存,這樣就清楚多了。一個是為了防止請求過多超出服務的上限,一個是為了防止重複計算而把計算好的值存起來下次直接用


Cache 是要用的先備著, buffer 是拿不下的先放著……


buffer:排隊等待你翻牌;

cache:上次被臨幸後一直睡你床上,隨時可用,直到你臨幸別人,換別人睡你床上。


1、cache丟失不會影響數據完整性,只會影響性能。buffer丟失會影響輸出數據完整性,源數據不受影響。

2、一般來說cache越大,性能越好,超過一定程度,導致命中率太低之後才會越大性能越低。buffer來說,空間越大性能影響不大,夠用就行。

3、cache過小,或者沒有cache,不影響程序邏輯(高並發cache過小或者丟失導致系統忙死除外)。buffer過小有時候會影響程序邏輯,如導致網路丟包。

4、cache可以做到應用透明,編寫應用的可以不用管是否有cache,可以在應用做好之後再上cache。當然開發者顯式使用cache也行。buffer需要編寫應用的人設計,是程序的一部分。


Cache和Buffer都既可以用硬體實現,也可以用軟體實現。它們都作為數據發送源和接收端的中間數據存儲。它們都是為了提高數據訪問效率(但Buffer除此之外還有其它功能)。故Cache和Buffer的功能是有一定交叉的。

廣義上來講,Cache可以當Buffer用,但Buffer不能當Cache用。但一般還是會明顯區別開2者。

之前有很多答案提到,Cache是為了緩和「高速和低速設備/端的速度差異」。對,確實是這樣的。但其實Buffer也有這樣的功能和作用。還有說Buffer是用作臨時存儲,Cache不是的,但其實Cache也是用於臨時存儲。

不同的是,Cache的唯一作用就是減少訪問低速端數據的次數、降低數據訪問時延。這是Cache的根本作用,也是Cache區別於Buffer的地方所在。Cache里的數據,我們希望能夠多次訪問到,因為多次訪問到Cache里的數據就不用從低速的數據源端訪問從而節省時間。所以Cache會有命中率,越高越好。所以,Cache很多由硬體來實現,CPU、TLB、GPU、DSP、Disk等的Cache都是速度很快存儲器(與數據收、發2端最慢的設備相比),同時也導致Cache比較貴,容易小。所以Cache會有替換策略/演算法

但Buffer則完全不同。Cache很多是硬體實現,軟體實現的也有,比如web伺服器緩存、瀏覽器緩存,而Buffer絕大多數都是由軟體來實現的,較少由硬體來實現,比如我們平常所說的磁碟緩存一般指的是硬體Buffer而非Cache。

所以,即使Cache和Buffer都可以用來緩衝「高低速設備之間速度差異」,如果Cache里的數據第一次讀入後再也用不到了,那毫無疑問Cache做了無用功、是失敗的,僅僅作為了一個臨時存儲器,相當於Buffer;但對於Buffer而言,哪怕Buffer里的數據只需要用一次也是成功的,因為Buffer的本意就不是通過命中率來減少訪問低速端數據的次數從而降低時延,而是通過批量操作來提高數據訪問效率。

當然,除此之外,Buffer還可以作為通信雙方無法或不方便直接通信時的中轉層等。


如果咬文嚼字的話,一般有這麼區分:

1. 讀的叫Cache,寫的叫buffer

2. 不同請求共用的叫cache,作用域主要是本請求的叫buffer

但其實使用起來並沒有那麼嚴格。比如有的操作系統里喜歡各種都叫cache,有的資料庫里喜歡各種都叫buffer。所以也沒必要咬文嚼字了,無所謂了。


都是為了解決處理速度不一致的系統之間的匹配。習慣上根據用途有不同的叫法:Buffer是待處理的數據,Cache是處理結果。

比如OS處理網路數據的速度遠超過網卡接收數據,因此需要一個Buffer,等存滿了一次性交給OS。

又比如從資料庫獲取數據很慢,所以對於不經常修改的數據,就一次性取出,放入Cache,將來就不去資料庫取了


推薦閱讀:

TAG:資料庫 | MySQL | Memcached | InnoDB |