開足碼力,碼動人生,本文首發(fā)公眾號【 Craig無忌 】篙程,關注這個一言不合就開車的的代碼界老司機
本文 GitHub上已經(jīng)收錄 https://github.com/BeKingCoding/JavaKing , 一線大廠面試核心知識點、我的聯(lián)系方式和技術交流群叉跛,歡迎Star和完善
前言
我們知道訂單系統(tǒng)堪稱整個電商交易平臺的核心,它需要與很多內(nèi)部模塊蒸殿、外部第三方系統(tǒng)打交道筷厘。其實從下訂單到支付完成這個過程中,需要完成很多額外的步驟:
為用戶積分
發(fā)放紅包卡券
庫存扣減
通知物流系統(tǒng)
發(fā)送短信通知
本文就以訂單系統(tǒng)為基礎宏所,看完后相信你會對消息中間件的原理有更清晰的認識酥艳。本文將會從以下幾個方面來講述相關知識,相信大家耐心看了之后肯定有收獲爬骤,碼字不易充石,別忘了「在看」,「轉發(fā)」哦霞玄。
- 什么是消息中間件骤铃,消息中間件的作用
- 實現(xiàn)三高(高并發(fā)、高可用坷剧、高性能)的策略
- 消息中間件的種類
- 如何選擇合適的消息中間件
正文
01 什么是消息中間件
對于一個電商APP而言惰爬,每賣掉了一個商品,就要扣減掉商品的庫存惫企,而且一旦用戶成功支付了撕瞧,還需要將訂單的狀態(tài)更新成待發(fā)貨。
在完成這些最核心的功能后狞尔,其實是有很多事情要做的丛版,比如上圖紅色的部分。如果這些動作都以同步方式來完成沪么,根據(jù)線上系統(tǒng)的一般統(tǒng)計硼婿,多個子步驟全部執(zhí)行完畢,加起來大概需要1秒~2秒的時間禽车。
有時候在高峰期并發(fā)量特別大寇漫,服務器的磁盤、IO殉摔、CPU的負載會很高州胳,執(zhí)行SQL語句的性能也會有所下降。因此有的時候甚至需要幾秒鐘的時間完成上述幾個步驟逸月。
那么影響是什么呢?
想象一下栓撞,如果你是一個用戶,在支付完一個訂單之后,界面上會有一個圈圈不停的旋轉瓤湘,讓你等待好幾秒之后才能提示支付成功瓢颅。對用戶來說幾秒鐘的時間,會讓人非常不耐煩的!
所以首先針對子步驟過多弛说、速度過慢挽懦、讓用戶支付之后等待時間過長的問題,就是訂單系統(tǒng)亟需解決的問題!
而解決這個問題的一大利器就是消息中間件木人,英文全稱“Message Queue”信柿,簡稱MQ。
在引入消息中間件以后醒第,系統(tǒng)A和系統(tǒng)B之間就由同步變?yōu)楫惒酵ㄐ庞嫒拢瓿蛇@樣的一個核心概念就是“消息”。
系統(tǒng)A發(fā)送消息給MQ后稠曼,就認為已經(jīng)完成了自己的任務形病;然后系統(tǒng)B根據(jù)自己的情況,可能會在系統(tǒng)A投遞消息到MQ之后的1秒內(nèi)霞幅,也可能是1分鐘之后窒朋,也可能是1小時之后,多長時間都有可能蝗岖。
反正不管是多長時間后,系統(tǒng)B會根據(jù)自己的節(jié)奏從MQ里獲取到一條屬于自己的消息榔至,再根據(jù)消息的指示完成自己的工作抵赢。
在“異步調(diào)用”的整個過程中,系統(tǒng)A僅僅是發(fā)個消息到MQ唧取,至于系統(tǒng)B什么時候獲取消息铅鲤,有沒有獲取消息,系統(tǒng)A是不管的枫弟。
02 消息中間件的作用
順著這個思路邢享,我們再重新思考一下訂單系統(tǒng)。由于支付訂單流程中淡诗,過多的子步驟如紅包發(fā)放骇塘、短信push通知、積分等等導致性能很差韩容。
在引入MQ后款违,我們可以讓訂單系統(tǒng)僅僅完成最核心的功能,然后發(fā)送消息到MQ群凶。比如需要進行減庫存插爹,就發(fā)送一個消息到庫存消息隊列中,然后庫存系統(tǒng)從這個MQ里獲取消息再進行處理就可以,把這些很耗時的步驟慢慢執(zhí)行赠尾,從而也實現(xiàn)了系統(tǒng)之間的解耦力穗。
在雙11大促活動的時候,同樣可以讓瞬間涌入的大量下單請求到MQ里去排隊气嫁,然后讓訂單系統(tǒng)在后臺慢慢的獲取訂單当窗,以數(shù)據(jù)庫可以接受的速率完成操作,避免瞬間請求量過大擊垮數(shù)據(jù)庫杉编。
這也是MQ的另一重要功能:削峰填谷超全,我會在接下來的文章更加詳細的以秒殺場景進行介紹。
所謂消息中間件邓馒,就是一種系統(tǒng)嘶朱,它自己本身也是獨立部署的,通過消息的收發(fā)光酣,是多個系統(tǒng)之間不局限于同步調(diào)用疏遏,通過異步調(diào)用更好地實現(xiàn)解耦。
03 實現(xiàn)三高的策略
具體來說救军,消息中間件财异,也就是MQ只是一種概念和模式。在真正使用的時候唱遭,我們要考慮如何正確使用MQ來滿足我們的需求戳寸。簡單來看,可以從以下幾個維度進行思考:
(1)MQ的性能表現(xiàn)怎么樣拷泽?
(2)假如機器硬件條件相同疫鹊,比如互聯(lián)網(wǎng)公司最為常見的2G4核或者4G8核,能抗住多少Q(mào)PS司致,每秒幾千QPS或幾萬QPS拆吆,什么程度會到達性能瓶頸?
(3)性能有多高脂矫,比如向MQ發(fā)送消息需要2毫秒還是20毫秒枣耀?
(4)能夠高可用嗎,如果部署的一臺服務器宕機了怎么辦庭再,有沒有自動修復的機制捞奕?
(5)可靠嗎,會不會丟失數(shù)據(jù)拄轻?
(6)支持線性的集群擴展嗎缝彬,添加更多機器的機制復雜嗎?
(7)功能性滿足嗎哺眯,比如經(jīng)常需要使用的功能:延遲消息谷浅、事務消息、消息累積、消息回溯一疯、死信隊列等等撼玄?
(8)官方文檔是否完整且清晰,社區(qū)活躍嗎墩邀,如果遇到技術問題我們是否方便地找到解決辦法掌猛?
(9)在工業(yè)中是否已經(jīng)被廣泛使用了,已經(jīng)被大公司驗證過它的質(zhì)量眉睹?
(10)它是用什么語言寫的荔茬,如果有個性化的需求,是否可以對源碼進行修改竹海?
借著這個機會慕蔚,我們可以對MQ有一個基本的了解,把這些事情都搞清楚了斋配,你會發(fā)現(xiàn)消息中間件技術并沒你想的那么難孔飒。
04 消息中間件的種類
目前業(yè)界使用最廣泛的是Kafka、RabbitMQ以及RocketMQ這三種消息中間件艰争,因此我們主要針對它們來進行調(diào)研對比坏瞄。接下來我們從性能、可靠性甩卓、功能性等多方面維度鸠匀,來分析一下它們的優(yōu)勢和劣勢。
Kafka
- 優(yōu)勢
(1)Kafka的吞吐量幾乎是行業(yè)里最優(yōu)秀的逾柿,在常規(guī)的機器配置下狮崩,一臺機器可以達到每秒十幾萬的QPS,可謂是消息中間件中的頂尖水平鹿寻。
(2)性能高,發(fā)送消息給Kafka可以控制在毫秒級诽凌。
(3)可用性高毡熏,Kafka能夠支持集群部署,如果部分服務器發(fā)生了宕機侣诵,集群其余部分可以保證任務的繼續(xù)運行痢法。
- 劣勢
(1)Kafka的存儲策略是在消息收到之后,將其寫入磁盤緩沖區(qū)內(nèi)杜顺,并不會直接存儲到物理硬盤上财搁。這就導致了假如機器本身發(fā)生故障,磁盤緩沖區(qū)里的數(shù)據(jù)非常有可能丟失躬络。而消息作為最重要的資源尖奔, kafka的這一特點有可能造成嚴重后果。
(2)Kafka另外一個比較大的缺點是功能比較單一。它使用了典型的推拉架構設計提茁,生產(chǎn)者將發(fā)送消息給它淹禾,然后消費者在從它拉取消息進行消費。除此之外茴扁,其他就沒有什么額外的高級功能铃岔,所以基于Kafka有限的功能,一些比較復雜的商業(yè)場景并不是很適合峭火。
RabbitMQ
再說RabbitMQ毁习,在RocketMQ出現(xiàn)之前,國內(nèi)大部分公司卖丸,包括很多一線互聯(lián)網(wǎng)大廠都在使用RabbitMQ纺且,而且直到目前,還有很多中小型公司在使用RabbitMQ坯苹。
- 優(yōu)勢
(1)可以有保證數(shù)據(jù)不丟失的機制隆檀。
(2)保證高可用性,集群部署的時候部分粹湃,即使部分服務器宕機可以繼續(xù)執(zhí)行任務恐仑。
(3)實現(xiàn)了部分高級功能,比如死信隊列为鳄,消息重試裳仆。
- 劣勢
(1)RabbitMQ的吞吐量是比較低,只有每秒幾萬的級別孤钦,遇到像雙十一這樣的高并發(fā)場景歧斟,很容易到達性能的瓶頸。
(2)維護比較復雜偏形,在集群部署時静袖,如果需要線性擴展,比較麻煩俊扭。
(3)它的開發(fā)語言是erlang队橙,國內(nèi)目前大大小小公司的技術骨干大部分都是BAT背景,精通erlang語言的還是少數(shù)萨惑。閱讀源代碼非常困難捐康,也就更加無從談起根據(jù)個性化要求修改源代碼了
RocketMQ
RocketMQ是阿里開源的消息中間件,經(jīng)過實戰(zhàn)的檢驗庸蔼,比較靠譜解总。后發(fā)優(yōu)勢使它在最初設計的時候,就為了去解決Kafka和RabbitMQ所存在的缺陷姐仅。
- 優(yōu)勢
(1)性能強大花枫,吞吐量高刻盐,能夠達到10萬QPS以上的級別
(2)可以保證高可用性,能夠大規(guī)模集群化部署
(3)支持通過配置保證數(shù)據(jù)絕對不丟失
(4)滿足多種需求乌昔,比如說延遲消息隙疚、事務消息、消息回溯磕道、死信隊列供屉、消息積壓等等。
(5)RocketMQ是基于Java開發(fā)的溺蕉,符合國內(nèi)大多數(shù)公司的技術棧伶丐,很容易就可以閱讀他的源碼,甚至是修改他的源碼疯特。
- 劣勢
當然RocketMQ也有美中不足的地方哗魂,RocketMQ的官方文檔相對簡單,而這也是國內(nèi)開源軟件和社區(qū)的一個通病漓雅,可能國內(nèi)996的工作強度導致大家沒有更多的精力維護录别。
相比于起步早,社區(qū)化程度高的的Kafka和RabbitMQ 的官方文檔邻吞,這是RocketMQ需要慢慢追趕的一點组题。
05 如何選擇合適的消息中間件
根據(jù)Kafka技術在各大公司里的使用情況,目前行業(yè)內(nèi)比較流行的方式是用Kafka進行采集和傳輸用戶行為日志抱冷。對于一個電商公司而言崔列,每天的行為數(shù)據(jù)堪稱天量,比如商品詳情頁的點擊旺遮,店鋪的轉化率等等赵讯,非常適合大數(shù)據(jù)團隊來收集APP上用戶的種種行為。
雖然Kafka有可能會導致消息的丟失耿眉,但由于日志本身并不像訂單那么重要边翼,即使真的發(fā)生了數(shù)據(jù)丟失也在可控范圍內(nèi)。
最主要在這個場景下鸣剪,日志量特別大组底,吞吐量必須要高,只要保證收發(fā)消息的正常完成就滿足的需要西傀,并不需要其他功能,所以 Kafka非常適合這種場景桶癣。
而目前現(xiàn)在國內(nèi)很多一線互聯(lián)網(wǎng)大廠拥褂,在核心系統(tǒng)模板上,都在慢慢切換為使用RocketMQ了牙寞。RocketMQ的高吞吐量饺鹃,大規(guī)模集群部署能力莫秆,以及各種高級功能滿足了日益復雜的商業(yè)化業(yè)務需求,尤其是非常適合用在Java業(yè)務系統(tǒng)架構中悔详,同時還可以根據(jù)自己的需求定制修改RocketMQ的源碼镊屎。
對于中小型互聯(lián)網(wǎng)公司,并發(fā)量沒那么大茄螃,似乎看起來RabbitMQ也能滿足所有的需要缝驳。沒有特別高的吞吐量,也不需要部署大規(guī)模集群归苍,更沒必要閱讀和修改RabbitMQ的源碼用狱。但是RocketMQ一定是更好的選擇,因為它規(guī)避掉了RabbitMQ的全部缺點拼弃。
假設未來我們身處一個大公司夏伊,每秒會有幾十萬的QPS,也許我們以后也需要對MQ進行源碼的二次開發(fā)吻氧,那此時RabbitMQ還合適嗎?
文末福利
最近各大互聯(lián)網(wǎng)公司的秋招都陸陸續(xù)續(xù)開始了溺忧,還在找工作的小伙伴可以后臺回復關鍵字進入對應的秋招/內(nèi)推/面試群,我給大家整理了各大公司的內(nèi)推通道盯孙、簡歷模板還有歷年的筆試題鲁森,大家要好好準備哦。還可以幫助大家免費修改簡歷镀梭、模擬面試哦~
關注公眾號「Craig無忌」
創(chuàng)作不易刀森,各位的支持和認可,就是我創(chuàng)作的最大動力报账,我們下篇文章見研底!