本文介紹雲訊息佇列 RocketMQ 版中隊列(MessageQueue)的定義、模型關係、內部屬性、版本相容性及使用建議。
定義
隊列是雲訊息佇列 RocketMQ 版中訊息儲存和傳輸的實際容器,也是雲訊息佇列 RocketMQ 版訊息的最小儲存單元。
雲訊息佇列 RocketMQ 版的所有主題都是由多個隊列組成,以此實現隊列數量的水平分割和隊列內部的流式儲存。
- 儲存順序性
隊列天然具備順序性,即訊息按照進入隊列的順序寫入儲存,同一隊列間的訊息天然存在循序關聯性,隊列頭部為最早寫入的訊息,隊列尾部為最新寫入的訊息。訊息在隊列中的位置和訊息之間的順序通過位點(Offset)進行標記管理。
- 流式操作語義
雲訊息佇列 RocketMQ 版基於隊列的儲存模型可確保訊息從任意位點讀取任意數量的訊息,以此實作類別似彙總讀取、回溯讀取等特性,這些特性是RabbitMQ、ActiveMQ等非佇列儲存體模型不具備的。
模型關係
雲訊息佇列 RocketMQ 版預設提供訊息可靠儲存機制,所有發送成功的訊息都被持久化儲存到隊列中,配合生產者和消費者用戶端的調用可實現至少投遞一次的可靠性語義。
雲訊息佇列 RocketMQ 版隊列模型和Kafka的分區(Partition)模型類似。在雲訊息佇列 RocketMQ 版訊息收發模型中,隊列屬於主題的一部分,雖然所有的訊息資源以主題粒度管理,但實際的操作實現是面向隊列。例如,生產者指定某個主題,向主題內發送訊息,但實際訊息發送到該主題下的某個隊列中。
雲訊息佇列 RocketMQ 版中通過修改隊列數量,以此實現橫向的水平擴容和縮容。
內部屬性
- 定義:當前隊列是否可以讀寫資料。
- 取值:由服務端定義,枚舉值如下
- 6:讀寫狀態,當前隊列同時允許寫入訊息和讀取訊息作業。
- 4:唯讀狀態,當前隊列只允許讀取歷史訊息,不允許向隊列寫入新的訊息。
- 2:唯寫狀態,當前隊列只允許寫入新訊息,不允許讀取訊息。
- 0:不可讀寫狀態,當前隊列不允許任何讀寫操作。
- 約束:隊列的讀寫權限屬於營運側操作,不建議頻繁修改。
行為約束
每個主題下會由一到多個隊列來儲存訊息,每個主題對應的隊列數與訊息類型以及執行個體所處地區(Region)相關,隊列數暫不支援修改。
版本相容性
- 服務端3.x/4.x版本:隊列名稱由{主題名稱}+{BrokerID}+{QueueID}三元組組成,和物理節點綁定。
- 服務端5.x版本:隊列名稱為一個叢集分配的全域唯一的字串組成,和物理節點解耦。
因此,在開發過程中,建議不要對隊列名稱做任何假設和綁定。如果您在代碼中自訂拼接隊列名稱並和其他動作進行綁定,一旦服務端版本升級,可能會出現隊列名稱無法解析的相容性問題。
使用建議
按照實際業務消耗設定隊列數
雲訊息佇列 RocketMQ 版的應遵循少用夠用原則,避免隨意增加隊列數量。
- 叢集中繼資料膨脹
雲訊息佇列 RocketMQ 版會以隊列粒度採集指標和監控資料,隊列過多容易造成管控中繼資料膨脹。
- 用戶端壓力過大
雲訊息佇列 RocketMQ 版的訊息讀寫都是針對隊列進行操作,隊列過多容易產生空輪詢請求,增加系統負荷。
常見隊列增加情境
- 需要增加隊列實現物理節點負載平衡
雲訊息佇列 RocketMQ 版每個主題的多個隊列可以分布在不同的服務節點上,在叢集水平擴容增加節點後,為了保證叢集流量的負載平衡,建議在新的服務節點上新增隊列,或將舊的隊列遷移到新的服務節點上。
- 需要增加隊列實現順序訊息效能擴充
在雲訊息佇列 RocketMQ 版服務端4.x版本中,順序訊息的順序性在隊列內生效的,因此順序訊息的並發度會在一定程度上受隊列數量的影響,因此建議僅在系統效能瓶頸時再增加隊列。
- 非順序訊息消費的負載平衡與隊列數無關
雲訊息佇列 RocketMQ 版服務端5.x系列執行個體的消費者負載平衡已升級為訊息粒度負載平衡,同一隊內的訊息可以被所有消費者均勻消費。因此,您無需擔心隊列數對消費並發度的影響。負載平衡詳細資料,請參見消費者負載平衡。