1. 程式人生 > 實用技巧 >php訊息佇列

php訊息佇列

一、訊息對列概念

從本質上說訊息對列就是一個佇列結構的中介軟體,也就是說訊息放入這個中介軟體之後就可以直接返回,並不需要系統立即處理,而另外會有一個程式讀取這些資料,並按順序進行逐次處理。

二、結構

由一個業務系統進行入隊,把訊息逐次插入到訊息佇列中,插入成功之後直接返回成功的結果,後續會有一個訊息處理系統,這個系統會把訊息系統中的記錄逐次進行取出並進行處理,完成一個出隊的流程。

三、應用場景

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訂閱同一主題,進行訊息釋出和接收。實現類似聊天室效果。
以上實際是訊息佇列的兩種訊息模式,點對點或釋出訂閱模式。

點對點示意圖

聊天室示意圖

以上就是我關於訊息佇列整理的一些資訊,整篇文章主要是對訊息佇列的認識和能用來幹什麼的描述,看完後也能對訊息佇列有個清晰的認知。