談談分布式消息隊列的一些特性,比較兩種比較常用的消息隊列——NSQ和Kafka
1 消息隊列的作用
- 解耦,將一個流程加入一層數據接口拆分成兩個部分,上游專注通知,下游專注處理
- 緩沖,應對流量的突然上漲變更,消息隊列有很好的緩沖削峰作用
- 異步,上游發送消息以后可以馬上返回,處理工作交給下游進行
- 廣播,讓一個消息被多個下游進行處理
- 冗余,保存處理的消息,防止消息處理失敗導致的數據丟失
2 NSQ
2.1 組件
NSQ主要包含3個組件:
- nsqd:在服務端運行的守護進程,負責接收,排隊,投遞消息給客戶端。能夠獨立運行,不過通常是由 nsqlookupd 實例所在集群配置的
- nsqlookup:為守護進程,負責管理拓撲信息並提供發現服務。客戶端通過查詢 nsqlookupd 來發現指定話題(topic)的生產者,並且 nsqd 節點廣播話題(topic)和通道(channel)信息
- nsqadmin:一套WEB UI,用來匯集集群的實時統計,並執行不同的管理任務
2.2 特性
- 消息默認不可持久化,雖然系統支持消息持久化存儲在磁盤中(通過設置 –mem-queue-size 為零),不過默認情況下消息都在內存中
- 消息最少會被投遞一次,假設成立於 nsqd 節點沒有錯誤
- 消息無序,是由重新隊列(requeues),內存和磁盤存儲的混合導致的,實際上,節點間不會共享任何信息。它是相對的簡單完成疏松隊列
- 支持無 SPOF 的分布式拓撲,nsqd 和 nsqadmin 有一個節點故障不會影響到整個系統的正常運行
- 支持requeue,延遲消費機制
- 消息push給消費者
2.3 流程
單個nsqd可以有多個Topic,每個Topic又可以有多個Channel。Channel能夠接收Topic所有消息的副本,從而實現了消息多播分發;而Channel上的每個消息被分發給它的訂閱者,從而實現負載均衡,所有這些就組成了一個可以表示各種簡單和復雜拓撲結構的強大框架。
3 Kafka
3.1 整體架構
3.2 角色
- Producer:消息發布者,負責發布消息到Kafka broker
- Consumer:消息消費者,向Kafka broker讀取消息的客戶端
- Broker:Kafka集群中的一個服務器
- Topic:每條發布到Kafka集群的消息都有一個類別,這個類別被稱為Topic。
- Consumer Group:Consumer Group對應NSQ的Channel,一個Consumer Group能夠消費一個Topic中的所有消息。
- Partition:Parition是物理上的概念,每個Topic包含一個或多個Partition,消息保證在partition中有序,Consumer可以消費多個partition的消息。
Topic & Partition
Topic在邏輯上可以被認為是一個queue,每條消費都必須指定它的Topic,可以簡單理解為必須指明把這條消息放進哪個queue里。為了使得Kafka的吞吐率可以線性提高,物理上把Topic分成一個或多個Partition,每個Partition在物理上對應一個文件夾,該文件夾下存儲這個Partition的所有消息和索引文件。
Producer消息路由
Producer發送消息到broker時,會根據Paritition機制選擇將其存儲到哪一個Partition。如果Partition機制設置合理,所有消息可以均勻分布到不同的Partition里,這樣就實現了負載均衡。
在發送一條消息時,可以指定這條消息的key,Producer根據這個key和Partition機制來判斷應該將這條消息發送到哪個Parition。消息在Partition中是有序的,同時一個Partition短時間內會提供給特定下游消費的Consumer 消費,這樣可以提供業務中某些場景的有序保證。
Consumer Group
使用Consumer high level API時,同一Topic的一條消息只能被同一個Consumer Group內的一個Consumer消費,但多個Consumer Group可同時消費這一消息。
這是Kafka用來實現一個Topic消息的廣播(發給所有的Consumer)和單播(發給某一個Consumer)的手段。一個Topic可以對應多個Consumer Group。如果需要實現廣播,只要每個Consumer有一個獨立的Group就可以了。要實現單播只要所有的Consumer在同一個Group里。用Consumer Group還可以將Consumer進行自由的分組而不需要多次發送消息到不同的Topic。
3.3 特性
- 存儲上使用了順序訪問磁盤和零拷貝技術(將磁盤文件的數據復制到頁面緩存中一次,然后將數據從頁面緩存直接發送到網絡中),使得其具有非常強大的吞吐性能
- 數據落磁盤,能夠持久化,支持消息的重新消費
- 投遞保證支持 at least one / at most one / exactly once
- Partition / Comsumer Group內保證消息有序
4 對比
4.1 存儲
- NSQ 默認是把消息放到內存中,只有當隊列里消息的數量超過–mem-queue-size配置的限制時,才會對消息進行持久化。
- Kafka 會把寫到磁盤中進行持久化,並通過順序讀寫磁盤來保障性能。持久化能夠讓Kafka做更多的事情:消息的重新消費(重置offset);讓數據更加安全,不那么容易丟失。同時Kafka還通過partition的機制,對消息做了備份,進一步增強了消息的安全性。
4.2 推拉模型
- NSQ 使用的是推模型,推模型能夠使得時延非常小,消息到了馬上就能夠推送給下游消費,但是下游消費能夠無法控制,推送過快可能導致下游過載。
- Kafka 使用的拉模型,拉模型能夠讓消費者自己掌握節奏,但是這樣輪詢會讓整個消費的時延增加,不過消息隊列本身對時延的要求不是很大,這一點影響不是很大。
4.3 消息的順序性
- NSQ 因為不能夠把特性消息和消費者對應起來,所以無法實現消息的有序性。
- Kafka 因為消息在Partition中寫入是有序的,同時一個Partition只能夠被一個Consumer消費,這樣就可能實現消息在Partition中的有序。自定義寫入哪個Partition的規則能夠讓需要有序消費的相關消息都進入同一個Partition中被消費,這樣達到”全局有序“
- 本文作者: Sixzeroo
- 本文鏈接: https://www.liuin.cn/2018/07/11/分布式消息隊列-NSQ-和-Kafka-對比/
- 發布時間: 2018年7月11日 - 22時07分
- 最后更新: 2019年4月1日 - 16時04分
- 版權聲明: 本博客所有文章除特別聲明外,均采用 CC BY-NC-SA 3.0 許可協議。轉載請注明出處