1. 程式人生 > >讀懂這篇文章,你的阿裏技術面就可以過關了

讀懂這篇文章,你的阿裏技術面就可以過關了

再處理 code topic ash 接口 這一 分布式消息 mage 例如

摘要: 在美國的大學課程中,101是所有課程中的第一門,是新生入學後的必修課程。阿裏巴巴中間件技術專家劉振東在上周的Apache RocketMQ開發者沙龍北京站的活動上,進行了主題為《ApacheRocketMQ 101》的分享,幫助開發者從0開始學習 Apache RocketMQ,除了一些基礎的入門內容外,還有很多是在社區未發表過的個人所感所悟,首次對外分享。

在美國的大學課程中,101是所有課程中的第一門,是新生入學後的必修課程。阿裏巴巴中間件技術專家劉振東在上周的Apache RocketMQ開發者沙龍北京站的活動上,進行了主題為《ApacheRocketMQ 101》的分享,幫助開發者從0開始學習 Apache RocketMQ,除了一些基礎的入門內容外,還有很多是在社區未發表過的個人所感所悟,首次對外分享。分享內容包括RocketMQ的起源、RocketMQ概念模型、存儲模型、部署模型和最佳實踐總結,其中最佳實踐的內容是阿裏中間件技術類崗位的必考面試題。

技術分享圖片

嘉賓介紹:劉振東,阿裏巴巴中間件技術專家,Apache RocketMQ PMC/Committer,2016年中間件性能挑戰賽亞軍,具有豐富的分布式系統設計和優化經驗,目前負責Apache RocketMQ新航道探索和創新。

一、RocketMQ的起源

通常,每個產品的誕生都源於一個具體的需求或問題,RocketMQ也不例外。起初,產品的原型像一個巨石,把所有需要實現的程序和接口都羅列到一起。但隨著公司業務的發展,所有的系統和功能都在這個巨石上開發,當覆蓋幾百上千名開發人員的時候,瓶頸就出來了。這時候,就需要我們把系統進行分解。

技術分享圖片

圖釋:巨石 -> 分布式

分解後,就出現了上圖中的分布式架構,這類架構最大的特點就是解耦,而RocketMQ的異步解耦意味著底層的重構不會影響到上層應用的功能。RocketMQ另一個優勢是削峰填谷,在面臨流量的不確定性時,實現對流量的緩沖處理。此外,RocketMQ的順序設計特性使得RocketMQ成為一個天然的排隊引擎,例如,三個應用同時對一個後臺引擎發起請求,排隊引擎的特性可以確保不會引起“撞車”事故。

二、RocketMQ的概念模型

對於任何一款中間件產品而言,清晰的概念模型是幫助開發者正確理解使用它的關鍵。從RocketMQ的概念模型來看:Topic是用於存儲邏輯的地址的,Producer是信息的發送,Consumer是信息的接收者。

技術分享圖片
圖釋:最基本的概念模型

這只是一個基礎的概念模型,在實際的生產中,結構會更復雜,例如我們需要對中間的Topic進行分區,出現多個有關聯的Topic,再如同一個信息的發送方會有多個訂閱者,同一個需求方會有多個發送方,出現一對多、多對一的情況。

技術分享圖片
圖釋:擴展後的概念模型

上圖就是對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這一臺設備上。

三、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端的消費情況進行隊列定義。

四、RocketMQ的部署模型

在實際的部署過程中,Broker是實際存儲消息的數據節點,Nameserver則是服務發現節點,Producer發送消息到某一個Topic,並給到某個Consumer用於消費的過程中,需要先請求Nameserver拿到這個Topic的路由信息,即Topic在哪些Broker上有,每個Broker上有哪些隊列,拿到這些請求後再把消息發送到Broker中;相對的,Consumer在消費的時候,也會經歷這個流程。

技術分享圖片
圖釋:部署模型

五、RocketMQ最佳實踐總結

這是我們在實踐過程的總結,同時我們也把其中一些普適性的總結作為阿裏中間件技術崗的面試題,目的是幫助大家更深刻的理解我們在設計分布式消息系統的一些思考和探索。

Q1:分布式消息系統中,如何避免消息重復?

造成消息重復的根本原因是:網絡不可靠。只要通過網絡交換數據,就無法避免這個問題。所以解決這個問題的辦法就是繞過這個問題。那麽問題就變成了:如果消費端收到兩條一樣的消息,應該怎樣處理?

a. 消費端處理消息的業務邏輯保持冪等性;

b. 保證每條消息都有唯一編號且保證消息處理成功與去重表的日誌同時出現。

通過冪等性,不管來多少條重復消息,可以實現處理的結果都一樣。再利用一張日誌表來記錄已經處理成功的消息的ID,如果新到的消息ID已經在日誌表中,那麽就可以不再處理這條消息,避免消息的重復處理。

Q2:順序消息擴容的過程中,如何在不停寫的情況下保證消息順序?

  1. 成倍擴容,實現擴容前後,同樣的key,hash到原隊列,或者hash到新擴容的隊列;

  2. 擴容前,記錄舊隊列中的最大位點;

  3. 對於每個Consumer Group,保證舊隊列中的數據消費完,再消費新隊列,也即:先對新隊列進行禁讀即可;

Q3:分布式消息系統中,如何對消息進行重放?

消費位點就是一個數字,把Consumer Offset改一下就可以達到重放的目的了。

技術分享圖片

Apache RocketMQ部分開發者合影

原文鏈接

本文為雲棲社區原創內容,未經允許不得轉載。

讀懂這篇文章,你的阿裏技術面就可以過關了