2.Kafka中topic的Partition,Kafka爲什麼這麼快,Consumer的負載均衡及consumerGroup的概念(來自學習筆記)

1.1. Kafka中topic的Partition

 在Kafka文件存儲中,同一個topic下有多個不同partition,每個partition爲一個目錄,partiton命名規則爲topic名稱+有序序號,第一個partiton序號從0開始,序號最大值爲partitions數量減1。
 每個partion(目錄)相當於一個巨型文件被平均分配到多個大小相等segment(段)數據文件中。但每個段segment file消息數量不一定相等,這種特性方便old segment file快速被刪除。默認保留7天的數據。
這裏寫圖片描述
 每個partiton只需要支持順序讀寫就行了,segment文件生命週期由服務端配置參數決定。(什麼時候創建,什麼時候刪除)
這裏寫圖片描述
數據有序的討論?
一個partition的數據是否是有序的? 間隔性有序,不連續
針對一個topic裏面的數據,只能做到partition內部有序,不能做到全局有序。
特別加入消費者的場景後,如何保證消費者消費的數據全局有序的?僞命題。

只有一種情況下才能保證全局有序?就是隻有一個partition。

其它:
這裏寫圖片描述

2.Kafka爲什麼這麼快

2.1. 首先簡單介紹一下Kafka的架構和涉及到的名詞:

  1. Topic:用於劃分Message的邏輯概念,一個Topic可以分佈在多個Broker上。
  2. Partition:是Kafka中橫向擴展和一切並行化的基礎,每個Topic都至少被切分爲1個Partition。
  3. Offset:消息在Partition中的編號,編號順序不跨Partition。
  4. Consumer:用於從Broker中取出/消費Message。
  5. Producer:用於往Broker中發送/生產Message。
  6. Replication:Kafka支持以Partition爲單位對Message進行冗餘備份,每個Partition都可以配置至少1個Replication(當僅1個Replication時即僅該Partition本身)。
  7. Leader:每個Replication集合中的Partition都會選出一個唯一的Leader,所有的讀寫請求都由Leader處理。其他Replicas從Leader處把數據更新同步到本地,過程類似大家熟悉的MySQL中的Binlog同步。
  8. Broker:Kafka中使用Broker來接受Producer和Consumer的請求,並把Message持久化到本地磁盤。每個Cluster當中會選舉出一個Broker來擔任Controller,負責處理Partition的Leader選舉,協調Partition遷移等工作。
  9. ISR(In-Sync Replica):是Replicas的一個子集,表示目前Alive且與Leader能夠“Catch-up”的Replicas集合。由於讀寫都是首先落到Leader上,所以一般來說通過同步機制從Leader上拉取數據的Replica都會和Leader有一些延遲(包括了延遲時間和延遲條數兩個維度),任意一個超過閾值都會把該Replica踢出ISR。每個Partition都有它自己獨立的ISR。
    以上幾乎是我們在使用Kafka的過程中可能遇到的所有名詞,同時也無一不是最核心的概念或組件,感覺到從設計本身來說,Kafka還是足夠簡潔的。這次本文圍繞Kafka優異的吞吐性能,逐個介紹一下其設計與實現當中所使用的各項“黑科技”。
    Broker
    不同於Redis和MemcacheQ等內存消息隊列,Kafka的設計是把所有的Message都要寫入速度低容量大的硬盤,以此來換取更強的存儲能力。實際上,Kafka使用硬盤並沒有帶來過多的性能損失,“規規矩矩”的抄了一條“近道”。
    首先,說“規規矩矩”是因爲Kafka在磁盤上只做Sequence I/O,由於消息系統讀寫的特殊性,這並不存在什麼問題。關於磁盤I/O的性能,引用一組Kafka官方給出的測試數據(Raid-5,7200rpm):
    Sequence I/O: 600MB/s
    Random I/O: 100KB/s
    所以通過只做Sequence I/O的限制,規避了磁盤訪問速度低下對性能可能造成的影響。
    接下來我們再聊一聊Kafka是如何“抄近道的”。
    首先,Kafka重度依賴底層操作系統提供的PageCache功能。當上層有寫操作時,操作系統只是將數據寫入PageCache,同時標記Page屬性爲Dirty。當讀操作發生時,先從PageCache中查找,如果發生缺頁才進行磁盤調度,最終返回需要的數據。實際上PageCache是把儘可能多的空閒內存都當做了磁盤緩存來使用。同時如果有其他進程申請內存,回收PageCache的代價又很小,所以現代的OS都支持PageCache。
    使用PageCache功能同時可以避免在JVM內部緩存數據,JVM爲我們提供了強大的GC能力,同時也引入了一些問題不適用與Kafka的設計。
    · 如果在Heap內管理緩存,JVM的GC線程會頻繁掃描Heap空間,帶來不必要的開銷。如果Heap過大,執行一次Full GC對系統的可用性來說將是極大的挑戰。
    · 所有在在JVM內的對象都不免帶有一個Object Overhead(千萬不可小視),內存的有效空間利用率會因此降低。
    · 所有的In-Process Cache在OS中都有一份同樣的PageCache。所以通過將緩存只放在PageCache,可以至少讓可用緩存空間翻倍。
    · 如果Kafka重啓,所有的In-Process Cache都會失效,而OS管理的PageCache依然可以繼續使用。
    PageCache還只是第一步,Kafka爲了進一步的優化性能還採用了Sendfile技術。在解釋Sendfile之前,首先介紹一下傳統的網絡I/O操作流程,大體上分爲以下4步。
  10. OS 從硬盤把數據讀到內核區的PageCache。
  11. 用戶進程把數據從內核區Copy到用戶區。
  12. 然後用戶進程再把數據寫入到Socket,數據流入內核區的Socket Buffer上。
  13. OS 再把數據從Buffer中Copy到網卡的Buffer上,這樣完成一次發送。
    這裏寫圖片描述
    整個過程共經歷兩次Context Switch,四次System Call。同一份數據在內核Buffer與用戶Buffer之間重複拷貝,效率低下。其中2、3兩步沒有必要,完全可以直接在內核區完成數據拷貝。這也正是Sendfile所解決的問題,經過Sendfile優化後,整個I/O過程就變成了下面這個樣子。
    這裏寫圖片描述
    通過以上的介紹不難看出,Kafka的設計初衷是盡一切努力在內存中完成數據交換,無論是對外作爲一整個消息系統,或是內部同底層操作系統的交互。如果Producer和Consumer之間生產和
    費進度上配合得當,完全可以實現數據交換零I/O。

3.Consumer的負載均衡

當一個group中,有consumer加入或者離開時,會觸發partitions均衡.均衡的最終目的,是提升topic的併發消費能力,步驟如下:
1、 假如topic1,具有如下partitions: P0,P1,P2,P3
2、 加入group中,有如下consumer: C1,C2
3、 首先根據partition索引號對partitions排序: P0,P1,P2,P3
4、 根據consumer.id排序: C0,C1
5、 計算倍數: M = [P0,P1,P2,P3].size / [C0,C1].size,本例值M=2(向上取整)
6、 然後依次分配partitions: C0 = [P0,P1],C1=[P2,P3],即Ci = [P(i * M),P((i + 1) * M -1)]
這裏寫圖片描述

發佈了13 篇原創文章 · 獲贊 25 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章