網站首頁 編程語言 正文
定義
隊列是 Apache RocketMQ 中消息存儲和傳輸的實際容器,也是 Apache RocketMQ 消息的最小存儲單元。 Apache RocketMQ 的所有主題都是由多個隊列組成,以此實現隊列數量的水平拆分和隊列內部的流式存儲。
隊列的主要作用如下:
- 存儲順序性 隊列天然具備順序性,即消息按照進入隊列的順序寫入存儲,同一隊列間的消息天然存在順序關系,隊列頭部為最早寫入的消息,隊列尾部為最新寫入的消息。消息在隊列中的位置和消息之間的順序通過位點(Offset)進行標記管理。
- 流式操作語義 Apache RocketMQ 基于隊列的存儲模型可確保消息從任意位點讀取任意數量的消息,以此實現類似聚合讀取、回溯讀取等特性,這些特性是RabbitMQ、ActiveMQ等非隊列存儲模型不具備的。
模型關系
在整個 Apache RocketMQ 的領域模型中,隊列所處的流程和位置如下:
Apache RocketMQ 默認提供消息可靠存儲機制,所有發送成功的消息都被持久化存儲到隊列中,配合生產者和消費者客戶端的調用可實現至少投遞一次的可靠性語義。
Apache RocketMQ 隊列模型和Kafka的分區(Partition)模型類似。在 Apache RocketMQ 消息收發模型中,隊列屬于主題的一部分,雖然所有的消息資源以主題粒度管理,但實際的操作實現是面向隊列。例如,生產者指定某個主題,向主題內發送消息,但實際消息發送到該主題下的某個隊列中。
Apache RocketMQ 中通過修改隊列數量,以此實現橫向的水平擴容和縮容。
內部屬性
讀寫權限
- 定義:當前隊列是否可以讀寫數據。
- 取值:由服務端定義,枚舉值如下
- 6:讀寫狀態,當前隊列允許讀取消息和寫入消息。
- 4:只讀狀態,當前隊列只允許讀取消息,不允許寫入消息。
- 2:只寫狀態,當前隊列只允許寫入消息,不允許讀取消息。
- 0:不可讀寫狀態,當前隊列不允許讀取消息和寫入消息。
- 約束:隊列的讀寫權限屬于運維側操作,不建議頻繁修改。
行為約束
每個主題下會由一到多個隊列來存儲消息,每個主題對應的隊列數與消息類型以及實例所處地域(Region)相關,隊列數暫不支持修改。
版本兼容性
隊列的名稱屬性在 Apache RocketMQ 服務端的不同版本中有如下差異:
- 服務端3.x/4.x版本:隊列名稱由{主題名稱}+{BrokerID}+{QueueID}三元組組成,和物理節點綁定。
- 服務端5.x版本:隊列名稱為一個集群分配的全局唯一的字符串組成,和物理節點解耦。
因此,在開發過程中,建議不要對隊列名稱做任何假設和綁定。如果您在代碼中自定義拼接隊列名稱并和其他操作進行綁定,一旦服務端版本升級,可能會出現隊列名稱無法解析的兼容性問題。
使用建議
按照實際業務消耗設置隊列數
Apache RocketMQ 的隊列數可在創建主題或變更主題時設置修改,隊列數量的設置應遵循少用夠用原則,避免隨意增加隊列數量。
主題內隊列數過多可能對導致如下問題:
- 集群元數據膨脹 Apache RocketMQ 會以隊列粒度采集指標和監控數據,隊列過多容易造成管控元數據膨脹。
- 客戶端壓力過大 Apache RocketMQ 的消息讀寫都是針對隊列進行操作,隊列過多容易產生空輪詢請求,增加系統負荷。
常見隊列增加場景
需要增加隊列實現物理節點負載均衡 Apache RocketMQ 每個主題的多個隊列可以分布在不同的服務節點上,在集群水平擴容增加節點后,為了保證集群流量的負載均衡,建議在新的服務節點上新增隊列,或將舊的隊列遷移到新的服務節點上。
需要增加隊列實現順序消息性能擴展 在 Apache RocketMQ 服務端4.x版本中,順序消息的順序性在隊列內生效的,因此順序消息的并發度會在一定程度上受隊列數量的影響,因此建議僅在系統性能瓶頸時再增加隊列。
消息隊列相關概念
生產者(Producer): 負責產生消息;
消費者(Consumer): 負責消費消息;
消息(Message): 在應用間傳送的數據。消息可以非常簡單,比如只包含文本字符串,也可以更復雜,可能包含嵌入對象;
消息隊列(Message Queue): 一種應用間的通信方式,消息發送后可以立即返回,由消息系統來確保消息的可靠傳遞。消息發布者只管把消息發布到 MQ 中而不用管誰來取,消息使用者只管從 MQ 中取消息而不管是誰發布的。這樣發布者和使用者都不用知道對方的存在。
消息代理(Message Broker): 負責存儲/轉發消息,轉發分為推和拉兩種。
- 拉是指Consumer主動從Message Broker獲取消息;
- 推是指Message Broker主動將Consumer感興趣的消息推送給Consumer。
消息隊列的消費場景
消息至多被消費一次
該場景是最容易滿足的,特點是整個消息隊列吞吐量大,實現簡單。適合能容忍丟消息,消息重復消費的任務。
a)Producer發送消息到Message Broker階段:
Producer發消息給Message Broker,不要求Message Broker對接收到的消息響應確認,Producer也不用關心Message Broker是否收到消息了。
b)Message Broker存儲/轉發階段:
對Message Broker的存儲不要求持久性,轉發消息時也不用關心Consumer是否真的收到了。
c)Consumer消費階段:
Consumer從Message Broker中獲取到消息后,可以從Message Broker刪除消息,或Message Broker在消息被Consumer拿去消費時刪除消息,不用關心Consumer最后對消息的處理結果。
消息至少被消費一次
適合不能容忍丟消息,但允許重復消費的任務。
a)Producer發送消息到Message Broker階段:
Producer發消息給Message Broker,Message Broker必須響應對消息的確認。
b)Message Broker存儲/轉發階段:
Message Broker必須提供持久性保障,轉發消息時,Message Broker需要Consumer通知刪除消息,才能將消息刪除。
c)Consumer消費階段:
Consumer從Message Broker中獲取到消息,必須在消費完成后,Message Broker上的消息才能被刪除。
消息僅被消費一次
適合對消息消費情況要求非常高的任務,實現較為復雜,這里的“僅被消費一次”包含如下兩種場景:
1)Message Broker上存儲的消息被Consumer僅消費一次,場景要求: a)Producer發送消息到Message Broker階段:
Producer發消息給Message Broker,不要求Message Broker對接收到的消息響應確認,Producer也不用關心Message Broker是否收到消息了。
b)Message Broker存儲/轉發階段:
Message Broker必須提供持久性保障,并且每條消息在其消費隊列里有唯一標識(這個唯一標識可以由Producer產生,也可以由Message Broker產生)。
c)Consumer消費階段:
Consumer從Message Broker中獲取到消息后,需要記錄下消費的消息標識,以便在后續消費中防止對某個消息重復消費。比如Consumer獲取到消息,消費完后,還沒來得及從Message Broker刪除消息,就掛了,這樣Message Broker如果把消息重新加入待消費隊列的話,那么這條消息就會被重復消費了。
2)Producer上產生的消息被Consumer僅消費一次,場景要求: a)Producer發送消息到Message Broker階段:
Producer發消息給Message Broker,Message Broker必須響應對消息的確認,并且Producer負責為該消息產生唯一標識,以防止Consumer重復消費(因為Producer發消息給Message Broker后,由于網絡問題沒收到Message Broker的響應,可能會重發消息給到Message Broker)。
b)Message Broker存儲/轉發階段:
Message Broker必須提供持久性保障,并且每條消息在其消費隊列里有唯一標識(這個唯一標識需要由Producer產生)。
c)Consumer消費階段:
Consumer從Message Broker中獲取到消息后,需要記錄下消費的消息標識,以便在后續消費中防止對某個消息重復消費。比如Consumer獲取到消息,消費完后,還沒來得及從Message Broker刪除消息,就掛了,這樣Message Broker如果把消息重新加入待消費隊列的話,那么這條消息就會被重復消費了。
實踐Hello World
/// <summary>
/// 發送按鈕事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(textBox1.Text.Trim()))
{
try
{
//判斷私有隊列是否存在
if (!MessageQueue.Exists(@".\Private$\MyPrivateQueue"))
{
//創建一個私有隊列
MessageQueue.Create(@".\Private$\MyPrivateQueue");
}
//實例一個隊列
var queue = new MessageQueue(@".\Private$\MyPrivateQueue");
//發送消息(第一個參數為消息內容,第二個參數為消息標簽或名稱)
queue.Send(textBox1.Text.Trim(), "TestLable");
}
catch (MessageQueueException ex)
{
MessageBox.Show(ex.Message, "異常消息", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
消息隊列好處或功能
1、消息可以在斷開連接的環境下發送。不需要同時運行正在發送和正在接收的應用程序。
2、使用快捷模式,消息可以非常快地發送。在快捷模式下,消息存儲在內存中。
3、對于可恢復的機制,消息可以使用有保證的交付方式發送。可恢復的消`息存儲在文件中。在服務器重新啟動時發送它們。
4、用訪問控制列表來保護消息隊列,可以確定哪些用戶可以發送或接收隊列中的消息。消息還可以加密,避免網絡嗅探器讀取其中的數據。消息在發送時可以指定優先級,這樣可以更快地處理高優先級的項。
5、Message Queuing 3.0支持多播消息的發送。
6、Message queuing 4.0支持病毒消息。病毒消息不能解析。可以定義病毒隊列中不能解析的消息是可以移動的。例如,如果從正常的隊列中讀取消息后,對應作業要把消息插入數據庫中,但消息不能插入數據庫,因此該作業失敗,該消息就會發送到病毒隊列中。有人負責處理病毒隊列,這個人應以能解析病毒消息的方式來處理該消息。
7、Message Queuing 5.0支持更安全學身份驗證算法,可以處理大量隊列(Message queuing 4.0在處理幾千個隊列時有性能問題)。
原文鏈接:https://blog.csdn.net/Androidxiaofei/article/details/129045741
相關推薦
- 2023-03-28 Python使用機器學習模型實現溫度預測詳解_python
- 2022-05-15 Python數據結構與算法中的棧詳解_python
- 2022-12-03 C++實現重載矩陣的部分運算符_C 語言
- 2022-05-18 ASP.NET?MVC自定義操作過濾器_實用技巧
- 2022-02-23 去除type=“number“輸入框聚焦時的上下箭頭
- 2022-05-22 使用Redis實現點贊取消點贊的詳細代碼_Redis
- 2023-05-30 Pandas.DataFrame的行名和列名的修改_python
- 2022-02-24 解決:this is incompatible with sql_mode=only_full_gr
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支