前言:之前做過的一些項目中有時候會接觸到消息隊列,但是對消息隊列並沒有一個很清楚的認知,本篇文章將會詳細分析和歸納一些筆記,以供后續學習。
一、消息對列概念
從本質上說消息對列就是一個隊列結構的中間件,也就是說消息放入這個中間件之后就可以直接返回,並不需要系統立即處理,而另外會有一個程序讀取這些數據,並按順序進行逐次處理。
二、結構
由一個業務系統進行入隊,把消息逐次插入到消息隊列中,插入成功之后直接返回成功的結果,后續會有一個消息處理系統,這個系統會把消息系統中的記錄逐次進行取出並進行處理,完成一個出隊的流程。
三、應用場景
1、數據冗余:比如訂單系統,后續需要嚴格的進行數據轉換和記錄,消息隊列可以把這些數據持久化的存儲在隊列中,然后有訂單,后續處理程序進行獲取,后續處理完之后在把這條記錄進行刪除來保證每一條記錄都能夠處理完成。
2、系統解耦:使用消息系統之后,入隊系統和出隊系統是分開的,也就說其中一個崩潰之后不會影響另外一個的正常運行。
3、異步通信:消息本身使用入隊之后可以直接返回。
4、擴展性:例如訂單隊列,不僅可以處理訂單,還可以給其他業務使用。
5、排序保證:有些場景需要按照產品的順序進行處理比如單進單出從而保證數據按照一定的順序處理,使用消息隊列是可以的。
6、流量削峰:就是秒殺和搶購的時候,會出現明顯的流量劇增,對服務器的壓力非常大。
7、消息通訊:消息隊列一般都內置了高效的通信機制,因此也可以用在純的消息通訊。比如實現點對點消息隊列,或者聊天室等。
四、隊列介質
1、數據庫,例如mysql(可靠性高,易實現,速度慢) 2、緩存, 例如redis(速度快,單個消息報包過大時效率低) 3、消息系統,專業性強,可靠,學習成本高(例如rabbitMq是實現了高級消息隊列協議(AMQP)的開源消息代理軟件(亦稱面向消息的中間件)。)
4、Beanstalkd (一個高性能、輕量級的分布式內存隊列系統)
五、消息處理觸發機制
1、死循環方式讀取:易實現,故障時無法及時恢復;(比較適合做秒殺,比較集中,運維集中維護)
2、定時任務:壓力均分,有處理上限;目前比較流行的處理觸發機制。(唯一的缺點是間隔和數據需要注意,不要等上一個任務沒有完成下一個任務又開始了)
3、守護進程:類似於php-fpm 和php-cg,需要shell基礎
4、采用發布訂閱的方式
六、案例一:應用解耦
應用解耦:在訂單系統出現故障時,不會影響到物流系統
一、說明:電商系統中訂單系統、物流系統、財務系統以及操作日志記錄系統之間的關系。 二、注意點:需要考慮中間數據的容災能力,當故障發生並恢復時,保證業務流程可以恢復。保證每條數據都可以正確地完成處理。
三、傳統模式:訂單系統調用庫存系統的接口。
缺點:1)假如物流系統無法訪問,則訂單無法調用物流接口,從而導致訂單失敗;
2) 訂單系統與庫存系統耦合
四、架構設計(以訂單系統、物流系統為例,mysql為隊列介質)
1、首先訂單系統會接收用戶的訂單,然后進行訂單的處理。
2、然后會把這些訂單信息寫到隊列表中,這個隊列表是溝通這兩個系統的關鍵。
3、由配送系統定時執行的一個程序來讀取隊列表進行處理。
4、配送系統處理之后,會把已處理的記錄進行標記。
架構圖
程序流程圖
發布訂閱方式
七、案例二:流量削峰
說明:一般情況下,做秒殺案例,搶購,瞬間高並發,需要排隊 的案例中 redis是一個很好的選擇。
解釋:小明制作蛋糕的時間比較長,訂單來到后先登記成一個清單,然后逐次按順序制作,訂單量過大時,會暫時掛出『已售完』的牌子。
注意點:對於消峰需求,可以高峰期掛出『暫時無法購買,請稍等』等提示,防止流量對后續業務的沖擊。對於秒殺等搶完即停的需求,需要考慮超發問題,可以添加一個名額計數器,或者在秒殺名額已滿員時,發放一個秒殺完成標記,后續處理程序檢測到完成標記后,再進行后續處理。
redis數據類型中的 list 類型常用命令:
* redis 的list 是一個雙向鏈表,可以從頭部或者尾部追加數據。
1、LPUSH/LPUSHX :將值插入到(/存在的)列表頭部
2、RPUSH/RPUSHX: 將值插入到(/存在的)列表尾部
3、LPOP : 移除並獲取列表的第一個元素
4、RPOP: 移除並獲取列表的最后一個元素
5、LTRIM: 保留指定區間內的元素
6、LLEN: 獲取列表長度
7、LSET: 通過索引設置列表元素的值
8、LINDEX: 通過索引獲取列表中的元素
9、LRANGE: 獲取列表指定范圍內的元素
架構圖
八、案例三:送達保證
場景說明:內容需要逐條嚴格執行,並保證執行成功,執行不成功或者中斷時,可以恢復
解釋:小明制作的蛋糕需要客戶驗貨簽收后,才可以繼續制作下一個蛋糕。
實現:入隊系統將業務需求寫入消息隊列后,即進行下一次業務處理。后續處理程序對隊列內容進行逐條處理,處理完成后發放『完成許可』。消息隊列中的內容,只有取得『完成許可』后,才可以從消息隊列中刪除。
注意點:重點考慮容災相關問題,如業務恢復問題、重復處理問題。
架構圖
九、案例四:排序保證
說明:消息隊列中的內容有嚴格的順序。
案例:搶號排隊等系統
解釋:小明制作蛋糕的順序需要嚴格按下單順序來制作。
實現:入隊系統將內容逐條寫入消息隊列,並按單線排列,按先進先出的順序來提出數據並進行后續處理。
注意點:需要使用單線程,保證只有一條生產線。
架構圖
十、案例五:擴展性
場景:采用發布-訂閱模式時,添加新的訂閱者
案例:注冊用戶后,發送成功短信的模型中,追加一個發送email的功能
實現: 由多個消費者訂閱一個消息的中間層,然后發布者將信息發布到中間層中。 訂閱了這個中間層的消費者均可以收到這個消息,並進行后續處理。在這個結構中。如果想添加一個消息的后續處理組件 ,只需要將這個組件訂閱到中間層即可
注意點:保證業務之間沒有深度耦合,防止擴展時造成干擾。
架構圖
十一、案例六:異步處理
場景說明:用戶注冊后,需要發注冊郵件和注冊短信。傳統的做法有兩種
(1)串行方式:將注冊信息寫入數據庫成功后,發送注冊郵件,再發送注冊短信。以上三個任務全部完成后,返回給客戶端。
(2)並行方式:將注冊信息寫入數據庫成功后,發送注冊郵件的同時,發送注冊短信。以上三個任務完成后,返回給客戶端。與串行的差別是,並行的方式可以提高處理的時間。
串行示意圖
並行示意圖
我們可以發現:假設三個業務節點每個使用50毫秒鍾,不考慮網絡等其他開銷,則串行方式的時間是150毫秒,並行的時間可能是100毫秒。
問題:如以上案例描述,傳統的方式系統的性能(並發量,吞吐量,響應時間)會有瓶頸。如何解決這個問題呢?
解決:引入消息隊列,將不是必須的業務邏輯,異步處理。改造后的架構如下:
引入消息隊列示意圖
解釋說明:按照以上約定,用戶的響應時間相當於是注冊信息寫入數據庫的時間,也就是50毫秒。注冊郵件,發送短信寫入消息隊列后,直接返回,因此寫入消息隊列的速度很快,基本可以忽略,
因此用戶的響應時間可能是50毫秒。因此架構改變后,系統的吞吐量提高到每秒20 QPS。比串行提高了3倍,比並行提高了兩倍。
十二、案例七:消息通訊
場景說明:消息通訊是指,消息隊列一般都內置了高效的通信機制,因此也可以用在純的消息通訊。比如實現點對點消息隊列,或者聊天室等。
點對點通訊:客戶端A和客戶端B使用同一隊列,進行消息通訊。
聊天室通訊:客戶端A,客戶端B,客戶端N訂閱同一主題,進行消息發布和接收。實現類似聊天室效果。
以上實際是消息隊列的兩種消息模式,點對點或發布訂閱模式。
點對點示意圖
聊天室示意圖
以上就是我關於消息隊列整理的一些信息,整篇文章主要是對消息隊列的認識和能用來干什么的描述,看完后也能對消息隊列有個清晰的認知。