15 解決訂單系統(tǒng)諸多問題的核心技術:消息中間件到底是什么?

解決訂單系統(tǒng)諸多問題的核心技術:消息中間件到底是什么?
1、解決訂單系統(tǒng)諸多問題的核心技術:消息中間件
今天一上班,小猛非常期待的跑到了明哥的工位旁:明哥,現(xiàn)在訂單系統(tǒng)的所有問題我們都搞清楚了,是不是可以開始研究對應的技術方案了啊?
明哥說:當然了,今天開始我們要慢慢調研和落地一些技術方案,去逐步解決訂單系統(tǒng)面臨的各種問題了。
首先第一步,我先給你介紹一個用來解決我們訂單系統(tǒng)問題的核心技術,消息中間件。
明哥問:你對消息中間件有了解過嗎?
小猛說:這個還真沒有,因為平時在學校里都做一些CRUD的項目,像什么酒店管理系統(tǒng)啊,圖書館管理系統(tǒng)之類的。
明哥笑了笑:沒關系,我先簡單給你介紹一下消息中間件的概念,你肯定一聽就懂,并不難。
2、了解消息中間件之前,先認識一下什么是“同步”
首先,我們想一下,通常而言,在公司里可能會存在多個業(yè)務系統(tǒng),這些業(yè)務系統(tǒng)之間的通信都是進行接口調用的。明哥說著在紙上畫出了一幅簡易的示意圖。
? ? ? ? ? ?

?? ? ? ? ? ?
現(xiàn)在假設系統(tǒng)A收到了一個請求,可能是用戶通過瀏覽器或者APP發(fā)起的,這個時候系統(tǒng)A收到請求之后就會立馬去調用系統(tǒng)B,然后系統(tǒng)B返回結果給系統(tǒng)A之后,系統(tǒng)A才能返回結果給用戶,是不是這樣?
明哥接著在圖里補充了一些東西。
? ? ? ? ? ?

?? ? ? ? ? ?
小猛點點頭,確實是的,因為通過一個復雜的系統(tǒng)去實現(xiàn)各種復雜的功能,滿足用戶的需求,簡化來說,大致確實如此。
明哥接著說,那么在這種情況下,用戶發(fā)起一個請求,系統(tǒng)A收到請求,接著系統(tǒng)A必須立馬去調用系統(tǒng)B,直到系統(tǒng)B返回了,系統(tǒng)A才能返回結果給用戶,這種模式其實就是所謂的“同步調用”。
這個同步的意思,就是各個系統(tǒng)的聯(lián)動都是同步依次進行的,一個系統(tǒng)先動,然后立馬帶動另外一個系統(tǒng)一起動,最后大家依次干完了以后,再返回結果。
這就是同步調用最通俗的解釋了,不是那種學術型的解釋。
3、再來看看依托消息中間件如何實現(xiàn)異步?
明哥接著說,現(xiàn)在假設我們在系統(tǒng)A和系統(tǒng)B之間加入了一個東西,這個東西就叫做“消息中間件”,但是這五個字念著太麻煩了,干脆就簡單點,叫MQ就行了,英文全稱就是“Message Queue”,也就是消息隊列。
然后明哥在圖里加入了消息中間件。? ? ? ? ?

? ? ? ?
加入了這個消息中間件以后,系統(tǒng)A和系統(tǒng)B之間是怎么通信的呢?
很簡單,之所以叫這個東西 是“消息中間件”,說明他里面一個核心的概念就是“消息”。所以系統(tǒng)A一般會發(fā)送一個消息給MQ。
接著系統(tǒng)A就認為自己的工作干完了,然后就直接返回結果給用戶了,明哥在圖里加了點東西,而且還標號了各個步驟執(zhí)行的順序。? ? ? ??

? ? ? ?
此時小猛很疑惑,那系統(tǒng)B什么時候執(zhí)行自己的任務呢?
明哥緊接著說:別著急,馬上就到系統(tǒng)B了。你先思考一下,這個時候系統(tǒng)A跟系統(tǒng)B是不是看著就沒什么關系了?因為系統(tǒng)A要做的事情只是接收請求,發(fā)送消息到MQ,然后就返回結果給用戶,系統(tǒng)B他就不管了。
然后系統(tǒng)B根據(jù)自己的情況,可能會在系統(tǒng)A投遞消息到MQ之后的1秒內,也可能是1分鐘之后,也可能是1小時之后,多長時間都有可能,反正不管是多長時間后,系統(tǒng)B肯定會從MQ里獲取到一條屬于自己的消息。
然后獲取到消息之后,根據(jù)消息的指示再完成自己的工作。
明哥說著繼續(xù)在圖里補充了一些東西。
? ? ? ? ? ?

? ? ? ?
在這種情況下,系統(tǒng)A和系統(tǒng)B有沒有實現(xiàn)通信?
有,因為系統(tǒng)A發(fā)了一個消息給MQ,系統(tǒng)B從MQ里獲取了一個消息,干了自己該干的工作。
那么系統(tǒng)A跟系統(tǒng)B之間是不是同步調用?
不是,因為系統(tǒng)A僅僅是發(fā)個消息到MQ,至于系統(tǒng)B什么時候獲取消息,有沒有獲取消息,他是不管的。
所以這種情況下,我們說系統(tǒng)A和系統(tǒng)B是異步調用。
所謂異步調用,意思就是系統(tǒng)A先干了自己的工作,然后想辦法去通知了系統(tǒng)B。
但是系統(tǒng)B什么時候收到通知?什么時候去干自己的工作?這個系統(tǒng)A不管,不想管,也沒法管,跟他就沒關系了。
但是最終在正常下,系統(tǒng)B總會獲取到這個通知,然后干自己該干的事兒。
這種情況下,并不是系統(tǒng)A動了,系統(tǒng)B就立馬同步動,他們不是同步的。而是系統(tǒng)A動了,但是系統(tǒng)B可能過一會兒才動,他們的步調是不一樣的,所以是異步的。
這就是所謂的“異步調用”最通俗的解釋了,完全沒任何的學術痕跡。
4、消息中間件是用來干什么的?
聽到這里,小猛又覺得自己面前打開了一扇新的大門,以前自己就知道做CRUD之類的事兒,最多是用Spring Cloud、Dubbo之類的技術搭建過幾個簡單的Demo,讓不同的系統(tǒng)實現(xiàn)同步調用。
但是自己從沒想過系統(tǒng)之間還可以進行異步調用!
所以聽到這里,小猛不禁脫口而出:所以消息中間件,其實就是一種系統(tǒng),他自己也是獨立部署的,然后讓我們的兩個系統(tǒng)之間通過發(fā)消息和收消息,來進行異步的調用,而不是僅僅局限于同步調用。
明哥大贊:精辟的總結!
5、那么消息中間件到底有什么用呢?
小猛接著提出了一個疑問:那讓兩個系統(tǒng)之間不是同步調用,而是異步調用,有什么用呢?換句話說,我們可以用消息中間件來干什么?
明哥說:這個用處可多了去了,主要的作用有這么幾個,包括異步化提升性能,降低系統(tǒng)耦合,流量削峰,等等。
比如,現(xiàn)在假設系統(tǒng)A要調用系統(tǒng)B干一個事兒,然后系統(tǒng)A先執(zhí)行一些操作,需要耗費20ms,接著系統(tǒng)B執(zhí)行一些操作要耗費200ms,總共就要耗費220ms。明哥說著重新畫了一個圖做了一個示意。? ? ? ? ?

這個時候等系統(tǒng)A和系統(tǒng)B都干完活兒,才能返回結果給用戶,要等待220ms。
那么如果在系統(tǒng)A和系統(tǒng)B之間加一個MQ呢?
系統(tǒng)A干完自己的事情,就20ms,然后發(fā)送一個消息到MQ,就5ms,然后就直接返回結果給用戶了。
也就是說,用戶僅僅等待25ms就收到了結果。
然后系統(tǒng)B從MQ里獲取消息,接著花費200ms去執(zhí)行,但是這個200ms就跟用戶沒關系了,用戶早就收到結果了,他也不關心你花200ms還是2s去干自己的事。
明哥說著在這個圖里補充了一些東西。? ? ? ? ??

? ? ? ?
這樣的話,對用戶來說,是不是從原來等待220ms返回結果,變成現(xiàn)在只要25ms就可以返回結果了?
小猛聽著都愣了,還有這套玩法?真是太棒了,消息中間件居然可以用來優(yōu)化系統(tǒng)性能。
明哥接著說,現(xiàn)在我們說另外一個場景,還是上面那個圖來舉例。如果系統(tǒng)A同步調用系統(tǒng)B,那么按照我們說過的,是不是這屬于系統(tǒng)間的耦合?因為系統(tǒng)A和系統(tǒng)B是耦合在一起的,互相之間會有影響。
那么如果系統(tǒng)B要是突然出現(xiàn)故障了,是不是會導致系統(tǒng)A調用系統(tǒng)B感知到這個故障?因為系統(tǒng)A調用系統(tǒng)B肯定是返回異常的,此時系統(tǒng)A是不是也得返回異常給用戶?而且系統(tǒng)A是不是還要去處理這個異常?
明哥說著畫了一個示意圖:? ? ? ??

? ? ? ?
這一切都是因為系統(tǒng)A和系統(tǒng)B通過同步調用的模式耦合在了一起,所以一旦系統(tǒng)B出現(xiàn)故障,很可能會影響系統(tǒng)A也有故障
而且系統(tǒng)A還得去關心系統(tǒng)B的故障,去處理對應的異常,這是很麻煩的。
那么假設我們在系統(tǒng)A和系統(tǒng)B之間加入一個消息中間件,在這種情況下,系統(tǒng)A對系統(tǒng)B的調用僅僅是發(fā)送一個消息到MQ,然后就直接返回給用戶了,后面對系統(tǒng)B就不管了。
此時系統(tǒng)B如果出現(xiàn)了故障,對系統(tǒng)A根本沒影響,系統(tǒng)A也感覺不到。
明哥說著畫了一個圖出來。
? ? ? ? ? ?

系統(tǒng)B故障,就成了他自己的事了,他要自己等故障恢復了,繼續(xù)去完成他要干的活兒,此時就對系統(tǒng)A沒任何影響了。
為什么會有這樣的效果呢?因為通過引入MQ,兩個系統(tǒng)實現(xiàn)了異步化調用,也就實現(xiàn)了解耦,系統(tǒng)A并沒有跟系統(tǒng)B耦合,所以互相之間并沒有任何影響。
小猛聽到這里,豁然開朗,消息中間件還能讓兩個系統(tǒng)解耦,讓他們倆互相之間沒有任何影響,太有意思了!
接著明哥說:消息中間件還有最后一個特別牛的功能,叫做流量削峰。
假設系統(tǒng)A是不操作數(shù)據(jù)庫的,因此只要多部署幾臺機器,就可以抗下每秒1萬的請求,比如部署個20臺機器,就可以輕松抗下每秒上萬請求。
然后系統(tǒng)B是要操作一臺數(shù)據(jù)庫服務器的,那臺數(shù)據(jù)庫的上限是接收每秒6000請求,那么系統(tǒng)B無論部署多少臺機器都沒用,因為他依賴的數(shù)據(jù)庫最多只能接收每秒6000請求。
明哥說著畫出了一幅圖。
? ? ? ? ? ?

? ? ? ? ? ? ?
現(xiàn)在假設大量用戶同時發(fā)起訪問,系統(tǒng)A就是收到了1萬QPS怎么辦?
這時候,系統(tǒng)A會瞬間把1萬QPS轉發(fā)給系統(tǒng)B,假設你系統(tǒng)B也部署20臺機器,系統(tǒng)B自己可以抗住1萬QPS,那么數(shù)據(jù)庫呢?
數(shù)據(jù)庫是抗不下來1萬QPS的,此時系統(tǒng)B如果對數(shù)據(jù)庫發(fā)起1萬QPS的請求,一定會瞬間壓垮數(shù)據(jù)庫的。
所以這時如果引入MQ,就可以解決這個問題了。MQ這個技術抗高并發(fā)的能力遠遠高于數(shù)據(jù)庫,同樣的機器配置下,如果數(shù)據(jù)庫可以抗每秒6000請求,MQ至少可以抗每秒幾萬請求。
為什么呢?因為數(shù)據(jù)庫復雜啊,他要能夠支持你執(zhí)行復雜的SQL語句,支持事務等復雜的機制,支持你對數(shù)據(jù)進行增刪改查,聽著簡單,其實是很復雜的!所以一般數(shù)據(jù)庫單服務器也就支撐每秒幾千的請求。
但是MQ就不一樣了,他的核心功能就是讓你發(fā)消息給他,再讓別人從他這里獲取消息,這個就簡單的多了,所以同等機器配置下,MQ一般都能抗幾萬并發(fā)請求。
所以只要你引入一個MQ,那么就可以讓系統(tǒng)A把每秒1萬請求都作為消息直接發(fā)送到MQ里,MQ可以輕松抗下來這每秒1萬請求
明哥說著畫了一個圖。? ? ? ? ?

? ? ? ? ? ? ?
接著,系統(tǒng)b只要慢慢的從MQ里獲取消息然后執(zhí)行數(shù)據(jù)庫讀寫操作即可,這個獲取消息的速度是系統(tǒng)B自己可以控制的,所以系統(tǒng)B完全可以用一個比較低的速率獲取消息然后寫入數(shù)據(jù)庫,保證對數(shù)據(jù)庫的QPS不要超過他的極限值6000。
明哥說著對圖補充了一下。
? ? ? ?

? ? ? ? ? ? ?
這個時候因為系統(tǒng)A發(fā)送消息到MQ很快,系統(tǒng)B從MQ消費消息很慢,所以MQ里自然會積壓一些消息
不過不要緊,MQ一般都是基于磁盤來存儲消息的,所以適當積壓一些消息是可以的。
當系統(tǒng)A的高峰過去,每秒可能就恢復到1000 QPS了,此時系統(tǒng)b還是以每秒6000QPS的速度獲取消息寫入數(shù)據(jù)庫,那么自然MQ里積壓的消息就會慢慢被消化掉了。
所以這就是MQ進行流量削峰的效果,系統(tǒng)A發(fā)送過來的每秒1萬請求是一個流量洪峰,然后MQ直接給扛下來了,都存儲自己本地磁盤,這個過程就是流量削峰的過程,瞬間把一個洪峰給削下來了,讓系統(tǒng)B后續(xù)慢慢獲取消息來處理。
小猛聽著都呆了,MQ還能這么玩兒?這簡直是一個神功利器??!看起來很棘手的系統(tǒng)性能差、耦合性高、流量洪峰等問題,只要引入MQ居然就可以搞定了,真是太好了!
明哥說:好了,今天就先講到這里,你回去一定要好好的吸收MQ的這些知識,他到底是什么,用來干什么的,有哪些功能。
End
專欄版權歸公眾號儒猿技術窩所有
未經許可不得傳播,如有侵權將追究法律責任