Kafka系統的角色php
Broker :一臺kafka服務器就是一個broker。一個集羣由多個broker組成。一個broker能夠容納多個topichtml
topic: 能夠理解爲一個MQ消息隊列的名字java
Partition:爲了實現擴展性,一個很是大的topic能夠分佈到多個 broker(即服務器)上,一個topic能夠分爲多個partition,每一個partition是一個有序的隊列。partition中的每條消息 都會被分配一個有序的id(offset)。kafka只保證按一個partition中的順序將消息發給consumer,不保證一個topic的總體 (多個partition間)的順序。也就是說,一個topic在集羣中能夠有多個partition,那麼分區的策略是什麼?(消息發送到哪一個分區上,有兩種基本的策略,一是採用Key Hash算法,一是採用Round Robin算法)
算法
ookeeper在Kakfa中扮演的角色Kafka將元數據信息保存在Zookeeper中,可是發送給Topic自己的數據是不會發到Zk上的,不然Zk就瘋了。
apache
kafka使用zookeeper來實現動態的集羣擴展,不須要更改客戶端(producer和consumer)的配置。broker會在zookeeper註冊並保持相關的元數據(topic,partition信息等)更新。服務器
而客戶端會在zookeeper上註冊相關的watcher。一旦zookeeper發生變化,客戶端能及時感知並做出相應調整。這樣就保證了添加或去除broker時,各broker間仍能自動實現負載均衡。這裏的客戶端指的是Kafka的消息生產端(Producer)和消息消費端(Consumer)
架構
Broker端使用zookeeper來註冊broker信息,以及監測partition leader存活性.併發
Consumer端使用zookeeper用來註冊consumer信息,其中包括consumer消費的partition列表等,同時也用來發現broker列表,並和partition leader創建socket鏈接,並獲取消息.app
Zookeer和Producer沒有創建關係,只和Brokers、Consumers創建關係以實現負載均衡,即同一個Consumer Group中的Consumers能夠實現負載均衡負載均衡
入門
一、簡介
Kafka is a distributed,partitioned,replicated commit logservice。它提供了相似於JMS的特性,可是在設計實現上徹底不一樣,此外它並非JMS規範的實現。kafka對消息保存時根據Topic進行歸類,發送消息者成爲Producer,消息接受者成爲Consumer,此外kafka集羣有多個kafka實例組成,每一個實例(server)成爲broker。不管是kafka集羣,仍是producer和consumer都依賴於zookeeper來保證系統可用性集羣保存一些meta信息。
<ignore_js_op>
二、Topics/logs
一個Topic能夠認爲是一類消息,每一個topic將被分紅多個partition(區),每一個partition在存儲層面是append log文件。任何發佈到此partition的消息都會被直接追加到log文件的尾部,每條消息在文件中的位置稱爲offset(偏移量),offset爲一個long型數字,它是惟一標記一條消息。它惟一的標記一條消息。kafka並無提供其餘額外的索引機制來存儲offset,由於在kafka中幾乎不容許對消息進行「隨機讀寫」。
<ignore_js_op>
kafka和JMS(Java Message Service)實現(activeMQ)不一樣的是:即便消息被消費,消息仍然不會被當即刪除.日誌文件將會根據broker中的配置要求,保留必定的時間以後刪除;好比log文件保留2天,那麼兩天後,文件會被清除,不管其中的消息是否被消費.kafka經過這種簡單的手段,來釋放磁盤空間,以及減小消息消費以後對文件內容改動的磁盤IO開支.
對於consumer而言,它須要保存消費消息的offset,對於offset的保存和使用,有consumer來控制;當consumer正常消費消息時,offset將會"線性"的向前驅動,即消息將依次順序被消費.事實上consumer可使用任意順序消費消息,它只須要將offset重置爲任意值..(offset將會保存在zookeeper中,參見下文)
kafka集羣幾乎不須要維護任何consumer和producer狀態信息,這些信息有zookeeper保存;所以producer和consumer的客戶端實現很是輕量級,它們能夠隨意離開,而不會對集羣形成額外的影響.
partitions的設計目的有多個.最根本緣由是kafka基於文件存儲.經過分區,能夠將日誌內容分散到多個server上,來避免文件尺寸達到單機磁盤的上限,每一個partiton都會被當前server(kafka實例)保存;能夠將一個topic切分多任意多個partitions,來消息保存/消費的效率.此外越多的partitions意味着能夠容納更多的consumer,有效提高併發消費的能力.(具體原理參見下文).
三、Distribution
一個Topic的多個partitions,被分佈在kafka集羣中的多個server上;每一個server(kafka實例)負責partitions中消息的讀寫操做;此外kafka還能夠配置partitions須要備份的個數(replicas),每一個partition將會被備份到多臺機器上,以提升可用性.
基於replicated方案,那麼就意味着須要對多個備份進行調度;每一個partition都有一個server爲"leader";leader負責全部的讀寫操做,若是leader失效,那麼將會有其餘follower來接管(成爲新的leader);follower只是單調的和leader跟進,同步消息便可..因而可知做爲leader的server承載了所有的請求壓力,所以從集羣的總體考慮,有多少個partitions就意味着有多少個"leader",kafka會將"leader"均衡的分散在每一個實例上,來確保總體的性能穩定.
Producers
Producer將消息發佈到指定的Topic中,同時Producer也能決定將此消息歸屬於哪一個partition;好比基於"round-robin"方式或者經過其餘的一些算法等.
Consumers
本質上kafka只支持Topic.每一個consumer屬於一個consumer group;反過來講,每一個group中能夠有多個consumer.發送到Topic的消息,只會被訂閱此Topic的每一個group中的一個consumer消費.
若是全部的consumer都具備相同的group,這種狀況和queue模式很像;消息將會在consumers之間負載均衡.
若是全部的consumer都具備不一樣的group,那這就是"發佈-訂閱";消息將會廣播給全部的消費者.
在kafka中,一個partition中的消息只會被group中的一個consumer消費;每一個group中consumer消息消費互相獨立;咱們能夠認爲一個group是一個"訂閱"者,一個Topic中的每一個partions,只會被一個"訂閱者"中的一個consumer消費,不過一個consumer能夠消費多個partitions中的消息.kafka只能保證一個partition中的消息被某個consumer消費時,消息是順序的.事實上,從Topic角度來講,消息仍不是有序的.
kafka的設計原理決定,對於一個topic,同一個group中不能有多於partitions個數的consumer同時消費,不然將意味着某些consumer將沒法獲得消息.
Guarantees
1) 發送到partitions中的消息將會按照它接收的順序追加到日誌中
2) 對於消費者而言,它們消費消息的順序和日誌中消息順序一致.
3) 若是Topic的"replicationfactor"爲N,那麼容許N-1個kafka實例失效.
2、使用場景
一、Messaging
對於一些常規的消息系統,kafka是個不錯的選擇;partitons/replication和容錯,可使kafka具備良好的擴展性和性能優點.不過到目前爲止,咱們應該很清楚認識到,kafka並無提供JMS中的"事務性""消息傳輸擔保(消息確認機制)""消息分組"等企業級特性;kafka只能使用做爲"常規"的消息系統,在必定程度上,還沒有確保消息的發送與接收絕對可靠(好比,消息重發,消息發送丟失等)
二、Websit activity tracking
kafka能夠做爲"網站活性跟蹤"的最佳工具;能夠將網頁/用戶操做等信息發送到kafka中.並實時監控,或者離線統計分析等
三、Log Aggregation
kafka的特性決定它很是適合做爲"日誌收集中心";application能夠將操做日誌"批量""異步"的發送到kafka集羣中,而不是保存在本地或者DB中;kafka能夠批量提交消息/壓縮消息等,這對producer端而言,幾乎感受不到性能的開支.此時consumer端可使hadoop等其餘系統化的存儲和分析系統.
它的架構包括如下組件:
話題(Topic):是特定類型的消息流。消息是字節的有效負載(Payload),話題是消息的分類名或種子(Feed)名。
生產者(Producer):是可以發佈消息到話題的任何對象。
服務代理(Broker):已發佈的消息保存在一組服務器中,它們被稱爲代理(Broker)或Kafka集羣。
消費者(Consumer):能夠訂閱一個或多個話題,並從Broker拉數據,從而消費這些已發佈的消息。
Kafka存儲策略
1)kafka以topic來進行消息管理,每一個topic包含多個partition,每一個partition對應一個邏輯log,有多個segment組成。
2)每一個segment中存儲多條消息(見下圖),消息id由其邏輯位置決定,即從消息id可直接定位到消息的存儲位置,避免id到位置的額外映射。
3)每一個part在內存中對應一個index,記錄每一個segment中的第一條消息偏移。
4)發佈者發到某個topic的消息會被均勻的分佈到多個partition上(或根據用戶指定的路由規則進行分佈),broker收到發佈消息往對應partition的最後一個segment上添加該消息,當某個segment上的消息條數達到配置值或消息發佈時間超過閾值時,segment上的消息會被flush到磁盤,只有flush到磁盤上的消息訂閱者才能訂閱到,segment達到必定的大小後將不會再往該segment寫數據,broker會建立新的segment。
Kafka刪除策略
1)N天前的刪除。
2)保留最近的MGB數據。
Kafka broker
與其它消息系統不一樣,Kafka broker是無狀態的。這意味着消費者必須維護已消費的狀態信息。這些信息由消費者本身維護,broker徹底無論(有offset managerbroker管理)。
從代理刪除消息變得很棘手,由於代理並不知道消費者是否已經使用了該消息。Kafka創新性地解決了這個問題,它將一個簡單的基於時間的SLA應用於保留策略。當消息在代理中超過必定時間後,將會被自動刪除。
這種創新設計有很大的好處,消費者能夠故意倒回到老的偏移量再次消費數據。這違反了隊列的常見約定,但被證實是許多消費者的基本特徵。
如下摘抄自kafka官方文檔:
Kafka Design
目標
1) 高吞吐量來支持高容量的事件流處理
2) 支持從離線系統加載數據
3) 低延遲的消息系統
持久化
1) 依賴文件系統,持久化到本地
2) 數據持久化到log
效率
1) 解決」small IO problem「:
使用」message set「組合消息。
server使用」chunks of messages「寫到log。
consumer一次獲取大的消息塊。
2)解決」byte copying「:
在producer、broker和consumer之間使用統一的binary message format。
使用系統的pagecache。
使用sendfile傳輸log,避免拷貝。
端到端的批量壓縮(End-to-end Batch Compression)
Kafka支持GZIP和Snappy壓縮協議。
The Producer
負載均衡
1)producer能夠自定義發送到哪一個partition的路由規則。默認路由規則:hash(key)%numPartitions,若是key爲null則隨機選擇一個partition。
2)自定義路由:若是key是一個user id,能夠把同一個user的消息發送到同一個partition,這時consumer就能夠從同一個partition讀取同一個user的消息。
異步批量發送
批量發送:配置很少於固定消息數目一塊兒發送而且等待時間小於一個固定延遲的數據。
The Consumer
consumer控制消息的讀取。
Push vs Pull
1)producer push data to broker,consumer pull data from broker
2)consumer pull的優勢:consumer本身控制消息的讀取速度和數量。
3)consumer pull的缺點:若是broker沒有數據,則可能要pull屢次忙等待,Kafka能夠配置consumer long pull一直等到有數據。
Consumer Position
1)大部分消息系統由broker記錄哪些消息被消費了,但Kafka不是。
2)Kafka由consumer控制消息的消費,consumer甚至能夠回到一個old offset的位置再次消費消息。
Message Delivery Semantics
三種:
At most once—Messages may be lost but are never redelivered.
At least once—Messages are never lost but may be redelivered.
Exactly once—this is what people actually want, each message is delivered once and only once.
Producer:有個」acks「配置能夠控制接收的leader的在什麼狀況下就回應producer消息寫入成功。
Consumer:
* 讀取消息,寫log,處理消息。若是處理消息失敗,log已經寫入,則沒法再次處理失敗的消息,對應」At most once「。
* 讀取消息,處理消息,寫log。若是消息處理成功,寫log失敗,則消息會被處理兩次,對應」At least once「。
* 讀取消息,同時處理消息並把result和log同時寫入。這樣保證result和log同時更新或同時失敗,對應」Exactly once「。
Kafka默認保證at-least-once delivery,允許用戶實現at-most-once語義,exactly-once的實現取決於目的存儲系統,kafka提供了讀取offset,實現也沒有問題。
複製(Replication)
1)一個partition的複製個數(replication factor)包括這個partition的leader自己。
2)全部對partition的讀和寫都經過leader。
3)Followers經過pull獲取leader上log(message和offset)
4)若是一個follower掛掉、卡住或者同步太慢,leader會把這個follower從」in sync replicas「(ISR)列表中刪除。
5)當全部的」in sync replicas「的follower把一個消息寫入到本身的log中時,這個消息才被認爲是」committed「的。
6)若是針對某個partition的全部複製節點都掛了,Kafka選擇最早復活的那個節點做爲leader(這個節點不必定在ISR裏)。
日誌壓縮(Log Compaction)
1)針對一個topic的partition,壓縮使得Kafka至少知道每一個key對應的最後一個值。
2)壓縮不會重排序消息。
3)消息的offset是不會變的。
4)消息的offset是順序的。
Distribution
Consumer Offset Tracking
1)High-level consumer記錄每一個partition所消費的maximum offset,並按期commit到offset manager(broker)。
2)Simple consumer須要手動管理offset。如今的Simple consumer Java API只支持commit offset到zookeeper。
Consumers and Consumer Groups
1)consumer註冊到zookeeper
2)屬於同一個group的consumer(group id同樣)平均分配partition,每一個partition只會被一個consumer消費。
3)當broker或同一個group的其餘consumer的狀態發生變化的時候,consumer rebalance就會發生。
Zookeeper協調控制
1)管理broker與consumer的動態加入與離開。
2)觸發負載均衡,當broker或consumer加入或離開時會觸發負載均衡算法,使得一個consumer group內的多個consumer的訂閱負載平衡。
3)維護消費關係及每一個partition的消費信息。
生產者代碼示例: