Kafka是2010年12月份開源的項目,採用Scala語言編寫,使用了多種效率優化機制,總體架構比較新穎(push/pull),更適合異構集羣。算法
設計目標:緩存
(1) 數據在磁盤上的存取代價爲O(1)服務器
(2) 高吞吐率,在普通的服務器上每秒也能處理幾十萬條消息網絡
(3) 分佈式架構,可以對消息分區數據結構
(4) 支持將數據並行的加載到Hadoop架構
架構:併發
Kafka其實是一個消息發佈訂閱系統。producer向某個topic發佈消息,而consumer訂閱某個topic的消息,進而一旦有新的關於某個topic的消息,broker會傳遞給訂閱它的全部consumer。 在kafka中,消息是按topic組織的,而每一個topic又會分爲多個partition,這樣便於管理數據和進行負載均衡。同時,它也使用了zookeeper進行負載均衡。負載均衡
Kafka中主要有三種角色,分別爲producer,broker和consumer。異步
(1) Producer分佈式
Producer的任務是向broker發送數據。
Kafka提供了兩種producer接口,一種是low_level接口,使用該接口會向特定的broker的某個topic下的某個partition發送數據;
另外一種那個是high level接口,該接口支持同步/異步發送數據,基於zookeeper的broker自動識別和負載均衡(基於Partitioner)。
其中,基於zookeeper的broker自動識別值得一說。producer能夠經過zookeeper獲取可用的broker列表,也能夠在zookeeper中註冊listener,該listener在如下狀況下會被喚醒:
a.添加一個broker
b.刪除一個broker
c.註冊新的topic
d.broker註冊已存在的topic
當producer得知以上時間時,可根據須要採起必定的行動。
0.8.0版本後,producer再也不經過zookeeper鏈接broker, 而是經過brokerlist(192.168.0.1:9092,192.168.0.2:9092,192.168.0.3:9092配置和zookeeper時很像吶)直接和broker鏈接,只要能和一個broker鏈接上就可以獲取到集羣中其餘broker上的信息
(2) Broker
Broker採起了多種策略提升數據處理效率,包括sendfile和zero copy等技術。
(3) Consumer
consumer的做用是將日誌信息加載到中央存儲系統上。kafka提供了兩種consumer接口,
一種是low level的,它維護到某一個broker的鏈接,而且這個鏈接是無狀態的,即,每次從broker上pull數據時,都要告訴broker數據的偏移量。
另外一種是high-level 接口,它隱藏了broker的細節,容許consumer從broker上pull數據而沒必要關心網絡拓撲結構。
更重要的是,對於大部分日誌系統而言,consumer已經獲取的數據信息都由broker保存,而在kafka中,由consumer本身維護所取數據信息。
Kafka是如何實現其高吞吐率及高可用行的?
kafka的集羣有多個Broker服務器組成,每一個類型的消息被定義爲topic,同一topic內部的消息按照必定的key和算法被分區(partition)存儲在不一樣的Broker上,消息生產者producer和消費者consumer能夠在多個Broker上生產/消費topic
以高吞吐率做爲第一設計原則,kafka的結構設計在不少方面都作了激進的取捨。
① 極簡的數據結構和應用模式
消息隊列是以log文件的形式存儲,消息生產者只能將消息添加到既有的文件尾部,沒有任何ID信息用於消息的定位,徹底依靠文件內的位移,所以消息的使用者只能依靠文件位移順序讀取消息,這樣也就不須要維護複雜的支持隨即讀取的索引結構。
kafka broker徹底不維護和協調多用戶使用消息的行爲模式,consumer本身維護位移用來索引消息,consumer將位移維護在zookeeper中,默認1分鐘自動提交一次,也能夠手動commitoffset
topic最小的併發訪問單位就是partition分區,同一用戶組內(group.id)的全部用戶只能有一個訪問同一分區,從0.8.0版本開始,分區個數是能夠動態增長,能夠經過增長分區數來優化發送性能。
此外分區也帶來一個問題就是消息只是分區內部有序而不是全局有序的。若是須要全局有序,應用須要本身靠別的機制來保證。
使用Pull模式拉取消息,消息的使用狀況,好比是否還有consumer沒有讀取,是否重複讀取(改進中)等,在Broker端也徹底不跟蹤維護,消息的過時處理簡單的由定時器定時刪除(好比保留7天),或者只保留最近100G的數據,由此簡化各類消息跟蹤維護的開銷。
②追求最大化的數據傳輸效率
生產者和消費者能夠批量讀寫消息減小RPC開銷
使用Zero Copy在內核層直接將文件內容傳送給網絡Socket,避免應用層數據拷貝
在傳輸消息前,對數據進行壓縮
③激進的內存管理模式
kafka不在JVM進程內部維護消息Cache,消息直接從文件中讀寫,徹底依賴操做系統在文件系統層面的Cache,避免在JVM中管理Cache帶來的額外數據結構開銷和GC帶來的性能代價。基於批量處理和順序讀寫的應用模式,最大化利用文件系統的Cache機制和規避文件讀寫相對內存讀寫的性能代價。對系統頁面緩存的需求大。
④高可用性
Kafka的0.8.0版本Topic開始支持replicas。
bin/kafka-create-topic.sh --replica 3 --partition 8 --topic test --zookeeper localhost:2181
topic:test的每一個partition會有3個備份,均衡負載在broker集羣,其中一個leader,其餘2個follower作備胎,leader負責message的讀寫。leader和follower的信息會記錄在zookeeper中,若是做爲leader的broker掛了,zookeeper會在2個follower中選舉一個作leader,用來讀寫message。leader收到producer發送的message後,會有獨立的線程把massage同步到follower。
⑤數據一致性
以前提到replica不爲1的狀況下,原leader失去信號, zookeeper會選舉一個follower做爲新的leader代替原leader的讀寫工做。
那麼怎麼保證原來leader和新leader之間的數據一致性呢?
Kafka producer的ack有3中機制,初始化producer時的producerconfig能夠經過配置request.required.acks不一樣的值來實現。
0:這意味着生產者producer不等待來自broker同步完成的確認繼續發送下一條(批)消息。
此選項提供最低的延遲但最弱的耐久性保證(當服務器發生故障時某些數據會丟失,如leader已死,但producer並不知情,發出去的信息broker就收不到)。
1:這意味着producer在leader已成功收到的數據並獲得確認後發送下一條message。
此選項提供了更好的耐久性爲客戶等待服務器確認請求成功(被寫入死亡leader但還沒有複製將失去了惟一的消息)。
-1:這意味着producer在follower副本確認接收到數據後纔算一次發送完成。
此選項提供最好的耐久性,咱們保證沒有信息將丟失,只要至少一個同步副本保持存活。
三種機制,性能依次遞減 (producer吞吐量下降),數據健壯性則依次遞增。