在美國的大學課程中,101是全部課程中的第一門,是新生入學後的必修課程。阿里巴巴中間件技術專家劉振東在上週的Apache RocketMQ開發者沙龍北京站的活動上,進行了主題爲《ApacheRocketMQ 101》的分享,幫助開發者從0開始學習 Apache RocketMQ,除了一些基礎的入門內容外,還有不少是在社區未發表過的我的所感所悟,首次對外分享。分享內容包括RocketMQ的起源、RocketMQ概念模型、存儲模型、部署模型和最佳實踐總結,其中最佳實踐的內容是阿里中間件技術類崗位的必考面試題。面試
嘉賓介紹:劉振東,阿里巴巴中間件技術專家,Apache RocketMQ PMC/Committer,2016年中間件性能挑戰賽亞軍,具備豐富的分佈式系統設計和優化經驗,目前負責Apache RocketMQ新航道探索和創新。網絡
1、RocketMQ的起源 架構
一般,每一個產品的誕生都源於一個具體的需求或問題,RocketMQ也不例外。起初,產品的原型像一個巨石,把全部須要實現的程序和接口都羅列到一塊兒。但隨着公司業務的發展,全部的系統和功能都在這個巨石上開發,當覆蓋幾百上千名開發人員的時候,瓶頸就出來了。這時候,就須要咱們把系統進行分解。異步
圖釋:巨石 -> 分佈式分佈式
分解後,就出現了上圖中的分佈式架構,這類架構最大的特色就是解耦,而RocketMQ的異步解耦意味着底層的重構不會影響到上層應用的功能。RocketMQ另外一個優點是削峯填谷,在面臨流量的不肯定性時,實現對流量的緩衝處理。此外,RocketMQ的順序設計特性使得RocketMQ成爲一個自然的排隊引擎,例如,三個應用同時對一個後臺引擎發起請求,排隊引擎的特性能夠確保不會引發「撞車」事故。性能
2、RocketMQ的概念模型 學習
對於任何一款中間件產品而言,清晰的概念模型是幫助開發者正確理解使用它的關鍵。從RocketMQ的概念模型來看:Topic是用於存儲邏輯的地址的,Producer是信息的發送,Consumer是信息的接收者。優化
圖釋:最基本的概念模型設計
這只是一個基礎的概念模型,在實際的生產中,結構會更復雜,例如咱們須要對中間的Topic進行分區,出現多個有關聯的Topic,再如同一個信息的發送方會有多個訂閱者,同一個需求方會有多個發送方,出現一對多、多對一的狀況。3d
圖釋:擴展後的概念模型
上圖就是對Topic、Producer、Consumer擴展後的概念模型。RocketMQ中能夠接觸到的全部概念均可以在這個概念模型圖中找到。左邊有兩個Producer,中間就是兩個分佈式的Topic,用於存儲邏輯地址的兩個Topic中分別有兩個用於存儲物理存儲地址的Message Queue,Broker是實際部署過程的對應的一臺設備,右邊則是兩個Consumer,Consumer Group是表明兩個Consumer可共享相互之間的訂閱。不一樣的Consumer Group相互獨立。一句話總結就是不一樣的Group是廣播訂閱的,同一個Group則是負載訂閱的。圖中的連線表示各模塊之間的關係,例如Consumer Group A中的Consumer1對應着Message Queue0和Message Queue1的兩個隊列,分佈在BrokerA這一臺設備上。
3、RocketMQ的存儲模型
RocketMQ的消息的存儲是由ConsumeQueue和CommitLog 配合來完成的,ConsumeQueue中只存儲不多的數據,消息主體都是經過CommitLog來進行讀寫。
圖釋:存儲模型
CommitLog:是消息主體以及元數據的存儲主體,對CommitLog創建一個ConsumeQueue,每一個ConsumeQueue對應一個(概念模型中的)MessageQueue,因此只要有Commit Log在,Consume Queue即便數據丟失,仍然能夠恢復出來。
Consume Queue:是一個消息的邏輯隊列,存儲了這個Queue在CommitLog中的起始offset,log大小和MessageTag的hashCode。每一個Topic下的每一個Queue都有一個對應的ConsumerQueue文件,例如Topic中有三個隊列,每一個隊列中的消息索引都會有一個編號,編號從0開始,往上遞增。並由此一個位點offset的概念,有了這個概念,就能夠對Consumer端的消費狀況進行隊列定義。
4、RocketMQ的部署模型
在實際的部署過程當中,Broker是實際存儲消息的數據節點,Nameserver則是服務發現節點,Producer發送消息到某一個Topic,並給到某個Consumer用於消費的過程當中,須要先請求Nameserver拿到這個Topic的路由信息,即Topic在哪些Broker上有,每一個Broker上有哪些隊列,拿到這些請求後再把消息發送到Broker中;相對的,Consumer在消費的時候,也會經歷這個流程。
圖釋:部署模型
5、RocketMQ最佳實踐總結
這是咱們在實踐過程的總結,同時咱們也把其中一些普適性的總結做爲阿里中間件技術崗的面試題,目的是幫助你們更深入的理解咱們在設計分佈式消息系統的一些思考和探索。
Q1:分佈式消息系統中,如何避免消息重複?
形成消息重複的根本緣由是:網絡不可靠。只要經過網絡交換數據,就沒法避免這個問題。因此解決這個問題的辦法就是繞過這個問題。那麼問題就變成了:若是消費端收到兩條同樣的消息,應該怎樣處理?
a. 消費端處理消息的業務邏輯保持冪等性;
b. 保證每條消息都有惟一編號且保證消息處理成功與去重表的日誌同時出現。
經過冪等性,無論來多少條重複消息,能夠實現處理的結果都同樣。再利用一張日誌表來記錄已經處理成功的消息的ID,若是新到的消息ID已經在日誌表中,那麼就能夠再也不處理這條消息,避免消息的重複處理。
Q2:順序消息擴容的過程當中,如何在不停寫的狀況下保證消息順序?
1. 成倍擴容,實現擴容先後,一樣的key,hash到原隊列,或者hash到新擴容的隊列;
2. 擴容前,記錄舊隊列中的最大位點;
3. 對於每一個Consumer Group,保證舊隊列中的數據消費完,再消費新隊列,也即:先對新隊列進行禁讀便可;
Q3:分佈式消息系統中,如何對消息進行重放?
消費位點就是一個數字,把Consumer Offset改一下就能夠達到重放的目的了。
Apache RocketMQ部分開發者合影
原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。