Kafka教程(一)Kafka入門教程數據庫
Message Queue消息傳送系統提供傳送服務。消息傳送依賴於大量支持組件,這些組件負責處理鏈接服務、消息的路由和傳送、持久性、安全性以及日誌記錄。消息服務器可使用一個或多個代理實例。數組
JMS(Java Messaging Service)是Java平臺上有關面向消息中間件(MOM)的技術規範,它便於消息系統中的Java應用程序進行消息交換,而且經過提供標準的產生、發送、接收消息的接口簡化企業應用的開發,翻譯爲Java消息服務。安全
KafkaMQ消息模型圖1-1服務器
消息隊列分類:點對點和發佈/訂閱兩種:網絡
一、點對點:數據結構
消息生產者生產消息發送到queue中,而後消息消費者從queue中取出而且消費消息。架構
消息被消費之後,queue中再也不有存儲,因此消息消費者不可能消費到已經被消費的消息。Queue支持存在多個消費者,可是對一個消息而言,只會有一個消費者能夠消費。併發
二、發佈/訂閱:app
消息生產者(發佈)將消息發佈到topic中,同時有多個消息消費者(訂閱)消費該消息。和點對點方式不一樣,發佈到topic的消息會被全部訂閱者消費。負載均衡
一、RabbitMQ:支持的協議多,很是重量級消息隊列,對路由(Routing),負載均衡(Loadbalance)或者數據持久化都有很好的支持。
二、ZeroMQ:號稱最快的消息隊列系統,尤爲針對大吞吐量的需求場景,擅長的高級/複雜的隊列,可是技術也複雜,而且只提供非持久性的隊列。
三、ActiveMQ:Apache下的一個子項,相似ZeroMQ,可以以代理人和點對點的技術實現隊列。
四、Redis:是一個key-Value的NOSql數據庫,但也支持MQ功能,數據量較小,性能優於RabbitMQ,數據超過10K就慢的沒法忍受。
Kafka是分佈式發佈-訂閱消息系統,它最初由 LinkedIn 公司開發,使用 Scala語言編寫,以後成爲 Apache 項目的一部分。在Kafka集羣中,沒有「中心主節點」的概念,集羣中全部的服務器都是對等的,所以,能夠在不作任何配置的更改的狀況下實現服務器的的添加與刪除,一樣的消息的生產者和消費者也可以作到隨意重啓和機器的上下線。
Kafka消息系統生產者和消費者部署關係圖1-2
Kafka消息系統架構圖1-3
一、消息生產者:即:Producer,是消息的產生的源頭,負責生成消息併發送到Kafka
服務器上。
二、消息消費者:即:Consumer,是消息的使用方,負責消費Kafka服務器上的消息。
三、主題:即:Topic,由用戶定義並配置在Kafka服務器,用於創建生產者和消息者之間的訂閱關係:生產者發送消息到指定的Topic下,消息者從這個Topic下消費消息。
四、消息分區:即:Partition,一個Topic下面會分爲不少分區,例如:「kafka-test」這個Topic下能夠分爲6個分區,分別由兩臺服務器提供,那麼一般能夠配置爲讓每臺服務器提供3個分區,假如服務器ID分別爲0、1,則全部的分區爲0-0、0-1、0-2和1-0、1-1、1-2。Topic物理上的分組,一個 topic能夠分爲多個 partition,每一個 partition 是一個有序的隊列。partition中的每條消息都會被分配一個有序的 id(offset)。
五、Broker:即Kafka的服務器,用戶存儲消息,Kafa集羣中的一臺或多臺服務器統稱爲 broker。
六、消費者分組:Group,用於歸組同類消費者,在Kafka中,多個消費者能夠共同消息一個Topic下的消息,每一個消費者消費其中的部分消息,這些消費者就組成了一個分組,擁有同一個分組名稱,一般也被稱爲消費者集羣。
七、Offset:消息存儲在Kafka的Broker上,消費者拉取消息數據的過程當中須要知道消息在文件中的偏移量,這個偏移量就是所謂的Offset。
一、Broker:即Kafka的服務器,用戶存儲消息,Kafa集羣中的一臺或多臺服務器統稱爲 broker。
二、Message在Broker中通Log追加的方式進行持久化存儲。並進行分區(patitions)。
三、爲了減小磁盤寫入的次數,broker會將消息暫時buffer起來,當消息的個數(或尺寸)達到必定閥值時,再flush到磁盤,這樣減小了磁盤IO調用的次數。
四、Broker沒有副本機制,一旦broker宕機,該broker的消息將都不可用。Message消息是有多份的。
五、Broker不保存訂閱者的狀態,由訂閱者本身保存。
六、無狀態致使消息的刪除成爲難題(可能刪除的消息正在被訂閱),kafka採用基於時間的SLA(服務水平保證),消息保存必定時間(一般爲7天)後會被刪除。
七、消息訂閱者能夠rewind back到任意位置從新進行消費,當訂閱者故障時,能夠選擇最小的offset(id)進行從新讀取消費消息。
一、Message消息:是通訊的基本單位,每一個 producer 能夠向一個 topic(主題)發佈一些消息。
二、Kafka中的Message是以topic爲基本單位組織的,不一樣的topic之間是相互獨立的。每一個topic又能夠分紅幾個不一樣的partition(每一個topic有幾個partition是在建立topic時指定的),每一個partition存儲一部分Message。
三、partition中的每條Message包含了如下三個屬性:
offset 即:消息惟一標識:對應類型:long
MessageSize 對應類型:int32
data 是message的具體內容。
一、Kafka基於文件存儲.經過分區,能夠將日誌內容分散到多個server上,來避免文件尺寸達到單機磁盤的上限,每一個partiton都會被當前server(kafka實例)保存。
二、能夠將一個topic切分多任意多個partitions,來消息保存/消費的效率。
三、越多的partitions意味着能夠容納更多的consumer,有效提高併發消費的能力。
一、消息和數據消費者,訂閱 topics並處理其發佈的消息的過程叫作 consumers。
二、在 kafka中,咱們能夠認爲一個group是一個「訂閱者」,一個Topic中的每一個partions,只會被一個「訂閱者」中的一個consumer消費,不過一個 consumer能夠消費多個partitions中的消息(消費者數據小於Partions的數量時)。注意:kafka的設計原理決定,對於一個topic,同一個group中不能有多於partitions個數的consumer同時消費,不然將意味着某些consumer將沒法獲得消息。
三、一個partition中的消息只會被group中的一個consumer消息。每一個group中consumer消息消費互相獨立。
一、一個Topic能夠認爲是一類消息,每一個topic將被分紅多partition(區),每一個partition在存儲層面是append log文件。任何發佈到此partition的消息都會被直接追加到log文件的尾部,每條消息在文件中的位置稱爲offset(偏移量),partition是以文件的形式存儲在文件系統中。
二、Logs文件根據broker中的配置要求,保留必定時間後刪除來釋放磁盤空間。
Kafka消息分區Partition圖1-4
Partition:
Topic物理上的分組,一個 topic能夠分爲多個 partition,每一個 partition 是一個有序的隊列。partition中的每條消息都會被分配一個有序的 id(offset)。
三、爲數據文件建索引:稀疏存儲,每隔必定字節的數據創建一條索引。下圖爲一個partition的索引示意圖:
Kafka消息分區Partition索引圖1-5
Kafka分佈式關係圖1-6
Kafka生產環境關係圖1-7
一、Kafka的Producer、Broker和Consumer之間採用的是一套自行設計基於TCP層的協議,根據業務需求定製,而非實現一套相似ProtocolBuffer的通用協議。
二、基本數據類型:(Kafka是基於Scala語言實現的,類型也是Scala中的數據類型)
定長數據類型:int8,int16,int32和int64,對應到Java中就是byte, short, int和long。
變長數據類型:bytes和string。變長的數據類型由兩部分組成,分別是一個有符號整數N(表示內容的長度)和N個字節的內容。其中,N爲-1表示內容爲null。bytes的長度由int32表示,string的長度由int16表示。
數組:數組由兩部分組成,分別是一個由int32類型的數字表示的數組長度N和N個元素。
三、Kafka通信的基本單位是Request/Response。
四、基本結構:
RequestOrResponse => MessageSize(RequestMessage | ResponseMessage)
名稱 |
類型 |
描術 |
MessageSize |
int32 |
表示RequestMessage或者ResponseMessage的長度
|
RequestMessage ResponseMessage |
— |
|
五、通信過程:
客戶端打開與服務器端的Socket
往Socket寫入一個int32的數字(數字表示此次發送的Request有多少字節)
服務器端先讀出一個int32的整數從而獲取此次Request的大小
而後讀取對應字節數的數據從而獲得Request的具體內容
服務器端處理了請求後,也用一樣的方式來發送響應。
六、RequestMessage結構:
RequestMessage => ApiKey ApiVersionCorrelationId ClientId Request
名稱 |
類型 |
描術 |
ApiKey |
int16 |
表示此次請求的API編號 |
ApiVersion |
int16 |
表示請求的API的版本,有了版本後就能夠作到後向兼容 |
CorrelationId |
int32 |
由客戶端指定的一個數字惟一標示此次請求的id,服務器端在處理完請求後也會把一樣的CorrelationId寫到Response中,這樣客戶端就能把某個請求和響應對應起來了。 |
ClientId |
string |
客戶端指定的用來描述客戶端的字符串,會被用來記錄日誌和監控,它惟一標示一個客戶端。 |
Request |
— |
Request的具體內容。 |
七、ResponseMessage結構:
ResponseMessage => CorrelationId Response
名稱 |
類型 |
描術 |
CorrelationId |
int32 |
對應Request的CorrelationId。 |
Response |
— |
對應Request的Response,不一樣的Request的Response的字段是不同的。 |
Kafka採用是經典的Reactor(同步IO)模式,也就是1個Acceptor響應客戶端的鏈接請求,N個Processor來讀取數據,這種模式能夠構建出高性能的服務器。
八、Message結構:
Message:Producer生產的消息,鍵-值對
Message => Crc MagicByte Attributes KeyValue
名稱 |
類型 |
描術 |
CRC |
int32 |
表示這條消息(不包括CRC字段自己)的校驗碼。 |
MagicByte |
int8 |
表示消息格式的版本,用來作後向兼容,目前值爲0。 |
Attributes |
int8 |
表示這條消息的元數據,目前最低兩位用來表示壓縮格式。 |
Key |
bytes |
表示這條消息的Key,能夠爲null。 |
Value |
bytes |
表示這條消息的Value。Kafka支持消息嵌套,也就是把一條消息做爲Value放到另一條消息裏面。 |
九、MessageSet結構:
MessageSet:用來組合多條Message,它在每條Message的基礎上加上了Offset和MessageSize
MessageSet => [Offset MessageSize Message]
名稱 |
類型 |
描術 |
Offset |
int64 |
它用來做爲log中的序列號,Producer在生產消息的時候還不知道具體的值是什麼,能夠隨便填個數字進去。 |
MessageSize |
int32 |
表示這條Message的大小。 |
Message |
- |
表示這條Message的具體內容,其格式見上一小節。 |
十、 Request/Respone和Message/MessageSet的關係:
Request/Response是通信層的結構,和網絡的7層模型對比的話,它相似於TCP層。
Message/MessageSet定義的是業務層的結構,相似於網絡7層模型中的HTTP層。Message/MessageSet只是Request/Response的payload中的一種數據結構。
備註:Kafka的通信協議中不含Schema,格式也比較簡單,這樣設計的好處是協議自身的Overhead小,再加上把多條Message放在一塊兒作壓縮,提升壓縮比率,從而在網絡上傳輸的數據量會少一些。
一、at most once:最多一次,這個和JMS中"非持久化"消息相似.發送一次,不管成敗,將不會重發。
at most once:消費者fetch消息,而後保存offset,而後處理消息;當client保存offset以後,可是在消息處理過程當中出現了異常,致使部分消息未能繼續處理.那麼此後"未處理"的消息將不能被fetch到,這就是"atmost once"。
二、at least once:消息至少發送一次,若是消息未能接受成功,可能會重發,直到接收成功。
at least once:消費者fetch消息,而後處理消息,而後保存offset.若是消息處理成功以後,可是在保存offset階段zookeeper異常致使保存操做未能執行成功,這就致使接下來再次fetch時可能得到上次已經處理過的消息,這就是"atleast once",緣由offset沒有及時的提交給zookeeper,zookeeper恢復正常仍是以前offset狀態。
三、exactly once:消息只會發送一次。
exactly once: kafka中並無嚴格的去實現(基於2階段提交,事務),咱們認爲這種策略在kafka中是沒有必要的。
注:一般狀況下"at-least-once"是咱們首選。(相比at most once而言,重複接收數據總比丟失數據要好)。
1. 《Apache Kafka》
2. 《從Paxos到Zookeeper分佈式一致性原理與實踐》
——厚積薄發(yuanxw)