順序消息可以保證消息的消費順序和發(fā)送的順序一致,即先發(fā)送的先消費,后發(fā)送的后消費,常用于金融證券、電商業(yè)務(wù)等對消息指令順序有嚴格要求的場景。本文介紹云消息隊列 RocketMQ 版順序消息的概念、適用場景、實現(xiàn)原理以及使用過程中的注意事項。
什么是順序消息
順序消息是云消息隊列 RocketMQ 版提供的一種對消息發(fā)送和消費順序有嚴格要求的消息。對于一個指定的Topic,消息嚴格按照先進先出(FIFO)的原則進行消息發(fā)布和消費,即先發(fā)布的消息先消費,后發(fā)布的消息后消費。
順序消息分為分區(qū)順序消息和全局順序消息。
分區(qū)順序消息
對于指定的一個Topic,所有消息根據(jù)Sharding Key進行區(qū)塊分區(qū),同一個分區(qū)內(nèi)的消息按照嚴格的先進先出(FIFO)原則進行發(fā)布和消費。同一分區(qū)內(nèi)的消息保證順序,不同分區(qū)之間的消息順序不做要求。
- 適用場景
適用于性能要求高,以Sharding Key作為分區(qū)字段,在同一個區(qū)塊中嚴格地按照先進先出(FIFO)原則進行消息發(fā)布和消費的場景。
- 示例
- 用戶注冊需要發(fā)送驗證碼,以用戶ID作為Sharding Key,那么同一個用戶發(fā)送的消息都會按照發(fā)布的先后順序來消費。
- 電商的訂單創(chuàng)建,以訂單ID作為Sharding Key,那么同一個訂單相關(guān)的創(chuàng)建訂單消息、訂單支付消息、訂單退款消息、訂單物流消息都會按照發(fā)布的先后順序來消費。
阿里巴巴集團內(nèi)部電商系統(tǒng)均使用分區(qū)順序消息,既保證業(yè)務(wù)的順序,同時又能保證業(yè)務(wù)的高性能。
全局順序消息
對于指定的一個Topic,所有消息按照嚴格的先入先出(FIFO)的順序來發(fā)布和消費。
- 適用場景
適用于性能要求不高,所有的消息嚴格按照FIFO原則來發(fā)布和消費的場景。
- 示例
在證券處理中,以人民幣兌換美元為Topic,在價格相同的情況下,先出價者優(yōu)先處理,則可以按照FIFO的方式發(fā)布和消費全局順序消息。
如何實現(xiàn)順序消息
全局順序消息和分區(qū)順序消息原理一樣,下文以分區(qū)順序消息為例介紹在云消息隊列 RocketMQ 版中如何保證消息收發(fā)的順序。- 消息發(fā)送
如上圖所示,A1、B1、A2、A3、B2、B3是訂單A和訂單B的消息產(chǎn)生的順序,業(yè)務(wù)上要求同一訂單的消息保持順序,例如訂單A的消息發(fā)送和消費都按照A1、A2、A3的順序。如果是普通消息,訂單A的消息可能會被輪詢發(fā)送到不同的隊列中,不同隊列的消息將無法保持順序,而順序消息發(fā)送時云消息隊列 RocketMQ 版支持將Sharding Key相同(例如同一訂單號)的消息序路由到一個隊列中。
云消息隊列 RocketMQ 版服務(wù)端判定消息產(chǎn)生的順序性是參照同一生產(chǎn)者發(fā)送消息的時序。不同生產(chǎn)者、不同線程并發(fā)產(chǎn)生的消息,云消息隊列 RocketMQ 版服務(wù)端無法判定消息的先后順序。
- 消息存儲
如上圖所示,順序消息的Topic中,每個邏輯隊列對應(yīng)一個物理隊列,當消息按照順序發(fā)送到Topic中的邏輯隊列時,每個分區(qū)的消息將按照同樣的順序存儲到對應(yīng)的物理隊列中。
- 消息消費
云消息隊列 RocketMQ 版按照存儲的順序?qū)⑾⑼哆f給Consumer,Consumer收到消息后也不對消息順序做任何處理,按照接收到的順序進行消費。
Consumer消費消息時,同一Sharding Key的消息使用單線程消費,保證消息消費順序和存儲順序一致,最終實現(xiàn)消費順序和發(fā)布順序的一致。
注意事項
- 同一個Group ID只對應(yīng)一種類型的Topic,即不同時用于順序消息和無序消息的收發(fā)。
- 對于全局順序消息,建議消息不要有阻塞。同時運行多個實例,是為了防止工作實例意外退出而導(dǎo)致業(yè)務(wù)中斷。當工作實例退出時,其他實例可以立即接手工作,不會導(dǎo)致業(yè)務(wù)中斷,實際工作的只會有一個實例。
- 云消息隊列 RocketMQ 版服務(wù)端判定消息產(chǎn)生的順序性是參照單一生產(chǎn)者、單一線程并發(fā)下消息發(fā)送的時序。如果發(fā)送方有多個生產(chǎn)者或者有多個線程并發(fā)發(fā)送消息,則此時只能以到達云消息隊列 RocketMQ 版服務(wù)端的時序作為消息順序的依據(jù),和業(yè)務(wù)側(cè)的發(fā)送順序未必一致。
順序消息常見問題
- 同一條消息是否可以既是順序消息,又是定時消息和事務(wù)消息?
不可以。順序消息、定時消息、事務(wù)消息是不同的消息類型,三者是互斥關(guān)系,不能疊加在一起使用。
- 順序消息支持哪些地域?
支持云消息隊列 RocketMQ 版所有公共云地域和金融云地域。
- 為什么全局順序消息性能一般?
全局順序消息是嚴格按照FIFO的消息阻塞原則,即上一條消息沒有被成功消費,那么下一條消息會一直被存儲到Topic隊列中。如果想提高全局順序消息的TPS,可以升級實例配置,同時消息客戶端應(yīng)用盡量減少處理本地業(yè)務(wù)邏輯的耗時。
- 順序消息支持哪種消息發(fā)送方式?
順序消息只支持可靠同步發(fā)送方式,不支持異步發(fā)送方式,否則將無法嚴格保證順序。
- 順序消息是否支持集群消費和廣播消費?
順序消息暫時僅支持集群消費模式,不支持廣播消費模式。
TCP SDK示例代碼
- Java:收發(fā)順序消息
- C/C++:收發(fā)順序消息
- .NET:收發(fā)順序消息
HTTP SDK示例代碼
- Java:收發(fā)順序消息
- Go:收發(fā)順序消息
- Python:收發(fā)順序消息
- Node.js:收發(fā)順序消息
- PHP:收發(fā)順序消息
- C#:收發(fā)順序消息
- C++:收發(fā)順序消息