Kafka知識點匯總

jopen 10年前發布 | 15K 次閱讀 消息系統

1、Kafka是一種分布式的,基于發布/訂閱的消息系統。

2、常用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僅提供非持久性的隊列,也就是說如果宕機,數據將會丟失。其中,推ter的Storm 0.9.0以前的版本中默認使用ZeroMQ作為數據流的傳輸(Storm從0.9版本開始同時支持ZeroMQ和Netty作為傳輸模塊)。

  • 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是一個非常輕量級的消息系統,除了性能非常好之外,還是一個工作良好的分布式系統。

3、經驗證,順序寫磁盤效率比隨機寫內存還要高,這是Kafka高吞吐率的一個很重要的保證

4、每一條消息被發送到broker時,會根據paritition規則選擇被存儲到哪一個partition。如果partition規則設置的合理,所有消息可以均勻分布到不同的partition里,這樣就實現了水平擴展。(如果一個topic對應一個文件,那這個文件所在的機器I/O將會成為這個topic的性能瓶頸,而partition解決了這個問題)。

5、對于傳統的message queue而言,一般會刪除已經被消費的消息,而Kafka集群會保留所有的消息,無論其被消費與否。當然,因為磁盤限制,不可能永久保留所有數據(實際上也沒必要),因此Kafka提供兩種策略去刪除舊數據。一是基于時間,二是基于partition文件大小。例如可以通過配置$KAFKA_HOME/config/server.properties,讓Kafka刪除一周前的數據,也可通過配置讓Kafka在partition文件超過1GB時刪除舊數據。

6、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的高吞吐率提供了有力保障。

7、一條消息只有被“in sync” list里的所有follower都從leader復制過去才會被認為已提交。這樣就避免了部分數據被寫進了leader,還沒來得及被任何follower復制就宕機了,而造成數據丟失(consumer無法消費這些數據)。而對于producer而言,它可以選擇是否等待消息commit,這可以通過request.required.acks來設置。這種機制確保了只要“in sync” list有一個或以上的flollower,一條被commit的消息就不會丟失。

8、這里的復制機制即不是同步復制,也不是單純的異步復制。事實上,同步復制要求“活著的”follower都復制完,這條消息才會被認為commit,這種復制方式極大的影響了吞吐率(高吞吐率是Kafka非常重要的一個特性)。而異步復制方式下,follower異步的從leader復制數據,數據只要被leader寫入log就被認為已經commit,這種情況下如果follwer都落后于leader,而leader突然宕機,則會丟失數據。而Kafka的這種使用“in sync” list的方式則很好的均衡了確保數據不丟失以及吞吐率。follower可以批量的從leader復制數據,這樣極大的提高復制性能(批量寫磁盤),極大減少了follower與leader的差距(前文有說到,只要follower落后leader不太遠,則被認為在“in sync” list里)。

9、每一個consumer實例都屬于一個consumer group,每一條消息只會被同一個consumer group里的一個consumer實例消費。(不同consumer group可以同時消費同一條消息)

10、實際上,Kafka的設計理念之一就是同時提供離線處理和實時處理。根據這一特性,可以使用Storm這種實時流處理系統對消息進行實時在線處理,同時使用Hadoop這種批處理系統進行離線處理,還可以同時將數據實時備份到另一個數據中心,只需要保證這三個操作所使用的consumer在不同的consumer group即可。

11、Kafka默認保證At least once,并且允許通過設置producer異步提交來實現At most once

12、在1臺機器上跑多個實例對吞吐率的增加不會有太大幫忙,因為網卡已經基本飽和了

13、需要注意的是,replication factor并不會影響consumer的吞吐率測試,因為consumer只會從每個partition的leader讀數據,而與replicaiton factor無關。同樣,consumer吞吐率也與同步復制還是異步復制無關。

14、上面的所有測試都基于短消息(payload 100字節),而正如上文所說,短消息對Kafka來說是更難處理的使用方式,可以預期,隨著消息長度的增大,records/second會減小,但MB/second會有所提高。下圖是records/second與消息長度的關系圖。

正如我們所預期的那樣,隨著消息長度的增加,每秒鐘所能發送的消息的數量逐漸減小。但是如果看每秒鐘發送的消息的總大小,它會隨著消息長度的增加而增加,如下圖所示。

從上圖可以看出,當消息長度為10字節時,因為要頻繁入隊,花了太多時間獲取鎖,CPU成了瓶頸,并不能充分利用帶寬。但從100字節開始,我們可以看到帶寬的使用逐漸趨于飽和(雖然MB/second還是會隨著消息長度的增加而增加,但增加的幅度也越來越小)。


來自: http://my.oschina.net/drl/blog/600364

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!