1. 程式人生 > >RocketMQ原理學習--RocketMQ整體架構窺探

RocketMQ原理學習--RocketMQ整體架構窺探

 RocketMQ總體架構圖:

RocketMQ簡單架構

角色簡介:

1、Name Server:簡單可以理解為註冊中心,Broker相關資訊會註冊到Name Server叢集中,維護Broker及Broker中相關Topic資訊,這樣生產者和消費者就可以從Name Server中定時(30秒)獲取相關Broker資訊。

2、Broker:叢集最核心模組,主要負責Topic訊息儲存、消費者的消費位點管理(消費進度)。

3、Producer: 訊息生產者,每個生產者都有一個ID(編號),多個生產者例項可以共用同一個ID。同一個ID下所有例項組成一個生產者叢集。
4、Consumer: 訊息消費者,每個訂閱者也有一個ID(編號),多個消費者例項可以共用同一個ID。同一個ID下所有例項組成一個消費者叢集。

Name Server

        Namesrv用於儲存Topic、Broker關係資訊,功能簡單,穩定性高。多個Namesrv之間相互沒有通訊,單臺Namesrv宕機不影響其他Namesrv與叢集;即使整個Namesrv叢集宕機,已經正常工作的Producer,Consumer,Broker仍然能正常工作,但新起的Producer, Consumer,Broker就無法工作。
        Namesrv壓力不會太大,平時主要開銷是在維持心跳和提供Topic-Broker的關係資料。但有一點需要注意,Broker向Namesr發心跳時,會帶上當前自己所負責的所有Topic資訊,如果Topic個數太多(萬級別),會導致一次心跳中,就Topic的資料就幾十M,網路情況差的話,網路傳輸失敗,心跳失敗,導致Namesrv誤認為Broker心跳失敗。

Broker

1、高併發讀寫服務
Broker的高併發讀寫主要是依靠以下兩點:
訊息順序寫:所有Topic資料同時只會寫一個檔案,一個檔案滿1G,再寫新檔案,真正的順序寫盤,使得發訊息TPS大幅提高。
訊息隨機讀:RocketMQ儘可能讓讀命中系統pagecache,因為作業系統訪問pagecache時,即使只訪問1K的訊息,系統也會提前預讀出更多的資料,在下次讀時就可能命中pagecache,減少IO操作。

2、負載均衡與動態伸縮

負載均衡:在Broker上一個Topic會對應幾個MessageQueue(預設每個Broker上會建立4個MessageQueue),生產者在傳送訊息時預設採用輪詢方式將訊息依次傳送到各個MessageQueue中。

動態伸縮能力:訊息會發送到不同Broker的同一個Topic的MessageQueue中,因此可以進行Broker的動態修改。

3、高可用&高可靠
高可用:叢集部署時一般都為主備,備機實時從主機同步訊息,如果其中一個主機宕機,備機提供消費服務,但不提供寫服務。
高可靠:所有發往broker的訊息,有同步刷盤和非同步刷盤機制;同步刷盤時,訊息寫入物理檔案才會返回成功,非同步刷盤時,只有機器宕機,才會產生訊息丟失,broker掛掉可能會發生,但是機器宕機崩潰是很少發生的,除非突然斷電
4、Broker與Namesrv的心跳機制
單個Broker跟所有Namesrv保持心跳請求,心跳間隔為30秒,心跳請求中包括當前Broker所有的Topic資訊。Namesrv會反查Broer的心跳資訊,如果某個Broker在2分鐘之內都沒有心跳,則認為該Broker下線,調整Topic跟Broker的對應關係。但此時Namesrv不會主動通知Producer、Consumer有Broker宕機。

消費者

消費者啟動時需要指定Namesrv地址,與其中一個Namesrv建立長連線。消費者每隔30秒從nameserver獲取所有topic的最新佇列情況,這意味著某個broker如果宕機,客戶端最多要30秒才能感知。連線建立後,從namesrv中獲取當前消費Topic所涉及的Broker,直連Broker。

Consumer跟Broker是長連線,會每隔30秒發心跳資訊到Broker。Broker端每10秒檢查一次當前存活的Consumer,若發現某個Consumer 2分鐘內沒有心跳,就斷開與該Consumer的連線,並且向該消費組的其他例項傳送通知,觸發該消費者叢集的負載均衡。

消費者端的負載均衡
先討論消費者的消費模式,消費者有兩種模式消費:叢集消費,廣播消費。

廣播消費:每個消費者消費Topic下的所有佇列。
叢集消費:一個topic可以由同一個ID下所有消費者分擔消費。具體例子:假如TopicA有6個佇列,某個消費者ID起了2個消費者例項,那麼每個消費者負責消費3個佇列。如果再增加一個消費者ID相同消費者例項,即當前共有3個消費者同時消費6個佇列,那每個消費者負責2個佇列的消費。
消費者端的負載均衡,就是叢集消費模式下,同一個ID的所有消費者例項平均消費該Topic的所有佇列。

目前RocketMQ提供了消費者兩種獲取訊息的方式:Pull和Push(實際都是Consumer拉取訊息)

Pull模式:Pull方式裡,取訊息的過程需要使用者自己寫,首先通過打算消費的Topic拿到MessageQueue的集合,遍歷MessageQueue集合,然後針對每個MessageQueue批量取訊息,一次取完後,記錄該佇列下一次要取的開始offset,直到取完了,再換另一個MessageQueue。

Push模式:Push方式裡,consumer把輪詢過程封裝了,並註冊MessageListener監聽器,取到訊息後,喚醒MessageListener的consumeMessage()來消費,對使用者而言,感覺訊息是被推送過來的。

生產者(Producer)

Producer啟動時,也需要指定Namesrv的地址,從Namesrv叢集中選一臺建立長連線。如果該Namesrv宕機,會自動連其他Namesrv。直到有可用的Namesrv為止。

生產者每30秒從Namesrv獲取Topic跟Broker的對映關係,更新到本地記憶體中。再跟Topic涉及的所有Broker建立長連線,每隔30秒發一次心跳。在Broker端也會每10秒掃描一次當前註冊的Producer,如果發現某個Producer超過2分鐘都沒有發心跳,則斷開連線。

生產者端的負載均衡

1、生產者傳送時,會自動輪詢當前所有可傳送的broker中的MessageQueue,一條訊息傳送成功,下次換另外一個broker傳送,以達到訊息平均落到所有的broker上。

2、由於生產者預設的負載均衡策略是輪詢,如果想要修改這種策略可以實現MessageQueueSelector介面,例如順序訊息的實現就可以依賴MessageQueueSelector來實現。

這裡需要注意一點:假如某個Broker宕機,意味生產者最長需要30秒才能感知到。在這期間會向宕機的Broker傳送訊息。當一條訊息傳送到某個Broker失敗後,會往該broker自動再重發2次,假如還是傳送失敗,則丟擲傳送失敗異常。業務捕獲異常,重新發送即可。客戶端裡會自動輪詢另外一個Broker重新發送,這個對於使用者是透明的。

 


參考:

https://blog.csdn.net/yhl_jxy/article/details/77512226

https://blog.csdn.net/javahongxi/article/details/72956608