MQ的提出
上游發出請求后阻塞等待下游給到反饋,否則整個流程將一直阻塞。
提出mq之后:即有producer mq consumer 三者
MQ的特點
異步解耦
在有了 mq 后,producer 不需要過分關心 consumer 的身份信息,只需要把消息按照指定的協議投遞到對應的 topic 即可
producer 在處理請求時,只需要把消息投遞到 mq 即可認為流程處理結束,相比于同步請求下游,整個流程會更加輕便靈活,擁有更高的吞吐量
流量削峰
因為有 mq 作為緩沖層. 下游 consumer 可以設定好合適的消費限流參數,按照指定的速率進行消費,能夠在很大程度上對 consumer 起到保護作用
Redis自身的缺點(無論是做緩存還是做mq都存在的)
價格昂貴:redis本身是基于內存的,相比傳統的mq組件是基于磁盤的。因此總容量可能有限。
存在數據丟失:即使有RDB/AOF的持久化策略,也難免存在數據丟失的問題,因為這個持久化是異步執行的,只要是異步,都不能說它是百分百的。
Redis自身的優點:
輕量,部署方便,運維成本低。
基于List實現的消息隊列
首先,在使用 list 充當消息隊列時,list 對應的 key 則對應為消息的 topic 名稱.
producer 在投遞消息時,可以使用 lpush 指令
consumer 消費消息時,使用 rpop 指令
但是存在一定的缺陷:
首先,consumer 在消費時,一定是一個類似于 loop thread 的自旋模型,每一輪循環中,通過 rpop 指令嘗試從 list 中讀取消息,如果成功讀取到了消息,則進行相應的邏輯處理.
然而在此處,redis 的 rpop 指令是非阻塞型的,即在 list 沒有數據時,也會即時返回一個結果為 nil 的響應,這樣在自旋模型下,對CPU是一筆不小的損耗。
倘若我們在 rpop 捕捉到 nil 時,立即開啟下一輪循環,則這個輪詢行為可能是沒有意義的,因為 list 中可能仍然不存在數據. 這樣的高頻率自旋,對于 cpu 資源是一種無謂的損耗
倘若我們選擇讓 consumer 休眠一段時間進行循環,這個休眠的時長又具有一定的人為誤判性. 倘若我們把時長設得太短,仍然會存在 cpu 浪費的問題;倘若設得太長,則可能會導致消息處理不及時的問題
在這個過程中,最理想的實現方案是,在 list 中有數據到達時,我們令 consumer 即時獲取到對應的結果;倘若 list 數據為空,則令 consumer 陷入阻塞等待的狀態,直到有數據抵達時程序才被喚醒.?
推出阻塞等待機制:
BRPop key 【阻塞等待的超時時長】
達到此閾值仍未獲取數據時會返回 nil. 如果設置為 0 ,則代表沒有這個超時限制.
基于Pub/Sub
?