從0到1設計一個MQ消息隊列

消息隊列做爲系統解耦,流量控制的利器,是分佈式系統核心組件之一。java

瞭解消息隊列背後的實現是很是重要的。sql

今天,咱們就一塊兒來探討設計一個消息隊列背後的技術。數據庫

消息隊列總體設計思路

主要是設計一個總體的消息被消費的數據流。編程

這裏會涉及到:消息生產Producer、Broker(消息服務端)、消息消費者Consumer。網絡

1.Producer(消息生產者):發送消息到Broker。
nosql

2.Broker(服務端):Broker這個概念主要來自於Apache的ActiveMQ,特指消息隊列的服務端。分佈式

主要功能就是:把消息從發送端傳送到接收端,這裏會涉及到消息的存儲、消息通信機制等。oop

3.Consumer(消息消費者):從消息隊列接收消息,consumer回覆消費確認。性能

Broker(消息隊列服務端)設計重點

1)消息的轉儲:在更合適的時間點投遞,或者經過一系列手段輔助消息最終能送達消費機。ui

2)規範一種範式和通用的模式,以知足解耦、最終一致性、錯峯等需求。

3)其實簡單理解就是一個消息轉發器,把一次RPC作成兩次RPC,發送者把消息投遞到broker,broker再將消息轉發一手到接收端。

總結起來就是兩次RPC加一次轉儲,若是要作消費確認,則是三次RPC。

爲了實現上述消息隊列的基礎功能:

1)消息的傳輸

2)存儲

3)消費

就須要涉及到以下三個方面的設計:

1)通訊協議

2)存儲選擇

3)消費關係維護

通信協議

消息Message:既是信息的載體,消息發送者須要知道如何構造消息,消息接收者須要知道如何解析消息,它們須要按照一種統一的格式描述消息,這種統一的格式稱之爲消息協議。

傳統的通訊協議標準有XMPP和AMQP協議等,如今更多的消息隊列從性能的角度出發使用本身設計實現的通訊協議。

1.JMS

JMS(Java MessageService)其實是指JMS API。JMS是由Sun公司早期提出的消息標準,旨在爲java應用提供統一的消息操做,包括建立消息、發送消息、接收消息等。

JMS一般包含以下一些角色:

JMS提供了兩種消息模型:

1)點對點

2)以及publish-subscribe(發佈訂閱)模型。

當採用點對點模型時,消息將發送到一個隊列,該隊列的消息只能被一個消費者消費。

而採用發佈訂閱模型時,消息能夠被多個消費者消費。

在發佈訂閱模型中,生產者和消費者徹底獨立,不須要感知對方的存在。

2.AMQP

AMQP是 Advanced Message Queuing Protocol,即高級消息隊列協議。

AMQP不是一個具體的消息隊列實現,而 是一個標準化的消息中間件協議。

目標是讓不一樣語言,不一樣系統的應用互相通訊,並提供一個簡單統一的模型和編程接口。 目前主流的ActiveMQ和RabbitMQ都支持AMQP協議。

AMQP是一種協議,更準確的說是一種binary wire-level protocol(連接協議)。這是其和JMS的本質差異,AMQP不從API層進行限定,而是直接定義網絡交換的數據格式。

JMS和AMQP比較

JMS: 只容許基於JAVA實現的消息平臺的之間進行通訊

AMQP: AMQP容許多種技術同時進行協議通訊

3.Kafka的通訊協議

Kafka的Producer、Broker和Consumer之間採用的是一套自行設計的基於TCP層的協議。Kafka的這套協議徹底是爲了Kafka自身的業務需求而定製的。

存儲選型

對於分佈式系統,存儲的選擇有如下幾種

1.內存

2.本地文件系統

3.分佈式文件系統

4.nosql

5.DB

從速度上內存顯然是最快的,對於容許消息丟失,消息堆積能力要求不高的場景(例如日誌),內存會是比較好的選擇。

DB則是最簡單的實現可靠存儲的方案,很適合用在可靠性要求很高,最終一致性的場景(例如交易消息),對於不須要100%保證數據完整性的場景,要求性能和消息堆積的場景,hbase也是一個很好的選擇。

理論上,從速度來看,文件系統>分佈式KV(持久化)>分佈式文件系統>數據庫,而可靠性卻截然相反。

仍是要從支持的業務場景出發做出最合理的選擇,若是大家的消息隊列是用來支持支付/交易等對可靠性要求很是高,但對性能和量的要求沒有這麼高,並且沒有時間精力專門作文件存儲系統的研究,DB是最好的選擇。

對於不須要100%保證數據完整性的場景,要求性能和消息堆積的場景,hbase也是一個很好的選擇,典型的好比 kafka的消息落地可使用hadoop。

消費關係處理

如今咱們的消息隊列初步具有了轉儲消息的能力。

下面一個重要的事情就是解析發送接收關係,進行正確的消息投遞了。

市面上的消息隊列定義了一堆讓人暈頭轉向的名詞,如JMS 規範中的Topic/Queue,Kafka裏面的Topic/Partition/ConsumerGroup,RabbitMQ裏面的Exchange等等。

拋開現象看本質,無外乎是單播與廣播的區別。

所謂單播,就是點到點;而廣播,是一點對多點。

爲了實現廣播功能,咱們必需要維護消費關係,一般消息隊列自己不維護消費訂閱關係,能夠利用zookeeper等成熟的系統維護消費關係,在消費關係發生變化時下發通知。

消息隊列須要支持高級特性

  • 消息的順序

  • 投遞可靠性保證

  • 消息持久化

  • 支持不一樣消息模型

  • 多實例集羣功能

  • 事務特性等

除了上述的消息隊列基本功能之外,消息隊列在某些特殊的場景還須要支持事務,消息重試等功能。

以上,是從0到1設計一個MQ消息隊列的經驗分享。

相關文章
相關標籤/搜索