消息隊列
- 介紹
- 開發環境
- 技術支持
- 安裝
- 補充介紹
- 消息隊列概念
- 聯繫
- 工作流程
介紹
在併發編程中,有一種特殊的隊列叫阻塞隊列,一般可以用來實現生產者-消費者模型。生產者生產數據到隊列中,消費者取出數據進行處理。它存在諸多好處:
- 解耦合 支持開發 支持忙閒不均 削峯填谷
舉個例子:食堂托盤架
1、後廚=>生產者 2、同學=>消費者 3、托盤架最多10個->有界容量
4、後廚看到架子滿了->阻塞(休息),等同學拿走一個才被叫醒
5、同學發現架子空了->阻塞(休息),等後廚放新托盤才被叫醒
整個過程中:
- 沒有人原地轉圈(cpu 0%空轉)
- 不會出現“發現架子空了”或“空架子卻硬拿的錯亂->這就是阻塞隊列要乾的全部事情
在實際後台開發中,尤其是分佈式系統裏,跨主機之間使用生產者-消費者模型,是非常普遍的需求。因此,我們通常會把阻塞隊列封裝成一個獨立的服務器,並且賦予其豐富的功能。這樣的服務器程序稱為消息隊列(Message Queue,MQ)。例如常見的消息隊列:RabblitMQ Kafka RocketMQ ActiveMQ
開發環境
- Linux(Ubuntu-22.04)
- vscode/vim
- g++/gdb
- Makefile
技術支持
- 開發諸語言:C++
- 序列化框架:protobuf二進制序列化
- 網絡通信:
自定義應用層協議+muduo庫:對tcp長連接的封裝,並且使用epoll事件驅動模式,實現高併發服務器與客户端 - 源數據信息數據庫:SQLite3
- 單元測試框架:Gtest
安裝
安裝wget
sudo apt install wget
補充介紹
消息隊列概念
日常學習中,消息隊列是分佈式系統裏解耦的核心工具。通俗來講,消息隊列就是一個”中轉站“,專門用來存儲和傳遞不同系統和模塊之間的”消息“,避免他們直接依賴。
消息隊列的價值體現在解耦、削峯和異步通信三個方面。
1、解耦:讓發送消息的”生產者“和接收消息的”消費者“互不認識。生產者只需將”消息“發送給隊列,不用管誰來接。消費者只需要從隊列拿消息,不用管誰發來。即使一方出故障,另一方也不影響。
2、削峯:應對突發的高流量。例如,秒殺活動時,會有大量的請求,消息隊列可以把這些請求存起來,讓消費者按照自己的能力慢慢處理,避免直接壓跨後端系統。
3、異步:減少接口的響應時間。比如,用户下單後不需要等 “扣庫存、發通知、記日誌” 這些操作全做完才返回結果,只需要把這些操作對應的消息發給隊列,立即告訴用户”下單成功“,後續操作讓消費者異步完成。
聯繫
生產者-消費者模型時消息隊列的設計核心思想,消息隊列是這個模型工業級實現工具。
例如:
- 沒有MQ時:生產者 - 消費者模型就像 “你(生產者)把文件放在公司前台(緩衝區),同事(消費者)自己去前台拿”—— 前台就是簡單的 “緩衝區”,但只能本地用、容易丟文件、沒人管排隊;
- 有了 MQ 後,前台升級成了 “專業快遞站(MQ)”—— 不僅能存文件,還能保證不丟、按順序送、支持異地取,甚至能通知同事 “有新文件”,這就是工業級的封裝。
工作流程
以 “用户下單後,扣庫存、發通知” 為例,完整流程就是生產者 - 消費者模型的落地:
1、生產者發送消息:用户下單接口(生產者)執行完 “創建訂單” 後,不需要同步等扣庫存、發通知,直接把 “扣庫存”“發通知” 兩個任務封裝成消息,發送到 MQ 的對應隊列;
2、MQ存儲消息:MQ 接收到消息後,先持久化到磁盤(避免宕機丟失),然後按順序存放在隊列中
3、消費者處理消息:庫存服務(消費者 1)、通知服務(消費者 2)分別監聽 MQ 的對應隊列,各自從隊列中獲取消息,執行 “扣庫存”“發通知” 邏輯
4、消息確認和處理:消費者處理完消息後,向 MQ 發送 “確認信號(Ack)”,MQ 收到後刪除該消息;如果消費者處理失敗,MQ 會重新投遞消息,避免丟失。
整個過程中,生產者和消費者完全解耦—哪怕庫存服務宕機,下單接口依然能正常返回,MQ 會暫存消息,等庫存服務恢復後再投遞,這就是生產者 - 消費者模型 “解耦、異步” 的核心價值,而 MQ 讓這個價值在分佈式系統中穩定落地。