Kafka是一個開源的,分布式的,高吞吐量的消息系統。隨着Kafka的版本迭代,日趨成熟。大家對它的使用也逐步從日志系統衍生到其他關鍵業務領域。特別是其超高吞吐量的特性,在互聯網領域,使用越來越廣泛,生態系統也越來的完善。同時,其設計思路也是其他消息中間件重要的設計參考。
Kafka原先的開發初衷是構建一個處理海量日志的框架,基於高吞吐量為第一原則,所以它對消息的可靠性以及消息的持久化機制考慮的並不是特別的完善。0.8版本后,陸續加入了一些復制、應答和故障轉移等相關機制以后,才可以讓我們在其他關鍵性業務中使用。
Kafka的運行架構如下圖,各組件之間通過TCP協議通信:

Topic:
主題,或者說是一類消息。類似於RabbitMQ中的queue。可以理解為一個隊列。
Broker:
一個Kafka服務稱之為Broker。Kafka可以集群部署,每一個Kafka部署就是一個Broker。
Producer & Consumer:
生產者和消費者。一般消息系統都有生產者和消費者的概念。生產者產生消息,即把消息放入Topic中,而消費者則從Topic中獲取消息處理。一個生產者可以向多個Topic發送消息,一個消費者也可以同時從幾個Topic接收消息。同樣的,一個Topic也可以被多個消費者來接收消息。
Partition:
分區,或者說分組。分組是Kafka提升吞吐量的一個關鍵設計。這樣可以讓消費者多線程並行接收消息。創建Topic時可指定Parition數量。一個Topic可以分為多個Partition,也可以只有一個Partition。每一個Partition是一個有序的,不可變的消息序列。每一個消息在各自的Partition中有唯一的ID。這些ID是有序的。稱之為offset,offset在不同的Partition中是可以重復的,但是在一個Partition中是不可能重復的。越大的offset的消息是最新的。Kafka只保證在每個Partition中的消息是有序的,就會帶來一個問題,即如果一個Consumer在不同的Partition中獲取消息,那么消息的順序也許是和Producer發送到Kafka中的消息的順序是不一致的。這個在后續會討論。

如果是多Partition,生產者在把消息放到Topic中時,可以決定放到哪一個Patition。這個可以使用簡單的輪訓方法,也可以使用一些Hash算法。
一個Topic的多個Partition可以分布式部署在不同的Server上,一個Kafka集群。配置項為:num.partitions,默認是1。每一個Partition也可以在Broker上復制多分,用來做容錯。詳細信息見下面創建Topic一節。
Consumer Group:
顧名思義,定義了一組消費者。一般來說消息中間件都有兩種模式:隊列模式和發布訂閱模式。隊列模式及每一個消息都會給其中一個消費者,而發布訂閱模式則是每個消息都廣播給所有的消費者。Kafka就是使用了Consumer Group來實現了這兩種模式。
如果所有的消費者都是同一個Consumer Group的話,就是隊列模式,每個消息都會負載均衡的分配到所有的消費者。
如果所有的消息者都在不同的Consumer Group的話,就是發布訂閱模式,每個消費者都會得到這個消息。
下圖是一個Topic,配置了4個Patition,分布在2個Broker上。由於有2個Consumer Group,Group A和Group B都可以得到P0-P3的所有消息,是一個訂閱發布模式。兩個Group中的Consumer則負載均衡的接收了這個Topic的消息。如果Group中的Consumer的總線程數量超過了Partition的數量,則會出現空閑狀態。

Zookeeper:
Kafka的運行依賴於Zookeeper。Topic、Consumer、Patition、Broker等注冊信息都存儲在ZooKeeper中。
消息的持久化:
Kafka可以通過配置時間和大小來持久化所有的消息,不管是否被消費(消費者收掉)。舉例來說,如果消息保留被配置為1天,那么,消息就會在磁盤保留一天的時間,也就是說,一天以內,任意消費這個消息。一天以后,這個消息就會被刪除。保留多少時間就取決於業務和磁盤的大小。
Kafka主要有兩種方式:時間和大小。在Broker中的配置參數為:
log.retention.bytes:最多保留的文件字節大小。默認-1。
log.retention.hours:最多保留的時間,小時。優先級最低。默認168。
log.retention.minutes:最多保留的時間,分鍾。如果為空,則看log.retention.hours。默認null。
log.retention.ms:最多保留的時間,毫秒。如果為空,則看log.retention.minutes。默認null。
創建Topic:
通過命令創建topic:
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic haoxy1
partitions:這個topic的partition的數量。
replication-factor:每個partition的副本個數。任意將每一個分區復制到n個broker上。
這個命令就是創建一個topic:haoxy1,只有1個partition,並且這個分區會部署在一個broker,但是具體哪個broker可以通過如下命令查看:
bin/kafka-topics.sh --describ --zookeeper localhost:2181 --topic haoxy1
展示如下:
第一行的摘要信息。
第二行開始是詳細信息,所以是縮進的格式,如果這個topic有10個Partition,那么就有10行。
Leader:每一個分區都有一個broker為Leader,它負責該分區內的所有讀寫操作,其他Leader被動的復制Leader broker。如果Leader broker 掛了,那么其他broker中的一個將自動成為該分區的新Leader。本例子只有1個復制,Leader的Partition在Broker1上面。
Replicas:副本在Broker1上面。
Isr:當前有效的副本在Broker1上面。
再來創建一個多副本的Topic:
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 2 --partitions 5 --topic haoxy2
如圖:
因為我有3個Broker:0,1,2。每一個Partition都有2個Replicas。分別在2個Broker上。


