您好,登錄后才能下訂單哦!
這篇文章主要介紹“Kafka的存儲方法是什么”,在日常操作中,相信很多人在Kafka的存儲方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Kafka的存儲方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Kafka 依賴于文件系統(更底層地來說就是磁盤)來存儲和緩存消息。在我們的印象中,對于各個存儲介質的速度認知大體同下圖所示的相同,層級越高代表速度越快。很顯然,磁盤處于一個比較尷尬的位置,這不禁讓我們懷疑 Kafka 采用這種持久化形式能否提供有競爭力的性能。在傳統的消息中間件 RabbitMQ 中,就使用內存作為默認的存儲介質,而磁盤作為備選介質,以此實現高吞吐和低延遲的特性。然而,事實上磁盤可以比我們預想的要快,也可能比我們預想的要慢,這完全取決于我們如何使用它。
?有關測試結果表明,一個由6塊 7200r/min 的 RAID-5 陣列組成的磁盤簇的線性(順序)寫入速度可以達到 600MB/s,而隨機寫入速度只有 100KB/s,兩者性能相差6000倍。操作系統可以針對線性讀寫做深層次的優化,比如預讀(read-ahead,提前將一個比較大的磁盤塊讀入內存)和后寫(write-behind,將很多小的邏輯寫操作合并起來組成一個大的物理寫操作)技術。順序寫盤的速度不僅比隨機寫盤的速度快,而且也比隨機寫內存的速度快,如下圖所示。
Kafka 在設計時采用了文件追加的方式來寫入消息,即只能在日志文件的尾部追加新的消息,并且也不允許修改已寫入的消息,這種方式屬于典型的順序寫盤的操作,所以就算Kafka使用磁盤作為存儲介質,它所能承載的吞吐量也不容小覷。但這并不是讓 Kafka 在性能上具備足夠競爭力的唯一因素,我們不妨繼續分析。
頁緩存是操作系統實現的一種主要的磁盤緩存,以此用來減少對磁盤 I/O 的操作。具體來說,就是把磁盤中的數據緩存到內存中,把對磁盤的訪問變為對內存的訪問。為了彌補性能上的差異,現代操作系統越來越“激進地”將內存作為磁盤緩存,甚至會非常樂意將所有可用的內存用作磁盤緩存,這樣當內存回收時也幾乎沒有性能損失,所有對于磁盤的讀寫也將經由統一的緩存。?
當一個進程準備讀取磁盤上的文件內容時,操作系統會先查看待讀取的數據所在的頁(page)是否在頁緩存(pagecache)中,如果存在(命中)則直接返回數據,從而避免了對物理磁盤的 I/O 操作;如果沒有命中,則操作系統會向磁盤發起讀取請求并將讀取的數據頁存入頁緩存,之后再將數據返回給進程。
同樣,如果一個進程需要將數據寫入磁盤,那么操作系統也會檢測數據對應的頁是否在頁緩存中,如果不存在,則會先在頁緩存中添加相應的頁,最后將數據寫入對應的頁。被修改過后的頁也就變成了臟頁,操作系統會在合適的時間把臟頁中的數據寫入磁盤,以保持數據的一致性。
Linux 操作系統中的 vm.dirty_background_ratio 參數用來指定當臟頁數量達到系統內存的百分之多少之后就會觸發 pdflush/flush/kdmflush 等后臺回寫進程的運行來處理臟頁,一般設置為小于10的值即可,但不建議設置為0。與這個參數對應的還有一個 vm.dirty_ratio 參數,它用來指定當臟頁數量達到系統內存的百分之多少之后就不得不開始對臟頁進行處理,在此過程中,新的 I/O 請求會被阻擋直至所有臟頁被沖刷到磁盤中。對臟頁有興趣的讀者還可以自行查閱 vm.dirty_expire_centisecs、vm.dirty_writeback.centisecs 等參數的使用說明。?
對一個進程而言,它會在進程內部緩存處理所需的數據,然而這些數據有可能還緩存在操作系統的頁緩存中,因此同一份數據有可能被緩存了兩次。并且,除非使用 Direct I/O 的方式,否則頁緩存很難被禁止。此外,用過 Java 的人一般都知道兩點事實:對象的內存開銷非常大,通常會是真實數據大小的幾倍甚至更多,空間使用率低下;Java 的垃圾回收會隨著堆內數據的增多而變得越來越慢。基于這些因素,使用文件系統并依賴于頁緩存的做法明顯要優于維護一個進程內緩存或其他結構,至少我們可以省去了一份進程內部的緩存消耗,同時還可以通過結構緊湊的字節碼來替代使用對象的方式以節省更多的空間。如此,我們可以在32GB的機器上使用28GB至30GB的內存而不用擔心 GC 所帶來的性能問題。
此外,即使 Kafka 服務重啟,頁緩存還是會保持有效,然而進程內的緩存卻需要重建。這樣也極大地簡化了代碼邏輯,因為維護頁緩存和文件之間的一致性交由操作系統來負責,這樣會比進程內維護更加安全有效。
Kafka 中大量使用了頁緩存,這是 Kafka 實現高吞吐的重要因素之一。雖然消息都是先被寫入頁緩存,然后由操作系統負責具體的刷盤任務的,但在 Kafka 中同樣提供了同步刷盤及間斷性強制刷盤(fsync)的功能,這些功能可以通過 log.flush.interval.messages、log.flush.interval.ms 等參數來控制。
同步刷盤可以提高消息的可靠性,防止由于機器掉電等異常造成處于頁緩存而沒有及時寫入磁盤的消息丟失。不過筆者并不建議這么做,刷盤任務就應交由操作系統去調配,消息的可靠性應該由多副本機制來保障,而不是由同步刷盤這種嚴重影響性能的行為來保障。
Linux 系統會使用磁盤的一部分作為 swap 分區,這樣可以進行進程的調度:把當前非活躍的進程調入 swap 分區,以此把內存空出來讓給活躍的進程。對大量使用系統頁緩存的 Kafka 而言,應當盡量避免這種內存的交換,否則會對它各方面的性能產生很大的負面影響。
我們可以通過修改 vm.swappiness 參數(Linux 系統參數)來進行調節。vm.swappiness 參數的上限為100,它表示積極地使用 swap 分區,并把內存上的數據及時地搬運到 swap 分區中;vm.swappiness 參數的下限為0,表示在任何情況下都不要發生交換(vm.swappiness = 0 的含義在不同版本的 Linux 內核中不太相同,這里采用的是變更后的最新解釋),這樣一來,當內存耗盡時會根據一定的規則突然中止某些進程。筆者建議將這個參數的值設置為1,這樣保留了 swap 的機制而又最大限度地限制了它對 Kafka 性能的影響。
到此,關于“Kafka的存儲方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。