对接kafka_Kafka系列9:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(上)...
?前言
在本文開始之前,作者一直有個疑惑,就是面試題是只寫寫問題和答案就草草了事,還是應該深入分析一下其背后發生的一些原理。和朋友探討以后作者還是決定采用后者的方式,因為我認為不僅要做到知其一,更要知其二,所以我們就用講解原理的方式來看看 Kafka 常見的面試題吧。另外避免文章過長,我打算接下來使用幾篇文章來詳解每道題背后的原理。好了廢話有點多,直接開干。
文章概覽
- kafka 如何保證數據的可靠性和一致性?
- kafka 為什么那么快?
- Kafka 中的消息是否會丟失和重復消費?
- 為什么要使用 kafka,為什么要使用消息隊列?
- 為什么 Kafka 不支持讀寫分離?
kafka 如何保證系統的高可用、數據的可靠性和數據的一致性的?
kafka 的高可用性:
Kafka 的可靠性:
設置為 1 時代表當 Leader 狀態的 Partition 接收到消息并持久化時就認為消息發送成功,如果 ISR 列表的 Replica 還沒來得及同步消息,Leader 狀態的 Partition 對應的 Broker 宕機,則消息有可能丟失。
request.required.acks=0設置為 0 時代表 Producer 發送消息后就認為成功,消息有可能丟失。
request.required.acks=-1設置為-1 時,代表 ISR 列表中的所有 Replica 將消息同步完成后才認為消息發送成功;但是如果只存在主 Partition 的時候,Broker 異常時同樣會導致消息丟失。所以此時就需要min.insync.replicas參數的配合,該參數需要設定值大于等于 2,當 Partition 的個數小于設定的值時,Producer 發送消息會直接報錯。
上面這個過程看似已經很完美了,但是假設如果消息在同步到部分從 Partition 上時,主 Partition 宕機,此時消息會重傳,雖然消息不會丟失,但是會造成同一條消息會存儲多次。在新版本中 Kafka 提出了冪等性的概念,通過給每條消息設置一個唯一 ID,并且該 ID 可以唯一映射到 Partition 的一個固定位置,從而避免消息重復存儲的問題(作者到目前還沒有使用過該特性,感興趣的朋友可以自行在深入研究一下)。
Kafka 的一致性:
從上圖可以看出,假設 Consumer 從主 Partition1 上消費消息,由于 Kafka 規定只允許消費 HW 之前的消息,所以最多消費到 Message2。假設當 Partition1 異常后,Partition2 被選舉為 Leader,此時依舊可以從 Partition2 上讀取到 Message2。其實 HW 的意思利用了木桶效應,始終保持最短板的那個位置。
從上面我們也可以看出,使用 HW 特性后會使得消息只有被所有副本同步后才能被消費,所以在一定程度上降低了消費端的性能,可以通過設置replica.lag.time.max.ms參數來保證消息同步的最大時間。
kafka 為什么那么快?
kafka 使用了順序寫入和“零拷貝”技術,來達到每秒鐘 200w(Apache 官方給出的數據) 的磁盤數據寫入量,另外 Kafka 通過壓縮數據,降低 I/O 的負擔。
大家都知道,對于磁盤而已,如果是隨機寫入數據的話,每次數據在寫入時要先進行尋址操作,該操作是通過移動磁頭完成的,極其耗費時間,而順序讀寫就能夠避免該操作。
普通的數據拷貝流程如上圖所示,數據由磁盤 copy 到內核態,然后在拷貝到用戶態,然后再由用戶態拷貝到 socket,然后由 socket 協議引擎,最后由協議引擎將數據發送到網絡中。
"零拷貝"流程圖采用了“零拷貝”技術后可以看出,數據不在經過用戶態傳輸,而是直接在內核態完成操作,減少了兩次 copy 操作。從而大大提高了數據傳輸速度。
Kafka 官方提供了多種壓縮協議,包括 gzip、snappy、lz4 等等,從而降低了數據傳輸的成本。
Kafka 中的消息是否會丟失和重復消費?
這里給大家一個解決重復消費的思路,作者公司使用了 Redis 記錄了被消費的 key,并設置了過期時間,在 key 還沒有過期內,對于同一個 key 的消息全部當做重復消息直接拋棄掉。 在網上看到過另外一種解決方案,使用 HDFS 存儲被消費過的消息,是否具有可行性存疑(需要讀者朋友自行探索),讀者朋友們可以根據自己的實際情況選擇相應的策略,如果朋友們還有其他比較好的方案,歡迎留言交流。
為什么要使用 kafka,為什么要使用消息隊列?
先來說說為什么要使用消息隊列?
這道題比較主觀一些(自認為沒有網上其他文章寫得話,輕噴),但是都相信大家使用消息隊列無非就是為了 解耦、異步、消峰。
系統調用圖隨著業務的發展,相信有不少朋友公司遇到過如上圖所示的情況,系統 A 處理的結構被 B、C、D 系統所依賴,當新增系統 E 時,也需要系統 A 配合進行聯調和上線等操作;還有當系統 A 發生變更時同樣需要告知 B、C、D、E 系統需要同步升級改造。
引入消息隊列圖引入消息隊列后有兩個好處:
引入消息隊列的壞處:
萬事皆具備兩面性,看似引入消息隊列這件事情很美好,但是同時也增加了系統的復雜度、系統的維護成本提高(如果 MQ 掛了怎么辦)、引入了一致性等等問題需要去解決。
為什么要使用 Kafka?
作者認為采用 Kafka 的原因有如下幾點:
為什么 Kafka 不支持讀寫分離?
這個問題有個先決條件,我們只討論 Kafka0.9 版本的情況。對于高版本,從 Partition 也可以承擔讀請求了,這里不多贅述。
Kafka 如果支持讀寫分離的話,有如下幾個問題。
2. 從上圖可以看出,從從 Partition 上讀取數據會有兩個問題。一、數據從主 Partition 上同步到從 Partition 有數據延遲問題,因為數據從生產到消費會經歷 3 次網絡傳輸才能夠被消費,對于時效性要求比較高的場景本身就不適合了。二、數據一致性問題,假設主 Partition 將數據第一次修改成了 A,然后又將該數據修改成了 B,由于從主 Partition 同步到從 Partition 會有延遲問題,所以也就會產生數據一致性問題。
分析得出,通過解決以上問題來換取從 Partition 承擔讀請求,成本可想而知,而且對于寫入壓力大,讀取壓力小的場景,本身也就沒有什么意義了。
總結
本文介紹了幾個常見的 Kafka 的面試題,下篇文章我們分析一下延遲隊列及其實際落地場景的使用問題,敬請期待
歷史精彩文章推薦:
Kafka系列第7篇:你必須要知道集群內部工作原理的一些事!?mp.weixin.qq.comKafka系列第6篇:消息是如何在服務端存儲與讀取的,你真的知道嗎??mp.weixin.qq.comkafka系列第5篇:一文讀懂消費者背后的那點"貓膩"?mp.weixin.qq.comKafka系列第4篇:消息發送時,網絡“偷偷”幫忙做的那點事兒?mp.weixin.qq.com重要:Kafka第3篇之一條消息如何被存儲到Broker上?mp.weixin.qq.com文章參考:
https://www.cnblogs.com/binyue/p/10308754.html
https://www.cnblogs.com/yoke/p/11477167.html
微信公眾號搜索【z小趙】,更多系列精彩文章等你解
總結
以上是生活随笔為你收集整理的对接kafka_Kafka系列9:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(上)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言的VC开发环境界面介绍,【c语言在
- 下一篇: MFC CListCtrl 取消选中