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