天天看點

MQ(消息隊列)常見的應用場景解析

前言

提高系統性能首先考慮的是資料庫的優化,之前一篇文章《資料庫的使用你可能忽略了這些》中有提到過開發中,針對資料庫需要注意的事項。但是資料庫因為曆史原因,橫向擴充是一件非常複雜的工程,所有我們一般會盡量把流量都擋在資料庫之前。

不管是無限的橫向擴充伺服器,還是縱向阻隔到達資料庫的流量,都是這個思路。阻隔直達資料庫的流量,緩存元件和消息元件是兩大殺器。之前文章《Redis常見的應用場景解析》已經描述了最常用的緩存元件redis的應用場景,那麼今天,就重點說說MQ的應用場景。

MQ簡介

MQ,Message queue,消息隊列,就是指儲存消息的一個容器。具體的定義這裡就不類似于資料庫、緩存等,用來儲存資料的。當然,與資料庫、緩存等産品比較,也有自己一些特點,具體的特點後文會做詳細的介紹。

現在常用的MQ元件有activeMQ、rabbitMQ、rocketMQ、zeroMQ,當然近年來火熱的kafka,從某些場景來說,也是MQ,當然kafka的功能更加強大,雖然不同的MQ都有自己的特點和優勢,但是,不管是哪種MQ,都有MQ本身自帶的一些特點,下面,咱們就先聊聊MQ的特點。

MQ特點

  • 先進先出

    不能先進先出,都不能說是隊列了。消息隊列的順序在入隊的時候就基本已經确定了,一般是不需人工幹預的。而且,最重要的是,資料是隻有一條資料在使用中。 這也是MQ在諸多場景被使用的原因。

  • 釋出訂閱

    釋出訂閱是一種很高效的處理方式,如果不發生阻塞,基本可以當做是同步操作。這種處理方式能非常有效的提升伺服器使用率,這樣的應用場景非常廣泛。

  • 持久化

    持久化確定MQ的使用不隻是一個部分場景的輔助工具,而是讓MQ能像資料庫一樣存儲核心的資料。

  • 分布式

    在現在大流量、大資料的使用場景下,隻支援單體應用的伺服器軟體基本是無法使用的,支援分布式的部署,才能被廣泛使用。而且,MQ的定位就是一個高性能的中間件。

應用場景

基于上文所述的特點,那麼MQ就衍生出了中的使用場景,在大型的系統中,應用非常廣泛,這裡我們就列舉一下常見的應用場景。

應用解耦(異步)

MQ(消息隊列)常見的應用場景解析

image

系統之間進行資料互動的時候,在時效性和穩定性之間我們都需要進行選擇。基于線程的異步處理,能確定使用者體驗,但是極端情況下可能會出現異常,影響系統的穩定性,而同步調用很多時候無法保證理想的性能,那麼我們就可以用MQ來進行處理。上遊系統将資料投遞到MQ,下遊系統取MQ的資料進行消費,投遞和消費可以用同步的方式處理,因為MQ接收資料的性能是非常高的,不會影響上遊系統的性能,那麼下遊系統的及時率能保證嗎?當然可以,不然就不會有下面的一個應用場景。

通知

這裡就用到了前文一個重要的特點,釋出訂閱,下遊系統一直在監聽MQ的資料,如果MQ有資料,下遊系統則會按照 先進先出 這樣的規則, 逐條進行消費 ,而上遊系統隻需要将資料存入MQ裡,這樣就既降低了不同系統之間的耦合度,同時也確定了消息通知的及時性,而且也不影響上遊系統的性能。

限流

上文有說了一個非常重要的特性,MQ 資料是隻有一條資料在使用中。 在很多存在并發,而又對資料一緻性要求高,而且對性能要求也高的場景,如何保證,那麼MQ就能起這個作用了。不管多少流量進來,MQ都會讓你遵守規則,排除處理,不會因為其他原因,導緻并發的問題,而出現很多意想不到髒資料。

資料分發

MQ的釋出訂閱肯定不是隻是簡單的一對一,一個上遊和一個下遊的關系,MQ中間件基本都是支援一對多或者廣播的模式,而且都可以根據規則選擇分發的對象。這樣上遊的一份資料,衆多下遊系統中,可以根據規則選擇是否接收這些資料,這樣擴充性就很強了。

PS:上文中的上遊和下遊,在MQ更多的是叫做生産者(producer)和消費者(consumer)。

分布式事務

分布式事務是我們開發中一直盡量避免的一個技術點,但是,現在越來越多的系統是基于微服務架構開發,那麼分布式事務成為必須要面對的難題,解決分布式事務有一個比較容易了解的方案,就是二次送出。基于MQ的特點,MQ作為二次送出的中間節點,負責存儲請求資料,在失敗的情況可以進行多次嘗試,或者基于MQ中的隊列資料進行復原操作,是一個既能保證性能,又能保證業務一緻性的方案,當然,這個方案的主要問題就是定制化較多,有一定的開發工作量。

應用示例

為了更加直覺的展示MQ的應用場景,這裡我們就用一個常見的電商系統中的幾個業務,來具體說明下MQ在實際開發中應用場景。

我們的實際場景大概是一個基于微服務架構的電商系統,分為使用者微服務、商品微服務、訂單微服務、促銷微服務等。基于微服務模式開發的系統,MQ的使用場景更多,下面我們逐一說明:

1、注冊後我們可能需要做很多初始化的操作,如:調用郵件伺服器發送郵件、調用促銷服務贈送優惠劵、下發使用者資料到客戶關系系統等。那麼這時候我們将這些操作去監聽MQ,當使用者注冊成功過後,通過MQ通知其他業務進行操作。確定注冊使用者的性能。

2、背景釋出商品的時候,商品資料需要從資料庫中轉換成搜尋引擎資料(基于elasticsearch),那麼我們應該将商品寫入資料庫後,再寫入到MQ,然後通過監聽MQ來生成elasticsearch對應的資料。

3、使用者下單後,24小時未支付,需要取消訂單。以前我們可能是定時任務循環查詢,然後取消訂單。實際上,我更推薦類似延遲MQ的方式,避免了很多無效的資料庫查詢,将一個MQ設定為24小時後才讓消費者消費掉,這樣很大程度上能減輕伺服器壓力。

4、支付完成後,需要及時的通知子系統(進銷存系統發貨,使用者服務積分,發送短信)進行下一步操作,但是,支付回調我們都是需要保證高性能的,是以,我應該直接修改資料庫狀态,存入MQ,讓MQ通知子系統做其他非實時的業務操作。這樣能保證核心業務的高效及時。

注意事項

其實,還有非常多的業務場景,是可以考慮用MQ方式的,但是很多時候,也會存在濫用的情況,我們需要清楚認識我們的業務場景:

發驗證碼短信、郵件,這種過分依賴外部,而且時效性可以接收幾十秒延遲的,其實更好的方式是多線程異步處理,而不是過多依賴MQ。

秒殺搶購確定庫存不為負數,更多的依賴高性能緩存(如redis),以及強制加鎖,千萬不要依賴消費者最終的傳回結果。(實際工作中已經看到好幾個這樣的案例了)上遊-下遊 這種直接的處理方式效率肯定是比 上遊-MQ-下遊 方式要高,MQ效率高,是因為,我隻是上遊-MQ 這個階段就當做已經成功了。

總結

任何一個技術的出現,都有他的業務場景,隻有清楚技術的特點,才能更加貼切的挖掘出應用場景,深入思考,深入實踐才能将一個技術用在最合适的地方。