在設計高并發、高性能的系統架構時,快取是繞不開的一個話題,之所以用快取,是因為不同的存盤介質的訪問速度存在巨大差異,例如SSD(固態硬碟)每秒鐘可以讀寫幾千次,而記憶體的隨機讀寫速度是SSD的10萬倍,使用記憶體作為快取來加速應用程式的訪問速度,是幾乎所有高性能系統都會采用的方法,
快取的思想很簡單:把低速存盤的資料,復制一份放到高速存盤中,用來加速資料訪問,
快取的分類
快取主要分為兩大類:
- 讀寫快取
- 只讀快取
這兩類快取的區別在于更新資料的時候是否經過快取,
讀寫快取
Kafka使用的PageCache就是典型的讀寫快取,作業系統會利用系統空閑的物理記憶體來給檔案讀寫做快取,應用程式在寫檔案的時候,作業系統會先把資料寫入到PageCache中,資料在成功寫到PageCache之后,對于用戶代碼來說,寫入就結束嘞,作業系統再通過異步的方式將資料更新到磁盤的檔案中,應用程式在讀檔案的時候,作業系統也是先嘗試從PageCache中尋找資料,如果找到就直接回傳資料,找不到就會觸發一個缺頁中斷,然后作業系統把資料從檔案讀取到PageCache中,再回傳給應用程式,
我么可以看到寫資料時,并不是同時將資料寫到PageCache和磁盤上,這中間會有一個延遲,作業系統可以保證,即使是應用程式意外退出了,作業系統也會把這部分資料同步到磁盤上,但是如果服務器突然掉電了,這部分資料就會丟失,
讀寫快取這種設計,天然就不是可靠的,這是一種犧牲資料一致性換取性能的設計,
寫快取的實作是非常復雜的,應用恒旭不停地更新PageCache中的資料,作業系統需要記錄哪些資料有變化,同時還要在另外一個執行緒中,把快取中變化的資料更新到磁盤中,在提供并發讀寫的同時來異步更新資料,這個程序中要保證資料的一致性,并且有非常好的性能,很不容易,
Kafka為什么可以使用PageCache提升性能?
Kafka可以使用PageCache并取得性能提升,有三個原因:
- 訊息佇列中資料的讀寫比例基本是1:1,我們用訊息佇列發送的大部分資料都是一收一發的,
- Kafka不是靠磁盤來保證資料的可靠性,它更依賴于不同節點上的多副本來解決資料可靠性問題,
- PageCache的讀寫快取是作業系統實作的,Kafka只需要按照正確的方法來使用就可以了,不會涉及到實作復雜度的問題,
對于不同的使用場景,我們選擇快取的方式也有區別,如果讀次數是寫次數的幾倍到幾十倍,那么可以選擇只讀快取,如果資料的讀寫次數基本一致,那么可以選擇讀寫快取,
只讀快取
對于只讀快取來說,我們需要考慮一個問題:快取的資料來源于磁盤,那么應該怎么更新快取中的資料呢?
我們可以有三種方法來更新只讀快取的資料:
- 資料更新時,同時更新磁盤和快取,這種方法可能會帶來資料不一致的問題,例如我們是選擇同步還是異步來更新快取?如果同步更新,磁盤更新成功了,快取更新失敗嘞,需要反復重試來保證更新成功嗎?如果多次重試都失敗,那么這次更新算成功還是失敗呢?如果是異步更新快取,怎么保證更新的時序?
- 定時將磁盤上的資料同步到快取中,同步時可以采用全量更新,也可以選擇增量更新,這種方法的缺點是快取更新不會很及時,優點是實作起來非常簡單,
- 我們不去更新快取中的資料,而是給快取中的每條資料設定一個比較短的過期時間,資料過期以后即使它還在快取中,我們也會認為它不再有效,需要從磁盤中再次加載,這樣就實作了資料更新,
快取置換策略
當應用程式要訪問某些資料時,如果這些資料在快取中,那么直接訪問快取中的資料就可以了,這種情況我們稱為一次快取命中;如果資料不在快取中,那只能去磁盤訪問資料,我們稱為快取穿透,
一般來說我們都會在資料首次被訪問時,把這條資料放到快取中,隨著訪問的資料越來越多,快取空間會被占完,這時就需要把快取中的一些資料刪掉,以便存放新的資料,這個程序稱為快取置換,
我們有兩種快取置換思路:
- 根據業務邏輯,定制化快取置換策略,例如,當我們知道某些資料已經被刪了,永遠不會再訪問到,那么優先置換這些資料是沒有問題的,
- 使用通用的置換演算法,例如LRU演算法, 也稱為最近最少使用演算法,它的思想是最近剛剛被訪問到的資料,它在將來被訪問的可能性也很大,而很久都沒有被訪問過的資料,未來再被訪問的幾率也不大,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/547160.html
標籤:其他
上一篇:為什么Kafka的性能那么好?
下一篇:怎么正確使用鎖?
