前言
消息隊列在互聯(lián)網(wǎng)技術(shù)存儲方面使用如此廣泛颤霎,幾乎所有的后端技術(shù)面試官都要在消息隊列的使用和原理方面對小伙伴們進行360°的刁難。
作為一個在互聯(lián)網(wǎng)公司面一次拿一次Offer的面霸涂滴,打敗了無數(shù)競爭對手友酱,每次都只能看到無數(shù)落寞的身影失望的離開,略感愧疚(請允許我使用一下夸張的修辭手法)柔纵。
于是在一個寂寞難耐的夜晚缔杉,暖男我痛定思痛,決定開始寫《吊打面試官》系列搁料,希望能幫助各位讀者以后面試勢如破竹或详,對面試官進行360°的反擊,吊打問你的面試官郭计,讓一同面試的同僚瞠目結(jié)舌霸琴,瘋狂收割大廠Offer!
面試開始
一個風(fēng)度翩翩昭伸,穿著格子襯衣的中年男子梧乘,拿著一個滿是劃痕的mac向你走來,看著錚亮的頭,心想著肯定是尼瑪頂級架構(gòu)師吧选调!但是我們看過暖男敖丙的系列夹供,腹有詩書氣自華,虛都不虛仁堪。
面試官你好:我們公司本身的業(yè)務(wù)體量很小哮洽,所以直接單機一把梭啥都能搞定了,但是后面業(yè)務(wù)體量不斷擴大枝笨,采用微服務(wù)的設(shè)計思想袁铐,分布式的部署方式,所以拆分了很多的服務(wù)横浑,隨著體量的增加以及業(yè)務(wù)場景越來越復(fù)雜了剔桨,很多場景單機的技術(shù)棧和中間件以及不夠用了,而且對系統(tǒng)的友好性也下降了徙融,最后做了很多技術(shù)選型的工作洒缀,我們決定引入消息隊列中間件。
哦欺冀?你說到業(yè)務(wù)場景越來越復(fù)雜树绩,你那說一下你都在什么場景用到了消息隊列?
嗯隐轩,我從三個方面去說一下我使用的場景吧饺饭。
Tip:這三個場景也是消息隊列的經(jīng)典場景,大家基本上要爛熟于心那種职车,就是一說到消息隊列你腦子就要想到異步瘫俊、削峰、解耦悴灵,條件反射那種扛芽。
異步:
我們之前的場景里面有很多步驟都是在一個流程里面需要做完的,就比如說我的下單系統(tǒng)吧积瞒,本來我們業(yè)務(wù)簡單川尖,下單了付了錢就好了,流程就走完了茫孔。
但是后面來了個產(chǎn)品經(jīng)理叮喳,搞了個優(yōu)惠券系統(tǒng),OK問題不大缰贝,流程里面多100ms去扣減優(yōu)惠券嘲更。
后來產(chǎn)品經(jīng)理靈光一閃說我們可以搞個積分系統(tǒng)啊,也行吧揩瞪,流程里面多了200ms去增減積分。
再后來后來隔壁的產(chǎn)品老王說:下單成功后我們要給用戶發(fā)短信篓冲,也將就吧李破,100ms去發(fā)個短信宠哄。
再后來。嗤攻。毛嫉。
反正就流程有點像這樣 ↓
你們可以看到這才加了三個,我可以斬釘截鐵的告訴你真正的下單流程涉及的系統(tǒng)絕對在10個以上(主流電商)妇菱,越大的越多承粤。
這個鏈路這樣下去,時間長得一批闯团,用戶發(fā)現(xiàn)我買個東西你特么要花幾十秒辛臊,垃圾電商我不在你這里買了,不過要是都像并夕夕這么便宜房交,真香彻舰!
但是我們公司沒有夕夕的那個經(jīng)濟實力啊,那只能優(yōu)化系統(tǒng)了候味。
Tip:我之前在的電商老東家要求所有接口的Rt(ResponseTime響應(yīng)時間)在200ms內(nèi)刃唤,超出的全部優(yōu)化,我現(xiàn)在所負責(zé)的系統(tǒng)QPS也是9W+就是抖動一下網(wǎng)絡(luò)集群都可能炸鍋那種白群,RT基本上都要求在50ms以內(nèi)尚胞。
大家感受一下這個QPS。
嗯不錯帜慢,鏈路長了就慢了笼裳,那你怎么解決的?
那鏈路長了就慢了崖堤,但是我們發(fā)現(xiàn)上面的流程其實可以同時做的呀侍咱,你支付成功后,我去校驗優(yōu)惠券的同時我可以去增減積分啊密幔,還可以同時發(fā)個短信啊楔脯。
那正常的流程我們是沒辦法實現(xiàn)的呀,怎么辦胯甩,異步昧廷。
你對比一下是不是發(fā)現(xiàn),這樣子最多只用100毫秒用戶知道下單成功了偎箫,至于短信你遲幾秒發(fā)給他他根本不在意是吧木柬。
小伙子我打斷你一下,你說了異步淹办,那我用線程眉枕,線程池去做不是一樣的么?
誒呀,面試官你不要急嘛速挑,我后面還會說到的谤牡,騷等。
解耦:
既然面試官這么問了姥宝,我就說一下為啥我們不能用線程去做翅萤,因為用線程去做,你是不是要寫代碼腊满?
你一個訂單流程套么,你扣積分,扣優(yōu)惠券碳蛋,發(fā)短信胚泌,扣庫存。疮蹦。诸迟。等等這么多業(yè)務(wù)要調(diào)用這么多的接口,每次加一個你要調(diào)用一個接口然后還要重新發(fā)布系統(tǒng)愕乎,寫一次兩次還好阵苇,寫多了你就說:老子不干了!
而且真的全部都寫在一起的話感论,不單單是耦合這一個問題绅项,你出問題排查也麻煩,流程里面隨便一個地方出問題搞不好會影響到其他的點比肄,小伙伴說我每個流程都try catch不就行了快耿,相信我別這么做,這樣的代碼就像個定時炸彈??芳绩,你不知道什么時候爆炸掀亥,平時不炸偏偏在你做活動的時候炸,你就領(lǐng)個P0故障收拾書包提前回家過年吧妥色。
Tip:P0—PN 是互聯(lián)網(wǎng)大廠經(jīng)常用來判定事故等級的機制搪花,P0是最高等級了。
但是你用了消息隊列嘹害,耦合這個問題就迎刃而解了呀撮竿。
且聽我娓娓道來:
你下單了,你就把你支付成功的消息告訴別的系統(tǒng)笔呀,他們收到了去處理就好了幢踏,你只用走完自己的流程,把自己的消息發(fā)出去许师,那后面要接入什么系統(tǒng)簡單房蝉,直接訂閱你發(fā)送的支付成功消息僚匆,你支付成功了我監(jiān)聽就好了。
那你的流程走完了搭幻,你不用管別人是否成功么白热?比如你下單了積分沒加,優(yōu)惠券沒扣怎么辦粗卜?
問題是個好問題,但是沒必要考慮纳击,業(yè)務(wù)系統(tǒng)本身就是自己的開發(fā)人員維護的续扔,你積分扣失敗關(guān)我下單的什么事情?你管好自己下單系統(tǒng)的就好了焕数。
Tip:話是這么說纱昧,但是這其實是用了消息隊列的一個缺點,涉及到分布式事務(wù)的知識點堡赔,我下面會提到识脆。
削峰:
就拿我上一期寫的秒殺來說(暗示新同學(xué)看我上一期),你平時流量很低善已,但是你要做秒殺活動00 :00的時候流量瘋狂懟進來灼捂,你的服務(wù)器,Redis换团,MySQL各自的承受能力都不一樣悉稠,你直接全部流量照單全收肯定有問題啊,直接就打掛了艘包。
那怎么辦的猛?
簡單,把請求放到隊列里面想虎,然后至于每秒消費多少請求卦尊,就看自己的服務(wù)器處理能力,你能處理5000QPS你就消費這么多舌厨,可能會比正常的慢一點岂却,但是不至于打掛服務(wù)器,等流量高峰下去了邓线,你的服務(wù)也就沒壓力了淌友。
你看阿里雙十一12:00的時候這么多流量瞬間涌進去,他有時候是不是會慢一點骇陈,但是人家沒掛啊震庭,或者降級給你個友好的提示頁面,等高峰過去了又是一條好漢了你雌。
為了這個圖特意打高一臺服務(wù)的流量
聽你說了辣么多器联,怎么都是好處二汛,那我問你使用了消息隊列有啥問題么?
誒拨拓,看過前面我寫的文章的人才都知道肴颊,我經(jīng)常說的就是,技術(shù)是把雙刃劍渣磷!
沒錯面試官婿着,我使用他是因為他帶給我們很多好處,但是使用之后問題也是接踵而至醋界。
同樣的暖男我呀竟宋,也從三個點介紹他主要的缺點:
系統(tǒng)復(fù)雜性
本來蠻簡單的一個系統(tǒng),我代碼隨便寫都沒事形纺,現(xiàn)在你憑空接入一個中間件在那丘侠,我是不是要考慮去維護他,而且使用的過程中是不是要考慮各種問題逐样,比如消息重復(fù)消費蜗字、消息丟失、消息的順序消費等等脂新,反正用了之后就是賊煩挪捕。
我插一句嘴,上面的問題(重復(fù)消費戏羽、消息丟失担神、順序消費)你能分別介紹一下,并且說一下分別是怎么解決的么始花?
這三個問題我想了下妄讯,統(tǒng)統(tǒng)都是MQ的重點問題,單獨拿一個出來就是一篇文章了酷宵,篇幅實在太長了亥贸,我會在下一章挨個介紹一遍的。
數(shù)據(jù)一致性
這個其實是分布式服務(wù)本身就存在的一個問題浇垦,不僅僅是消息隊列的問題炕置,但是放在這里說是因為用了消息隊列這個問題會暴露得比較嚴重一點。
就像我開頭說的男韧,你下單的服務(wù)自己保證自己的邏輯成功處理了朴摊,你成功發(fā)了消息,但是優(yōu)惠券系統(tǒng)此虑,積分系統(tǒng)等等這么多系統(tǒng)甚纲,他們成功還是失敗你就不管了?
我說了保證自己的業(yè)務(wù)數(shù)據(jù)對的就好了朦前,其實還是比較不負責(zé)任的一種說法介杆,這樣就像個渣男鹃操,沒有格局,這樣呀你的路會越走越窄的春哨。
所有的服務(wù)都成功才能算這一次下單是成功的荆隘,那怎么才能保證數(shù)據(jù)一致性呢?
分布式事務(wù):把下單赴背,優(yōu)惠券椰拒,積分。凰荚。耸三。都放在一個事務(wù)里面一樣,要成功一起成功浇揩,要失敗一起失敗。
Tip:分布式事務(wù)在互聯(lián)網(wǎng)公司里面實在常見憨颠,我也不在這里大篇幅介紹了胳徽,后面都會專門說的。
可用性
你搞個系統(tǒng)本身沒啥問題爽彤,你現(xiàn)在突然接入一個中間件在那放著养盗,萬一掛了怎么辦?我下個單MQ掛了适篙,優(yōu)惠券不扣了往核,積分不減了,這不是殺一個程序員能搞定的吧嚷节,感覺得殺一片聂儒。
至于怎么保證高可用,還是那句話也不在這里展開討論了硫痰,我后面一樣會寫衩婚,像寫Redis那樣寫出來的。
看不出來啊效斑,你有點東西呀非春,那我問一下你,你們是怎么做技術(shù)選型的缓屠?
目前在市面上比較主流的消息隊列中間件主要有奇昙,Kafka、ActiveMQ敌完、RabbitMQ储耐、RocketMQ 等這幾種。
不過我想說的是蠢挡,ActiveMQ和RabbitMQ這兩著因為吞吐量還有GitHub的社區(qū)活躍度的原因弧岳,在各大互聯(lián)網(wǎng)公司都已經(jīng)基本上絕跡了凳忙,業(yè)務(wù)體量一般的公司會是有在用的,但是越來越多的公司更青睞RocketMQ這樣的消息中間件了禽炬。
Kafka和RocketMQ一直在各自擅長的領(lǐng)域發(fā)光發(fā)亮涧卵,不過寫這篇文章的時候我問了螞蟻金服,字節(jié)跳動和美團的朋友腹尖,好像大家用的都有點不一樣柳恐,應(yīng)該都是各自的中間件,可能做過修改热幔,也可能是自研的乐设,大多沒有開源。
就像我們公司就是是基于Kafka和RocketMQ兩者的優(yōu)點自研的消息隊列中間件绎巨,吞吐量缝其、可靠性、時效性等都很可觀鸳劳。
我們回歸正題编兄,我這里用網(wǎng)上找的對比圖讓大家看看差距到底在哪里:
大家其實一下子就能看到差距了,就拿吞吐量來說和媳,早期比較活躍的ActiveMQ 和RabbitMQ基本上不是后兩者的對手了格遭,在現(xiàn)在這樣大數(shù)據(jù)的年代吞吐量是真的很重要。
比如現(xiàn)在突然爆發(fā)了一個超級熱點新聞留瞳,你的APP注冊用戶高達億數(shù)拒迅,你要想辦法第一時間把突發(fā)全部推送到每個人手上,你沒有大吞吐量的消息隊列中間件用啥去推她倘?
再說這些用戶大量涌進來看了你的新聞產(chǎn)生了一系列的附帶流量璧微,你怎么應(yīng)對這些數(shù)據(jù),很多場景離開消息隊列基本上難以為繼硬梁。
就部署方式而言前兩者也是大不如后面兩個天然分布式架構(gòu)的哥哥往毡,都是高可用的分布式架構(gòu),而且數(shù)據(jù)多個副本的數(shù)據(jù)也能做到0丟失靶溜。
我們再聊一下RabbitMQ這個中間件其實還行开瞭,但是這玩意開發(fā)語言居然是erlang,我敢說絕大部分工程師肯定不會為了一個中間件去刻意學(xué)習(xí)一門語言的罩息,開發(fā)維護成本你想都想不到嗤详,出個問題查都查半天。
至于RocketMQ(阿里開源的)瓷炮,git活躍度還可以葱色。基本上你push了自己的bug確認了有問題都有阿里大佬跟你試試解答并修復(fù)的娘香,我個人推薦的也是這個苍狰,他的架構(gòu)設(shè)計部分跟同樣是阿里開源的一個RPC框架是真的很像(Dubbo)可能是因為師出同門的原因吧办龄。
Kafka我放到最后說,你們也應(yīng)該知道了淋昭,壓軸的這是個大哥俐填,大數(shù)據(jù)領(lǐng)域,公司的日志采集翔忽,實時計算等場景英融,都離不開他的身影,他基本上算得上是世界范圍級別的消息隊列標(biāo)桿了歇式。
以上這些都只是一些我自己的個人意見驶悟,真正的選型還是要去深入研究的,不然那你公司一天UV就1000你告訴我你要去用Kafka我只能說你吃飽撐的材失。
記住痕鳍,沒有最好的技術(shù),只有最適合的技術(shù)龙巨,不要為了用而用额获。
面試結(jié)束
嗯,小伙子不錯不錯恭应,分析得很到位,那你記得下期來說一下消息隊列的高可用耘眨,重復(fù)消費昼榛、消息丟失、消息順序剔难、分布式事務(wù)等問題胆屿?
嗯嗯好的面試官,不過不確定能不能一口氣說完偶宫,畢竟敖丙還沒開始寫非迹,而且讀者還有可能白嫖,動力不一定夠纯趋。
嗯嗯這倒是個問題憎兽,不過啊在看的都是人才肯定會給你點贊??的!
我也這么認為吵冒。
總結(jié)
消息隊列的基礎(chǔ)知識我就先介紹這么多纯命,消息隊列在面試里面基本上也是跟我前面寫的Redis一樣必問的。
面試的思路還是一樣痹栖,要知其然亿汞,也要知其所以然,就是要知道為啥用揪阿,用了有啥好處疗我,有啥坑咆畏。
面試官不喜歡只知道用的,你只會用那哪天線上出問題怎么辦吴裤?你難道在旁邊拜佛旧找?
后面我會寫到很多實際開發(fā)過程中比較復(fù)雜的情況,在面試里面基本上是必考題嚼摩,我希望你們拿起小本本記下來钦讳,不要去背,要去理解枕面,我在人才交流群里面有仔問我愿卒,我怎么背住這些知識點的?
你確定沒逗我潮秘?你全靠背琼开,你通過了面試,你開發(fā)寫代碼的時候怎么辦枕荞?難道也還是背代碼柜候?別逗了兄弟,理解是最重要的躏精。
而且一般你背還是有實際開發(fā)經(jīng)驗的面試官一般一問就知道了渣刷,有啥坑他肯定比你清楚,會就是會矗烛,不會就不會老實回答就好了辅柴。
記住,腹有詩書氣自華瞭吃,我們一起學(xué)習(xí)一起進步喲碌嘀。