一、Kafka是一種分佈式的,基於發佈/訂閱的消息系統。web
二、經常使用Message Queue對比數據庫
RabbitMQ
RabbitMQ是使用Erlang編寫的一個開源的消息隊列,自己支持不少的協議:AMQP,XMPP, SMTP, STOMP,也正因如此,它很是重量級,更適合於企業級的開發。同時實現了Broker構架,這意味着消息在發送給客戶端時先在中心隊列排隊。對路由,負載均衡或者數據持久化都有很好的支持。服務器
Redis
Redis是一個基於Key-Value對的NoSQL數據庫,開發維護很活躍。雖然它是一個Key-Value數據庫存儲系統,但它自己支持MQ功能,因此徹底能夠當作一個輕量級的隊列服務來使用。對於RabbitMQ和Redis的入隊和出隊操做,各執行100萬次,每10萬次記錄一次執行時間。測試數據分爲128Bytes、512Bytes、1K和10K四個不一樣大小的數據。實驗代表:入隊時,當數據比較小時Redis的性能要高於RabbitMQ,而若是數據大小超過了10K,Redis則慢的沒法忍受;出隊時,不管數據大小,Redis都表現出很是好的性能,而RabbitMQ的出隊性能則遠低於Redis。網絡
ZeroMQ
ZeroMQ號稱最快的消息隊列系統,尤爲針對大吞吐量的需求場景。ZMQ可以實現RabbitMQ不擅長的高級/複雜的隊列,可是開發人員須要本身組合多種技術框架,技術上的複雜度是對這MQ可以應用成功的挑戰。ZeroMQ具備一個獨特的非中間件的模式,你不須要安裝和運行一個消息服務器或中間件,由於你的應用程序將扮演了這個服務角色。你只須要簡單的引用ZeroMQ程序庫,可使用NuGet安裝,而後你就能夠愉快的在應用程序之間發送消息了。可是ZeroMQ僅提供非持久性的隊列,也就是說若是宕機,數據將會丟失。其中,Twitter的Storm 0.9.0之前的版本中默認使用ZeroMQ做爲數據流的傳輸(Storm從0.9版本開始同時支持ZeroMQ和Netty做爲傳輸模塊)。app
ActiveMQ
ActiveMQ是Apache下的一個子項目。 相似於ZeroMQ,它可以以代理人和點對點的技術實現隊列。同時相似於RabbitMQ,它少許代碼就能夠高效地實現高級應用場景。負載均衡
Kafka/Jafka
Kafka是Apache下的一個子項目,是一個高性能跨語言分佈式發佈/訂閱消息隊列系統,而Jafka是在Kafka之上孵化而來的,即Kafka的一個升級版。具備如下特性:快速持久化,能夠在O(1)的系統開銷下進行消息持久化;高吞吐,在一臺普通的服務器上既能夠達到10W/s的吞吐速率;徹底的分佈式系統,Broker、Producer、Consumer都原生自動支持分佈式,自動實現複雜均衡;支持Hadoop數據並行加載,對於像Hadoop的同樣的日誌數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。Kafka經過Hadoop的並行加載機制來統一了在線和離線的消息處理。Apache Kafka相對於ActiveMQ是一個很是輕量級的消息系統,除了性能很是好以外,仍是一個工做良好的分佈式系統。框架
三、經驗證,順序寫磁盤效率比隨機寫內存還要高,這是Kafka高吞吐率的一個很重要的保證。異步
四、每一條消息被髮送到broker時,會根據paritition規則選擇被存儲到哪個partition。若是partition規則設置的合理,全部消息能夠均勻分佈到不一樣的partition裏,這樣就實現了水平擴展。(若是一個topic對應一個文件,那這個文件所在的機器I/O將會成爲這個topic的性能瓶頸,而partition解決了這個問題)。分佈式
五、對於傳統的message queue而言,通常會刪除已經被消費的消息,而Kafka集羣會保留全部的消息,不管其被消費與否。固然,由於磁盤限制,不可能永久保留全部數據(實際上也不必),所以Kafka提供兩種策略去刪除舊數據。一是基於時間,二是基於partition文件大小。例如能夠經過配置$KAFKA_HOME/config/server.properties
,讓Kafka刪除一週前的數據,也可經過配置讓Kafka在partition文件超過1GB時刪除舊數據。oop
六、Kafka讀取特定消息的時間複雜度爲O(1),即與文件大小無關,因此這裏刪除文件與Kafka性能無關,選擇怎樣的刪除策略只與磁盤以及具體的需求有關。另外,Kafka會爲每個consumer group保留一些metadata信息—當前消費的消息的position,也即offset。這個offset由consumer控制。正常狀況下consumer會在消費完一條消息後線性增長這個offset。固然,consumer也可將offset設成一個較小的值,從新消費一些消息。由於offet由consumer控制,因此Kafka broker是無狀態的,它不須要標記哪些消息被哪些consumer過,不須要經過broker去保證同一個consumer group只有一個consumer能消費某一條消息,所以也就不須要鎖機制,這也爲Kafka的高吞吐率提供了有力保障。
七、一條消息只有被「in sync」 list裏的全部follower都從leader複製過去纔會被認爲已提交。這樣就避免了部分數據被寫進了leader,還沒來得及被任何follower複製就宕機了,而形成數據丟失(consumer沒法消費這些數據)。而對於producer而言,它能夠選擇是否等待消息commit,這能夠經過request.required.acks
來設置。這種機制確保了只要「in sync」 list有一個或以上的flollower,一條被commit的消息就不會丟失。
八、這裏的複製機制即不是同步複製,也不是單純的異步複製。事實上,同步複製要求「活着的」follower都複製完,這條消息纔會被認爲commit,這種複製方式極大的影響了吞吐率(高吞吐率是Kafka很是重要的一個特性)。而異步複製方式下,follower異步的從leader複製數據,數據只要被leader寫入log就被認爲已經commit,這種狀況下若是follwer都落後於leader,而leader忽然宕機,則會丟失數據。而Kafka的這種使用「in sync」 list的方式則很好的均衡了確保數據不丟失以及吞吐率。follower能夠批量的從leader複製數據,這樣極大的提升複製性能(批量寫磁盤),極大減小了follower與leader的差距(前文有說到,只要follower落後leader不太遠,則被認爲在「in sync」 list裏)。
九、每個consumer實例都屬於一個consumer group,每一條消息只會被同一個consumer group裏的一個consumer實例消費。(不一樣consumer group能夠同時消費同一條消息)
十、實際上,Kafka的設計理念之一就是同時提供離線處理和實時處理。根據這一特性,可使用Storm這種實時流處理系統對消息進行實時在線處理,同時使用Hadoop這種批處理系統進行離線處理,還能夠同時將數據實時備份到另外一個數據中心,只須要保證這三個操做所使用的consumer在不一樣的consumer group便可。
十一、Kafka默認保證At least once
,而且容許經過設置producer異步提交來實現At most once
。
十二、在1臺機器上跑多個實例對吞吐率的增長不會有太大幫忙,由於網卡已經基本飽和了
1三、須要注意的是,replication factor並不會影響consumer的吞吐率測試,由於consumer只會從每一個partition的leader讀數據,而與replicaiton factor無關。一樣,consumer吞吐率也與同步複製仍是異步複製無關。
1四、上面的全部測試都基於短消息(payload 100字節),而正如上文所說,短消息對Kafka來講是更難處理的使用方式,能夠預期,隨着消息長度的增大,records/second會減少,但MB/second會有所提升。下圖是records/second與消息長度的關係圖。
正如咱們所預期的那樣,隨着消息長度的增長,每秒鐘所能發送的消息的數量逐漸減少。可是若是看每秒鐘發送的消息的總大小,它會隨着消息長度的增長而增長,以下圖所示。
從上圖能夠看出,當消息長度爲10字節時,由於要頻繁入隊,花了太多時間獲取鎖,CPU成了瓶頸,並不能充分利用帶寬。但從100字節開始,咱們能夠看到帶寬的使用逐漸趨於飽和(雖然MB/second仍是會隨着消息長度的增長而增長,但增長的幅度也愈來愈小)。
1五、Kafka支持對消息集合進行壓縮,Producer端能夠經過GZIP或Snappy格式對消息集合進行壓縮。Producer端進行壓縮以後,在Consumer端需進行解壓。壓縮的好處就是減小傳輸的數據量,減輕對網絡傳輸的壓力,在對大數據處理上,瓶頸每每體如今網絡上而不是CPU(壓縮和解壓會耗掉部分CPU資源)。那麼如何區分消息是壓縮的仍是未壓縮的呢,Kafka在消息頭部添加了一個 描述壓縮屬性字節,這個字節的後兩位表示消息的壓縮採用的編碼,若是後兩位爲0,則表示消息未被壓縮。