原創:小姐姐味道(微信公衆號ID:xjjdog),歡迎分享,轉載請保留出處。java
分佈式緩存方面,redis勇奪花魁。但對於消息隊列mq來講,還處於百花齊放的年代。程序員
緩存系統,基本上解決一個存取問題,就萬事大吉了,調用是同步的。對於消息隊列來講,就不太同樣。它的使用場景多樣,可靠級別多變,從生產端到消費端,過程是異步的。web
消息系統的設計要點,有不少。如今,很難有一個消息系統,可以兼顧下面提到的設計要點。它要是說能夠,那就是母體在吹。redis
因此不少時候,如今流行的Kafka、RabbitMQ、RocketMQ等,會被同時使用。若是你在作相關方面的選型,下面這些技術點就是權衡之處。那句話叫什麼來着:牝雞司晨,唯家之索。spring
本文將針對這些mq,從總體上抽象一些共有特性。包括:協議、類型、消費方式、堆積能力、高可用、高可靠、高性能、擴展性和生態。若是你想要深刻某個mq,這裏也有幾篇關於kafka的文章。數據庫
Kafka基礎知識索引 系統講解kafka的基礎知識 360度測試:KAFKA會丟數據麼?其高可用是否知足需求? 經過測試深刻探討kafka業務場景的使用編程
經過增長副本,能夠將數據的風險分散到多臺機器上。這就須要在主分片出現問題時,可以從副本中找出一個做爲新的主分片。有不少這樣的協調工具,好比zk。也有的mq,本身去實現這個過程。緩存
有的模式就比較浪費資源了,好比rocketmq,使用standby從機進行高可用保證,出問題再頂上來。微信
單機高可靠
集羣的高可靠方面,會有ack機制和多副本機制進行保證。對於單個節點來講,斷電或者主機異常,會是一個比較大的挑戰。爲了處理這種狀況,須要有刷盤機制或者其餘持久化機制。同時,數據的完整性校驗也是須要的,這也是相似kafka這種消息系統,數據量大的時候,啓動時間很是長的緣由。websocket
生產端
生產端除了要考慮buffer丟失的問題,還要考慮到一些發送錯誤的狀況,包括與集羣通訊的超時和重試處理。
消費端
消費端經過消息確認機制來保證消息已經被正確消費。因爲其間會發生不少異常狀況,因此大多數消息系統保證at least once語義。即確保消息至少被消費1次。
言外之意,消息是會重複的,消費者須要作到冪等,保證重複消費不會引發業務異常。
消費端一樣會發生一些錯誤狀況,有些mq能夠在屢次消費失敗後自動進入死信隊列,有些mq須要自行設計topic進行規劃。
消息從生產端發出,到消費者處理,其間的過程不能太長,對於使用拉模式來消費的mq來講,就要加快輪詢速度,並使用零拷貝一類的技術加快數據傳輸。
對於消息吞吐量來講,是一個生產端、mq節點、消費端共同優化的結果。目前主要有如下手段:
異步化
消息採用異步發送的方式,發送端不用同步等待,加快了處理速度。
batch
採用批量發送的方式,減小網絡傳輸的次數,方便進行數據壓縮。通常是內存中緩衝一個buffer,若是buffer滿了,或者到達了時間窗口,則進行一次傳輸。這可以顯著增長傳輸速度,但處理不當容易丟失數據。
順序IO
xjjdog已經在多篇文章提到,順序性操做磁盤,比隨機操做內存速度快的多。這也是kafka之類的消息隊列速度快的緣由之一,但要注意主題的數量(想下爲何)。
另外,還有其餘手段。好比優化操做系統參數,使用分片增長並行度等。
除了普通發送的消息,還有一些特殊用途的消息。順序性消息有全局有序和分區有序之分,通常用於有嚴格順序要求的業務。經過業務的設計,能夠規避全局有序這種很是耗性能的操做。
有些mq還支持定時消息(私覺得這種放業務系統更佳)。事務消息更加耗費性能,慎用。
還有一些mq,提供打tag、進行消息過濾的功能。好比訂單信息發送到一個topic,消費者只訂閱相關商品的訂單,某些有求隔離的狀況,很是有用。
推模式的實時性更好一些,但很差評估消費端能力,容易將其壓垮。同時,處理pub/sub,失敗重試等,也有不少挑戰。
這個傳輸協議,與功能關係不大。好比就有基於http協議的,或者redis協議,甚至websocket之上的stomp。
mqtt是物聯網IoT的應用協議,你會發現一大坨基於它的消息隊列。
堆積能力的體如今海量存儲上,好比存放在數據庫中(矛盾轉移),掛載很是大的磁盤等。但別高興的太早,大型集羣的啓動加載,以及故障再平衡,一般會花費比較長的時間。
堆積能力的另一個體現,就是對歷史消息的清理。通常有兩個策略:磁盤上線和過時清理,能夠結合需求靈活設置。
這方面除了比較新的mq系統,都作的不錯。
消息系統在目前的分佈式系統中設計中,做用愈來愈大。它的使用場景,包括但不限於:
削峯 用於承接超出業務系統處理能力的請求,使業務平穩運行。這可以大量節約成本,好比某些秒殺活動,並非針對峯值設計容量。
緩衝 在服務層和緩慢的落地層做爲緩衝層存在,做用與削峯相似,但主要用於服務內數據流轉。好比批量短信發送。
解耦 項目尹始,並不能肯定具體需求。消息隊列能夠做爲一個接口層,解耦重要的業務流程。只須要遵照約定,針對數據編程便可獲取擴展能力。
冗餘 消息數據可以採用一對多的方式,供多個毫無關聯的業務使用。
健壯性 消息隊列能夠堆積請求,因此消費端業務即便短期死掉,也不會影響主要業務的正常進行。
根據消息的體量和用途,目前能夠將分佈式mq大致分爲兩類。
一類用於業務系統,保證極高的可靠性。要求不可以丟失消息,好比訂單、支付等,有較高的SLA服務水準。這種狀況,對mq的功能要求也比較多,包括消息的可查性。
另一類用於大數據相關的系統,典型的特色就是吞吐量很是大。異常狀況下,丟失幾條消息,無傷大雅。
但消息系統,可能關注的只是mq自己。怎麼保證生產端、消費端、mq自己三者的可用性,是須要業務進行權衡的。
好比,前段時間xjjdog開源的okmq,就是用來解決一個特定場景的高可用問題。 開源一個kafka加強:okmq-1.0.0
做者簡介:小姐姐味道 (xjjdog),一個不容許程序員走彎路的公衆號。聚焦基礎架構和Linux。十年架構,日百億流量,與你探討高併發世界,給你不同的味道。個人我的微信xjjdog0,歡迎添加好友,進一步交流。