做者 王新棟 程序員
王新棟。2014年加入京東,一直從事京麥平臺的架構設計與開發工做,熟悉各類開源軟件架構。在Web開發、架構優化上有較豐富實戰經歷。有多年NIO領域的設計、開發經驗,對HTTP、TCP長鏈接技術有深刻研究與領悟,目前主要致力於移動與PC平臺網關技術的優化與實現。面試
消息隊列(MQ)是一種不一樣應用程序之間(跨進程)的通訊方法。應用程序經過寫入和檢索出入列隊的數據(消息)來通訊,而無需經過專用鏈接來連接它們。消息傳遞指的是程序之間經過在消息中發送數據進行通訊,而不是經過直接調用彼此來通訊,直接調用一般是用於諸如遠程過程調用(Remote Procedure Call. RPC)的技術。排隊指的是應用程序經過隊列來通訊。隊列的使用除去了接收和發送應用程序同時執行的要求。這樣自然的就實現了異步的目標。那麼MQ還有哪些功能場景呢。下面逐一介紹。性能優化
解耦服務器
MQ最直接的使用場景就是能夠將兩個系統進行解耦,好比咱們的貨款抵扣業務場景,用戶生成訂單發送MQ後當即返回,結算系統去消費該MQ進行用戶帳戶金額的扣款。這樣訂單系統只須要關注把訂單建立成功,最大可能的提升訂單量,而且生成訂單後當即返回用戶。而結算系統重點關心的是帳戶金額的扣減,保證帳戶金額最終一致。這個場景裏面還會涉及到重試冪等性問題,後面有介紹。網絡
削峯填谷session
仍是以訂單系統和結算系統場景爲例,若是訂單系統經過RPC框架來調用結算系統,在有高峯促銷的狀況下生成訂單的量會很是大,並且因爲生成訂單的速度也很是快,這樣勢必會給結算系統形成系統壓力,服務器利用率則會偏高,但在不是高峯的時間點訂單量比較小,結算系統的服務器利用率則會偏低。對於結算系統來講就會出現下面這樣的高峯波谷現象圖。多線程
那麼若是經過MQ的方式,將訂單存儲到MQ隊列中,消費端經過拉取的方式,而且拉去速度有消費端來控制,則就能夠控制流量趨於平穩。這樣對於結算系統來說,就達到了削峯填谷的目的。或者提及到了流控的目標。接下來,咱們介紹一下拉取方式。架構
拉取模式指用戶在代碼裏主動調用pull方法,不須要在配置文件裏面再配置<mq:listener />,拉取的速度由用戶控制,調用一次拉取一次消息進行消費,這裏要重視消費的速度若是消費性能降低必定會形成積壓,所以用戶本身啓用多線程控制並行度以提升消費速度。框架
代碼樣例:異步
1 2 3 4 5 |
|
method: pull(String topic,MessageListener listener)
topic:指消費的主題名
listener:是一個回調對象,當pull拉取到消息後會主動調用listener.onMessage(),
與監聽模式的區別是:監聽模式由MQ客戶端守護線程去不停的拉取消息進行消費,拉取模式由用戶控制拉取的頻率,不主動調用就不會消費消息。可是都不須要主動對消息進行確認。這種方式更適合寫場景,保證最終結果落地便可,由於讀是須要當即返回以避免讓用戶長時間等待從而影響用戶體驗。
最終一致性
一致性問題分爲強一致性、弱一致性、最終一致性。大多數互聯網業務要求實現最終一致性。仍是以訂單系統和結算系統業務場景舉例,訂單系統建立成功一個訂單後給用戶返回的結果便是成功並明確告訴用戶會從帳戶中扣除相應的金額。那麼結算系統須要保持跟訂單系統相同的狀態即從用帳戶中實際扣除一致的金額。訂單系統會涉及兩個動做,一個是建立成功訂單,一個是發送成功通知到MQ,咱們就能夠把這兩個動做放入到一個本地事務中,要麼成功要麼失敗。當一次發送MQ失敗以後,能夠結合定時任務進行補償,這樣能夠保證生成訂單的結果能夠落地到mq的存儲中。一樣結算系統消費端依靠MQ重試機制一直髮送消息,直到消費端最終確認扣款業務成功處理完成。這樣咱們經過消息落地加補償,消費端從業務上面考慮重複消費的保障,也就是作好冪等性操做,利用MQ實現了最終一致性。
廣播消費
MQ有兩種消息模式一種是點對點模式,一種是發佈/訂閱模式(最經常使用的模式)。同時發佈/訂閱模式按照消費類型又能夠分爲集羣消費和廣播消費。大部分狀況下咱們使用的是集羣消費。
集羣消費:MQ發送任何一條消息,集羣中只有一臺服務器可隨機消費到這條消息。以下圖:
廣播消費:MQ發送每一條消息,集羣中的每一臺服務器至少消費到一次。以下圖:
廣播消費舉例:消息推送系統。首先某一個客戶端與消息中心應用集羣中的一臺服務器創建長鏈接並將鏈接session信息保存到當前服務器內存中,集羣在消費業務消息的時候,是不知道該客戶端創建的長鏈接在哪一臺服務器上面。這個時候經過廣播消費,集羣中的每一臺服務器均可以消費到業務消息。在決定向用戶推送通知以前會判斷當前服務器內存中是否有該客戶端的鏈接session信息,若是有則推送,進而客戶端經過http協議拉取用戶的消息實體。若是session信息不在當前服務器上面,則丟棄。以下圖:
廣播消費注意事項:
一、消費進度在消費端管理,好比默認會在主目錄下建立offset文件夾,偏移量文件存儲在offset目錄下,出現重複的機率要大於集羣消費。
二、MQ能夠確保每條消息至少被每臺消費方服務器消費一次,可是若是消費方消費失敗,不會進入重試,所以業務方須要關注消費失敗的狀況。
三、因爲廣播消費消息不會進行確認,因此管理端上顯示的積壓數會一直不變,須要以出對數爲準。
使用集羣消費模擬廣播
在發佈/訂閱模式中,若是是集羣消費,那麼一條消息只能被集羣中的隨機一臺服務器消費到,若是咱們有須要集羣中的每臺服務器消費到好比上面的消息推送的例子,咱們使用廣播消費來實現。可是廣播消費有一些弊端好比不支持順序消息,消費進度在客戶端維護出現重複的概率要大於集羣模式,廣播模式下不能維護消費進度因此管理端上面的積壓數一直保持不變,咱們就必須以出隊數爲準,也就是不可以支持消息堆積的查詢。若是要規避這些弊端,那麼咱們能夠利用集羣消費來模擬廣播,在集羣消費中,咱們的每臺服務器上面的消費APPID是相同的,若是要達到廣播的效果,那麼每臺服務器上面的消費APPID保持不一樣就能夠了。
重試之坑
MQ的重試功能能夠保證數據結果最終獲得處理,但同時也正由於有重試那麼在業務處理的時候就須要格外注意冪等性的問題。好比貨款抵扣業務,訂單系統生成訂單以後調用結算平臺去扣除用戶的帳戶金額。結算平臺要根據流水號去計算,若是訂單系統在調用結算平臺的時候發生了網絡異常,形成告終算平臺實際上已經獲得請求而且已處理。訂單系統一側認爲發生異常須要重試,後續再發送到結算平臺的訂單就會形成重複扣款問題。因此流水號尤爲要注意須要保證重試過程當中每次發送的流水號是一致的,結算平臺會根據流水號去作業務校驗,若是已經處理,則丟棄,最終確保冪等性。針對上面的技術我特地整理了一下,有不少技術不是靠幾句話能講清楚,因此乾脆找朋友錄製了一些視頻,不少問題其實答案很簡單,可是背後的思考和邏輯不簡單,要作到知其然還要知其因此然。若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java進階羣:725219329,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。
總結
咱們介紹了MQ常見的使用場景,以及每種場景下的使用注意事項。尤爲是在重試功能中,重試原本是MQ提供的一種保持數據最終能夠獲得確認的方法,可是若是業務使用上面不注意冪等性,則會帶來業務數據的不一致甚至像重複扣款這樣比較嚴重的後果。咱們還介紹了發佈/訂閱模式下的廣播消費的使用舉例,也介紹了它的缺點以及可使用集羣消費來模擬廣播。鑑於以上每種場景都給咱們提供了很好的說明使得你們在之後使用MQ的過程當中能夠更好的發揮MQ的強大做用。
在互聯網公司面試中,架構的底層必定是面試官會問問的問題,針對面試官通常會提到的問題,我錄製了一些分佈式,微服務,性能優化等技術點底層原理的錄像視頻,加羣619881427能夠免費獲取這些錄像,裏面還有些分佈式,微服務,性能優化,春天設計時,MyBatis的等源碼知識點的錄像視頻。這些視頻都是 找一些資深架構師朋友一塊兒錄製出來的,這些視頻幫助如下幾類程序員:
1.對如今的薪資不滿,想要跳槽,卻對本身的技術沒有信心,不知道如何面對面試官。
2.想從傳統行業轉行到互聯網行業,但沒有接觸過互聯網技術。
3.工做1 - 5年須要提高本身的核心競爭力,但學習沒有系統化,不知道本身接下來要學什麼纔是正確的,踩坑後又不知道找誰,百度後依然不知因此然。
4.工做5 - 10年沒法突破技術瓶頸(運用過不少技術,在公司一直寫着業務代碼,卻依然不懂底層實現原理)
若是你如今正處於我上述所說的幾個階段能夠加下個人羣來學習。並且我也可以提供一些面試指導,職業規劃等建議。