面試官問我:什麼是訊息佇列?什麼場景需要他?用了會出現什麼問題?

敖丙發表於2020-02-16

你知道的越多,你不知道的越多

點贊再看,養成習慣

GitHub上已經開源 https://github.com/JavaFamily 有一線大廠面試點腦圖、個人聯絡方式,歡迎Star和完善

前言

訊息佇列在網際網路技術儲存方面使用如此廣泛,幾乎所有的後端技術面試官都要在訊息佇列的使用和原理方面對小夥伴們進行360°的刁難。

作為一個在網際網路公司面一次拿一次Offer的麵霸,打敗了無數競爭對手,每次都只能看到無數落寞的身影失望的離開,略感愧疚(請允許我使用一下誇張的修辭手法)。

於是在一個寂寞難耐的夜晚,暖男我痛定思痛,決定開始寫《吊打面試官》系列,希望能幫助各位讀者以後面試勢如破竹,對面試官進行360°的反擊,吊打問你的面試官,讓一同面試的同僚瞠目結舌,瘋狂收割大廠Offer!

絮叨

這期本來是準備大家投票出來的哈,然後在Java基礎訊息佇列選一個寫的,但是我一想,Java基礎光是集合每種集合我都可以寫好幾篇了,基礎都得寫幾個月了,那是不是可以先把短的這個訊息佇列寫了?

我腦子靈光一閃,拍了下桌子,那就這麼決定了吧!

所以就有這期了哈哈。

重要!在開始之前我想問一下,大家是喜歡我直接懟知識點用自己的語言組織的方式講,還是這樣面試場景的方式講?

因為我發現一個很嚴肅的問題,我的開場和結尾要是幾百篇都差不多,最後你們會不會厭倦呀?

總之這個建議對我很有用,或者你有什麼寫作的建議都可以去GitHub https://github.com/JavaFamily 上面有我的聯絡方式,可以加我微信悄悄跟我說。

面試開始

一個風度翩翩,穿著格子襯衣的中年男子,拿著一個滿是劃痕的mac向你走來,看著錚亮的頭,心想著肯定是尼瑪頂級架構師吧!但是我們看過暖男敖丙的系列,腹有詩書氣自華,虛都不虛。

小夥子之前問了你這麼多Redis的知識,你不僅對答如流,你還能把各自場景的解決方案,優缺點說得這麼流暢,說你是不是看過敖丙寫的《吊打面試官》系列呀?

驚!!!老師你怎麼知道的,我看了他的系列根本停不下來啊。

呵呵,Redis沒難住你,但是我問個新的技術棧我還怕難不住你?我問問你你專案中用過訊息佇列麼?你為啥用訊息佇列?

噗此,這也叫問題?別人用了我能不用麼?別人用了我就用了唄,我就是為了用而用。

你心裡嘀咕就好了,千萬別說出來哈,說出來了沒拿到Offer別到時候就在那說,敖丙那個渣男教我說的!

面試官你好:我們公司本身的業務體量很小,所以直接單機一把梭啥都能搞定了,但是後面業務體量不斷擴大,採用微服務的設計思想分散式的部署方式,所以拆分了很多的服務,隨著體量的增加以及業務場景越來越複雜了,很多場景單機的技術棧和中介軟體以及不夠用了,而且對系統的友好性也下降了,最後做了很多技術選型的工作,我們決定引入訊息佇列中介軟體

哦?你說到業務場景越來越複雜,你那說一下你都在什麼場景用到了訊息佇列?

嗯,我從三個方面去說一下我使用的場景吧。

Tip:這三個場景也是訊息佇列的經典場景,大家基本上要爛熟於心那種,就是一說到訊息佇列你腦子就要想到非同步、削峰、解耦,條件反射那種。

非同步:

我們之前的場景裡面有很多步驟都是在一個流程裡面需要做完的,就比如說我的下單系統吧,本來我們業務簡單,下單了付了錢就好了,流程就走完了。

但是後面來了個產品經理,搞了個優惠券系統,OK問題不大,流程裡面多100ms去扣減優惠券。

後來產品經理靈光一閃說我們可以搞個積分系統啊,也行吧,流程裡面多了200ms去增減積分。

再後來後來隔壁的產品老王說:下單成功後我們要給使用者發簡訊,也將就吧,100ms去發個簡訊。

再後來。。。(敖丙你有完沒完!!!)

反正就流程有點像這樣 ↓

你們可以看到這才加了三個,我可以斬釘截鐵的告訴你真正的下單流程涉及的系統絕對在10個以上(主流電商),越大的越多。

這個鏈路這樣下去,時間長得一批,使用者發現我買個東西你特麼要花幾十秒,垃圾電商我不在你這裡買了,不過要是都像並夕夕這麼便宜,真香

但是我們公司沒有夕夕的那個經濟實力啊,那隻能優化系統了。

Tip:我之前在的電商老東家要求所有介面的RtResponseTime響應時間)在200ms內,超出的全部優化,我現在所負責的系統QPS也是9W+就是抖動一下網路叢集都可能炸鍋那種,RT基本上都要求在50ms以內。

大家感受一下這個QPS。

嗯不錯,鏈路長了就慢了,那你怎麼解決的?

那鏈路長了就慢了,但是我們發現上面的流程其實可以同時做的呀,你支付成功後,我去校驗優惠券的同時我可以去增減積分啊,還可以同時發個簡訊啊。

那正常的流程我們是沒辦法實現的呀,怎麼辦,非同步

你對比一下是不是發現,這樣子最多隻用100毫秒使用者知道下單成功了,至於簡訊你遲幾秒發給他他根本不在意是吧。

小夥子我打斷你一下,你說了非同步,那我用執行緒,執行緒池去做不是一樣的麼?

誒呀,面試官你不要急嘛,我後面還會說到的,騷等。

解耦:

既然面試官這麼問了,我就說一下為啥我們不能用執行緒去做,因為用執行緒去做,你是不是要寫程式碼?

你一個訂單流程,你扣積分,扣優惠券,發簡訊,扣庫存。。。等等這麼多業務要呼叫這麼多的介面,每次加一個你要呼叫一個介面然後還要重新發布系統,寫一次兩次還好,寫多了你就說:老子不幹了!

而且真的全部都寫在一起的話,不單單是耦合這一個問題,你出問題排查也麻煩,流程裡面隨便一個地方出問題搞不好會影響到其他的點,小夥伴說我每個流程都try catch不就行了,相信我別這麼做,這樣的程式碼就像個定時炸彈?,你不知道什麼時候爆炸,平時不炸偏偏在你做活動的時候炸,你就領個P0故障收拾書包提前回家過年吧。

Tip:P0—PN 是網際網路大廠經常用來判定事故等級的機制,P0是最高等級了。

但是你用了訊息佇列,耦合這個問題就迎刃而解了呀。

哦,帥丙怎麼說?

且聽我娓娓道來:

你下單了,你就把你支付成功的訊息告訴別的系統,他們收到了去處理就好了,你只用走完自己的流程,把自己的訊息發出去,那後面要接入什麼系統簡單,直接訂閱你傳送的支付成功訊息,你支付成功了我監聽就好了

那你的流程走完了,你不用管別人是否成功麼?比如你下單了積分沒加,優惠券沒扣怎麼辦?

問題是個好問題,但是沒必要考慮,業務系統本身就是自己的開發人員維護的,你積分扣失敗關我下單的什麼事情?你管好自己下單系統的就好了。

Tip:話是這麼說,但是這其實是用了訊息佇列的一個缺點,涉及到分散式事務的知識點,我下面會提到。

削峰:

就拿我上一期寫的秒殺來說(暗示新同學看我上一期),你平時流量很低,但是你要做秒殺活動00 :00的時候流量瘋狂懟進來,你的伺服器,RedisMySQL各自的承受能力都不一樣,你直接全部流量照單全收肯定有問題啊,直接就打掛了。

那怎麼辦?

簡單,把請求放到佇列裡面,然後至於每秒消費多少請求,就看自己的伺服器處理能力,你能處理5000QPS你就消費這麼多,可能會比正常的慢一點,但是不至於打掛伺服器,等流量高峰下去了,你的服務也就沒壓力了。

你看阿里雙十一12:00的時候這麼多流量瞬間湧進去,他有時候是不是會慢一點,但是人家沒掛啊,或者降級給你個友好的提示頁面,等高峰過去了又是一條好漢了。

為了這個圖特意打高一臺服務的流量
為了這個圖特意打高一臺服務的流量

聽你說了辣麼多,怎麼都是好處,那我問你使用了訊息佇列有啥問題麼?

誒,看過前面我寫的文章的人才都知道,我經常說的就是,技術是把雙刃劍

沒錯面試官,我使用他是因為他帶給我們很多好處,但是使用之後問題也是接踵而至

同樣的暖男我呀,也從三個點介紹他主要的缺點:

系統複雜性

本來蠻簡單的一個系統,我程式碼隨便寫都沒事,現在你憑空接入一箇中介軟體在那,我是不是要考慮去維護他,而且使用的過程中是不是要考慮各種問題,比如訊息重複消費訊息丟失訊息的順序消費等等,反正用了之後就是賊煩。

我插一句嘴,上面的問題(重複消費、訊息丟失、順序消費)你能分別介紹一下,並且說一下分別是怎麼解決的麼?

不要!我都說了敖丙下一章寫啥?

其實不是暖男我不想在這裡寫,這三個問題我想了下,統統都是MQ重點問題,單獨拿一個出來就是一篇文章了,篇幅實在太長了,我會在下一章挨個介紹一遍的。

資料一致性

這個其實是分散式服務本身就存在的一個問題,不僅僅是訊息佇列的問題,但是放在這裡說是因為用了訊息佇列這個問題會暴露得比較嚴重一點。

就像我開頭說的,你下單的服務自己保證自己的邏輯成功處理了,你成功發了訊息,但是優惠券系統,積分系統等等這麼多系統,他們成功還是失敗你就不管了?

我說了保證自己的業務資料對的就好了,其實還是比較不負責任的一種說法,這樣就像個渣男,沒有格局這樣呀你的路會越走越窄的

所有的服務都成功才能算這一次下單是成功的,那怎麼才能保證資料一致性呢?

分散式事務:把下單,優惠券,積分。。。都放在一個事務裡面一樣,要成功一起成功,要失敗一起失敗。

Tip:分散式事務在網際網路公司裡面實在常見,我也不在這裡大篇幅介紹了,後面都會專門說的。

可用性

你搞個系統本身沒啥問題,你現在突然接入一箇中介軟體在那放著,萬一掛了怎麼辦?我下個單MQ掛了,優惠券不扣了,積分不減了,這不是殺一個程式設計師能搞定的吧,感覺得殺一片。

至於怎麼保證高可用,還是那句話也不在這裡展開討論了,我後面一樣會寫,像寫Redis那樣寫出來的。

放心敖丙我不是渣男來的,我肯定會對你們負責的。點贊!

看不出來啊,你有點東西呀,那我問一下你,你們是怎麼做技術選型的?

目前在市面上比較主流的訊息佇列中介軟體主要有,Kafka、ActiveMQ、RabbitMQ、RocketMQ 等這幾種。

不過敖丙我想說的是,ActiveMQRabbitMQ這兩著因為吞吐量還有GitHub的社群活躍度的原因,在各大網際網路公司都已經基本上絕跡了,業務體量一般的公司會是有在用的,但是越來越多的公司更青睞RocketMQ這樣的訊息中介軟體了。

KafkaRocketMQ一直在各自擅長的領域發光發亮,不過寫這篇文章的時候我問了螞蟻金服,位元組跳動和美團的朋友,好像大家用的都有點不一樣,應該都是各自的中介軟體,可能做過修改,也可能是自研的,大多沒有開源

就像我們公司就是是基於KafkaRocketMQ兩者的優點自研的訊息佇列中介軟體,吞吐量、可靠性、時效性等都很可觀。

我們迴歸正題,我這裡用網上找的對比圖讓大家看看差距到底在哪裡:

大家其實一下子就能看到差距了,就拿吞吐量來說,早期比較活躍的ActiveMQRabbitMQ基本上不是後兩者的對手了,在現在這樣大資料的年代吞吐量是真的很重要

比如現在突然爆發了一個超級熱點新聞,你的APP註冊使用者高達億數,你要想辦法第一時間把突發全部推送到每個人手上,你沒有大吞吐量的訊息佇列中介軟體用啥去推?

再說這些使用者大量湧進來看了你的新聞產生了一系列的附帶流量,你怎麼應對這些資料,很多場景離開訊息佇列基本上難以為繼

部署方式而言前兩者也是大不如後面兩個天然分散式架構的哥哥,都是高可用的分散式架構,而且資料多個副本的資料也能做到0丟失。

我們再聊一下RabbitMQ這個中介軟體其實還行,但是這玩意開發語言居然是erlang,我敢說絕大部分工程師肯定不會為了一箇中介軟體去刻意學習一門語言的,開發維護成本你想都想不到,出個問題查都查半天。

至於RocketMQ(阿里開源的),git活躍度還可以。基本上你push了自己的bug確認了有問題都有阿里大佬跟你試試解答並修復的,我個人推薦的也是這個,他的架構設計部分跟同樣是阿里開源的一個RPC框架是真的很像(Dubbo)可能是因為師出同門的原因吧。

Tip:Dubbo等我寫到RPC我會詳細介紹的。

Kafka我放到最後說,你們也應該知道了,壓軸的這是個大哥,大資料領域,公司的日誌採集,實時計算等場景,都離不開他的身影,他基本上算得上是世界範圍級別的訊息佇列標杆了。

以上這些都只是一些我自己的個人意見,真正的選型還是要去深入研究的,不然那你公司一天UV就1000你告訴我你要去用Kafka我只能說你吃飽撐的。

記住,沒有最好的技術,只有最適合的技術,不要為了用而用

面試結束

嗯,小夥子不錯不錯,分析得很到位,那你記得下期來說一下訊息佇列的高可用,重複消費、訊息丟失、訊息順序、分散式事務等問題?

嗯嗯好的面試官,不過不確定能不能一口氣說完,畢竟敖丙還沒開始寫,而且讀者還有可能白嫖,動力不一定夠。

嗯嗯這倒是個問題,不過啊在看的都是人才肯定會給你點贊?的!

我也這麼認為。

總結

訊息佇列的基礎知識我就先介紹這麼多,訊息佇列在面試裡面基本上也是跟我前面寫的Redis一樣必問的。

面試的思路還是一樣,要知其然,也要知其所以然,就是要知道為啥用,用了有啥好處,有啥坑。

面試官不喜歡只知道用的,你只會用那哪天線上出問題怎麼辦?你難道在旁邊拜佛?

後面我會寫到很多實際開發過程中比較複雜的情況,在面試裡面基本上是必考題,我希望你們拿起小本本記下來,不要去背,要去理解,我在人才交流群裡面有仔問我,我怎麼背住這些知識點的?

TipGItHub https://github.com/JavaFamily 個人聯絡方式

你確定沒逗我?你全靠背,你通過了面試,你開發寫程式碼的時候怎麼辦?難道也還是背程式碼?別逗了兄弟,理解是最重要的。

而且一般你背還是有實際開發經驗的面試官一般一問就知道了,有啥坑他肯定比你清楚,會就是會,不會就不會老實回答就好了。

記住,腹有詩書氣自華,我們一起學習一起進步喲。

鳴謝

之前的文章寫了很多人加我,然後有個人才說是他螞蟻金服的Leader推薦的我,我突然意識到我文章的受眾好像慢慢變廣了,之後不嚴謹的點要杜絕掉。

所以之後我的文章經常會有大廠的小夥伴Review,也希望幫助我更好的監督自己的文章吧。

這次是 某阿里系電商跟我一起做過活動小組的 佩恩 幫我Review的文章,感謝!

白嫖不好,創作不易,各位的點贊就是丙丙創作的最大動力,我們下篇文章見,文末圖片有福利

持續更新,未完待續……


文章每週持續更新,可以微信搜尋「 三太子敖丙 」第一時間閱讀,回覆【資料】【面試】有我準備的一線大廠面試資料和文章,本文 GitHub https://github.com/JavaFamily 已經收錄,有大廠面試完整考點,歡迎Star。

你知道的越多,你不知道的越多

相關文章