1. 前言
除了計(jì)算機(jī)網(wǎng)絡(luò)、操作系統(tǒng)等基礎(chǔ)知識的考察,各種流行的中間件也深受面試官的青睞。之前的章節(jié)已經(jīng)對緩存中間件的代表 Redis 的面試題進(jìn)行了分析,本章節(jié)將介紹常用的消息中間件,即 RabbitMQ 的基礎(chǔ)定義以及使用原因。
2. 消息隊(duì)列使用場景
面試官提問: 為什么要使用消息隊(duì)列?能說說消息隊(duì)列解決了什么問題?
題目解析:
任何工具都有誕生的背景,例如非關(guān)系型數(shù)據(jù)庫是為了解決性能以及擴(kuò)展性問題產(chǎn)生。
常見的消息隊(duì)列有 RabbitMQ、RocketMQ、Kafka 等,消息隊(duì)列也是針對特定問題有不同的使用場景,可以抽象為異步處理、應(yīng)用解耦、流量削峰三種場景。
2.1 異步處理 & 應(yīng)用解耦
以最常見的在網(wǎng)站注冊新用戶場景為例,如果經(jīng)過了基本的業(yè)務(wù)邏輯之后,要通過短信和郵件的方式驗(yàn)證是否用戶本人注冊,每個(gè)流程的請求響應(yīng)耗時(shí)為 100ms,在同步的方式下總共需要耗時(shí) 300ms。
?
其中發(fā)送驗(yàn)證短信以及發(fā)送驗(yàn)證郵件兩個(gè)步驟并沒有強(qiáng)制的先后依賴關(guān)系,所以同步請求的效率相對較低,使用消息隊(duì)列可以將驗(yàn)證短信和郵件的模塊拆開,經(jīng)過消息隊(duì)列中轉(zhuǎn)分發(fā)請求,假設(shè)消息隊(duì)列的讀寫時(shí)間為 20ms,總流程的耗時(shí)被優(yōu)化到 220ms。
?
上述異步請求的過程本質(zhì)上也是應(yīng)用解耦的過程,最基礎(chǔ)的應(yīng)用架構(gòu)中可以將短信注冊模塊和郵件注冊模塊都可以耦合在注冊業(yè)務(wù)邏輯中,但是如果有其他的服務(wù)也需要使用短信注冊功能,就只能調(diào)用注冊業(yè)務(wù)的短信模塊接口。此時(shí),程序的魯棒性相對較差,當(dāng)注冊業(yè)務(wù)模塊的服務(wù)器宕機(jī)之后,會(huì)造成所有服務(wù)的短信模塊都不可用,所以需要將短信模塊解耦出來,同理,郵件模塊也需要被拆分為單獨(dú)的服務(wù)。候選人需要注意一點(diǎn),這種拆分本質(zhì)上都是為了應(yīng)用服務(wù)的高可用。
2.2 流量削峰
互聯(lián)網(wǎng)存在很多高并發(fā)場景,例如在 12306 搶購春運(yùn)火車票,或者阿里淘寶的雙十一秒殺活動(dòng),系統(tǒng)服務(wù)在短時(shí)間收到大量的用戶請求,如果數(shù)據(jù)庫不能抗住相對日常的 N 倍流量被打垮,會(huì)導(dǎo)致服務(wù)不可用。為了避免這種情況發(fā)生,有熔斷、降級、以及流量削峰等多種解決方案,消息隊(duì)列是最常見的流量削峰方案。
?
還是以用戶注冊的例子,例如在雙十一凌晨時(shí)間,大量新用戶通過活動(dòng)鏈接進(jìn)入了網(wǎng)站的注冊頁面,在收到用戶請后后,首先將請求寫入消息隊(duì)列,如果請求數(shù)量超過消息隊(duì)列的容量,那么多余的請求直接放棄并且跳轉(zhuǎn)到錯(cuò)誤頁面,這也是常用的降級方案。
業(yè)務(wù)代碼從消息隊(duì)列中拿到用戶請求,再進(jìn)行后續(xù)的業(yè)務(wù)邏輯。消息隊(duì)列在用戶和業(yè)務(wù)邏輯中之間作為中間件模塊,防止大量流量直接打到底層數(shù)據(jù)庫。
3. 常用消息隊(duì)列
面試官提問: 常用的消息隊(duì)列有哪些?
題目解析:
最常見的消息隊(duì)列有 ActiveMQ、RabbitMQ、RocketMQ 以及 Kafka,我們一般關(guān)注的是 RabbitMQ 以及 Kafka,我們關(guān)注基本定義以及兩者之間的特性差別。
- RabbitMQ:基于 Erlang 語言開發(fā)的消息發(fā)布和訂閱系統(tǒng),基于 AMQP 協(xié)議實(shí)現(xiàn)。AMQP 協(xié)議一般在對數(shù)據(jù)一致性要求高、對性能要求較低的場景使用;
- Kafka:LinkedIn 公司開源的消息發(fā)布和訂閱系統(tǒng),一般在對數(shù)據(jù)一致性要求較低、海量數(shù)據(jù)的處理場景中使用。
下面對比分析下兩種消息隊(duì)列的特性差異。
3.1 吞吐量對比
- RabbitMQ:單機(jī)吞吐量在萬級別,比 Kafka 低一個(gè)數(shù)量級;
- Kafka:單機(jī)吞吐量在十萬級別,數(shù)據(jù)的存儲(chǔ)和讀取都是依靠本地硬盤的順序讀寫,處理效率高。
3.2 應(yīng)用場景對比
- RabbitMQ:企業(yè)內(nèi)部微服務(wù),例如內(nèi)部人員管理系統(tǒng)的消息通訊場景。因?yàn)榛?Erlang 開發(fā)語言,對小型企業(yè)來說,開發(fā)維護(hù)成本相對較高;
- Kafka:大數(shù)據(jù)系統(tǒng)中常用,例如日志處理以及數(shù)據(jù)實(shí)時(shí)分析場景,目前 Kafka 幾乎是日志采集場景的首選消息隊(duì)列。
4. 小結(jié)
本章節(jié)介紹了消息隊(duì)列的基本使用場景,需要理解消息隊(duì)列的核心是異步處理以及解耦能力。我們對比了 RabbitMQ 和 Kafka 兩種消息隊(duì)列的特性,在后續(xù)的章節(jié)主要會(huì)對 RabbitMQ 的常見題目進(jìn)行分析。