一、mq的特性:
異步。上游無法直到下游的執(zhí)行結(jié)果。這是mq無法取代直接調(diào)用最根本的原因。
所以,很多人說mq削峰,但是不是什么都削,必須是,調(diào)用方對調(diào)用結(jié)果的及時性不是很在意才行,比如,登錄,你不可能用mq削峰吧。。解耦。A系統(tǒng)發(fā)送個數(shù)據(jù)到BCD三個系統(tǒng),接口調(diào)用發(fā)送,那如果E系統(tǒng)也要這個數(shù)據(jù),或者C系統(tǒng)現(xiàn)在不要這個數(shù)據(jù),或者A系統(tǒng)再發(fā)第二種數(shù)據(jù),再或者,BCDE這些服務(wù),一旦掛了,這個數(shù)據(jù)就丟失了。
總之,耦合性太重,削峰。對于一些上游對下游的直接結(jié)果不是很關(guān)注的業(yè)務(wù),對CAP的C容錯比較大的業(yè)務(wù)。上游并發(fā)大,下游處理能力小,如果上游直接調(diào)用,下游會直接被打死。那么可以把任務(wù)先放到mq中去,然后異步慢慢處理。
二、mq的使用場景:
mq只是一個消息隊列,或者是一個生產(chǎn)者消費者模式,是進程間通信的。
進程內(nèi)的消費者生產(chǎn)者適合的場景跨服務(wù)就是mq適合的場景。
比如:
2.1. 時間上有依賴的任務(wù)執(zhí)行。
比如,我曾經(jīng)有一個定時服務(wù),同步,小區(qū),人員,房屋等等信息,之后還要對這些信息進行統(tǒng)計,計算處理。各個步驟有時間上的依賴。
1.1 一種很常見的方式:每個定時任務(wù)開啟定時器,然后同步的時間點預(yù)定在上一個任務(wù)之后,然后在預(yù)留相當(dāng)長的時間防止任務(wù)執(zhí)行超時了。
優(yōu)點:簡單,趕工期先這樣應(yīng)付著。。。
缺點就是:
1、一旦上一個任務(wù)超時了,下一個任務(wù)的數(shù)據(jù)就錯了。
2、需要預(yù)留時間,時間緊的話沒有那么多時間浪費,比如就晚上有時間給你同步數(shù)據(jù),可晚上就那么幾個鐘頭。
3、一旦以后數(shù)據(jù)量多了,同步時間延長了,則需要修改同步時間。
1.2 另一種方式:一個任務(wù)執(zhí)行完了之后,直接調(diào)下一個任務(wù)的方法,執(zhí)行下一個任務(wù)。
這種方式,能夠解決第一種方式的3個缺點。
缺點:1、耦合性很高,一個任務(wù)之后,要回調(diào)很多個下個任務(wù)的方法,不是很優(yōu)雅。而且,如果以后再新增一個回調(diào)任務(wù),則又要修改上個任務(wù)的回調(diào)方法。
2、假設(shè)這個任務(wù)是在多個服務(wù)的,如果遠(yuǎn)程調(diào)用的話,很可能會因為網(wǎng)絡(luò)原因等調(diào)用失敗,除非引入了rpc有重試機制。
1.3 再一種方式:寫一個進程內(nèi)的消費者生產(chǎn)者模式。然后上游任務(wù)執(zhí)行完,直接往進程內(nèi)隊列里put,然后,下游任務(wù)直接訂閱這個隊列,然后就會直接得到處理了。
優(yōu)點:耦合性不高。
缺點:需要花時間去寫一個進程內(nèi)消費者生產(chǎn)者模式。比如這樣的東西:寫一個消費者生產(chǎn)者模式
2.2. 可以異步,耦合性高,執(zhí)行時間長的場景
比如,添加一個商品,就要生產(chǎn)一個商品索引,還要生成一個商品的詳情頁,等等。
1、如果直接rpc調(diào)用,那么,直接調(diào)用,則執(zhí)行時間太長。
2、如果異步線程調(diào)用,耦合性太大,一旦增加一個獲取通知的回調(diào),又要修改生成商品服務(wù)。
3、而且直接調(diào)用,萬一下游服務(wù)掛了,消息就丟失了。
2.3. 流量削峰
上游qps大,直接調(diào)用,會把下游打死。
比如上游只有簡單的下單邏輯,下游有計算檢查,扣庫存等等。自然上游會比下游qps大。
如果可以異步,對執(zhí)行失敗可以容忍:可以把任務(wù)往mq中放,mq如果用主動推的方式,可以設(shè)置消費者線程數(shù),慢慢處理。如果用拉的方式,可以自己慢慢拉取。
否則,必須要同步調(diào)用的場景:只能服務(wù)限流的方式,拋棄一部分請求。
對于削峰
總結(jié):異步,解耦,削峰。
三、線程池和mq的區(qū)別
1、線程池是進程內(nèi)隊列,也是隊列。
2、如果消息積壓多了,用線程池的方式,會積壓大量任務(wù),消耗大量內(nèi)存。
3、消息丟失,重試機制,持久化等,應(yīng)答機制,如果消費者系統(tǒng)沒有運行,則線程池調(diào)用的方式,直接導(dǎo)致,消息丟失了。
4、mq的解耦機制是線程池沒有的。
四、mq的缺點
1、異步,這是最大的缺點。
2、引入組件,增加復(fù)雜度。
五、mq的高可用
activemq可以做主從。
rabbitmq可以做鏡像集群。
rocketmq和kafka更不用說,比如rocketmq的name server集群、broker集群。
rabbitmq的普通的集群:每個節(jié)點只有元數(shù)據(jù),獲取數(shù)據(jù)的時候,去真正節(jié)點上去拉,所以做不到高可用,只是負(fù)載均衡了一下。鏡像集群:則是每個節(jié)點有都有這個數(shù)據(jù)。
六、mq 如何保證冪等性
不管是發(fā)送、消費,如果網(wǎng)絡(luò)原因,還沒來得及ack應(yīng)答,導(dǎo)致重復(fù)推送,就會導(dǎo)致重復(fù)消息的問題。
要根據(jù)業(yè)務(wù)來。
有寫數(shù)據(jù)不需要保證冪等性,比如set或update操作。
比如數(shù)據(jù)庫的唯一鍵約束,比如訂單id,做一個唯一索引。
如果實在不好保證,只能存一個唯一id,然后處理前,查一下沒有沒處理過這個id。
七、如何保證消息的可靠性傳輸
比如activemq,消費者設(shè)置應(yīng)答模式為同步模式,這樣,在服務(wù)端沒有給生產(chǎn)者應(yīng)答之前,生產(chǎn)者一直堵塞。生產(chǎn)者設(shè)置消息持久化到硬盤,消費者設(shè)置手動應(yīng)答模式,當(dāng)真正消費了消息之后,才應(yīng)答。
如果是rabbitmq的話:為了保證消息發(fā)布到rabbitmq成功以否,rabbitmq提供了回調(diào)確認(rèn)機制,保證數(shù)據(jù)不丟失,當(dāng)然事務(wù)也可以做到,但是性能不好,不常用,也有持久化和應(yīng)答。
rocketmq也有同步寫主從以及持久化和應(yīng)答機制。
kafka不是很熟:kafka,kafka也可以通過配置,參數(shù),必須寫入多少臺機器,才算寫入成功。
八、如何保證消息的順序性
一個queue對應(yīng)一個消費者,就絕對是有序的,如果對應(yīng)多個消費者自然就無序。
九、消息延遲、消息積壓怎么處理?
1、修好consumer,然后可以臨時增加consumer增加分擔(dān)消費能力,比如rabbitmq,rocketmq,則直接新增消費者就可以。
2、如果不好這么做,可以新建一個臨時queue,然后把消息轉(zhuǎn)發(fā)過來,然后新的queue,用多個消費者消費。
3、如果對于rabbitmq,這種設(shè)置過期時間的,造成消息積壓導(dǎo)致的消息丟失,則只能想辦法找出丟失的數(shù)據(jù),然后,再推送到mq中去?!?/p>