雲妹導讀:算法
隨着互聯網的不斷髮展,大數據高併發再也不遙遠,是大部分項目都必須具有的能力。其中,消息隊列幾乎是必備技能。成熟的消息隊列工具備不少,本篇文章就來介紹一款京東智聯雲自研消息隊列工具——JCQ。segmentfault
_JCQ全名JD Cloud Message Queue,是京東智聯雲自研,具備CloudNative特性的分佈式消息中間件。_ JCQ設計初衷即爲適應雲特性的消息中間件,具備高可用、數據可靠性、副本物理隔離、服務自治、健康狀態彙報、少運維或無運維、容器部署、彈性伸縮、租戶隔離、按量付費、雲帳戶體系、受權等特性。服務器
JCQ早在2017年中開始開發1.0版本,2018年11月正式GA上線對外售賣。但1.0版本中Topic受限於單臺服務器限制,知足不了用戶超大規格Topic需求。網絡
所以,咱們在2.0 版本中着重解決擴縮容問題。2019年4月 JCQ 2.0 正式上線,主要新增特性就是Topic 擴縮容能力、熱點Topic在Broker間的負載均衡、熱點Broker的流量轉移。架構
2019年7月, JCQ又作了一次大的架構演進——計算存儲分離 ,大版本號爲JCQ 3.0, 於2019年末上線。計算存儲分離對架構帶來了比較明顯的好處,解決了平常遇到的許多痛點問題。併發
下文將詳細介紹這次演進帶來的優點以及解決了哪些痛點問題:負載均衡
在JCQ2.0中計算模塊與存儲模塊處於同一個進程,升級計算模塊勢必將存儲模塊一塊兒升級。而存儲模塊重啓是比較重的動做,須要作的工做有:加載大量數據、進行消息數據與消息索引數據比對、髒數據截斷等操做。每每修復計算模塊一個小的Bug,就須要作上述很是重的存儲模塊重啓。而在現實工做中,大部分升級工做都是因爲計算模塊功能更新或Bugfix引發的。less
爲了解決這個問題, JCQ3.0將計算模塊、存儲模塊獨立部署,之間經過RPC調用 。各自升級互不影響。以下圖所示:運維
計算節點Broker只負責生產消息、推送消息、鑑權、認證、限流、擁塞控制、客戶端負載均衡等業務邏輯,屬於無狀態服務。比較輕量,升級速度快。分佈式
存儲節點Store只負責數據寫入、副本同步、數據讀取。由於業務邏輯簡單,功能穩定後,除優化外基本無需改動,也就無需升級。
JCQ是共享消息中間件,用戶申請的是不一樣規格TPS的Topic,並不感知CPU、Memory、Disk等硬件指標。因此,JCQ服務方須要考慮如何合理使用這些硬件指標。
JCQ經過容器部署,有多種類型的組件,這些組件對硬件的需求也是多樣化的,其中對資源消耗最多的是計算模塊和存儲模塊。在JCQ2.0版本中,計算模塊和存儲模塊部署在一塊兒,選擇機型時要兼顧CPU、Memory、Disk等指標,機型要求單一,很難與其餘產品線混合部署。即便是同一資源池,也存在由於調度順序,形成調度失敗的狀況。如一臺機器剩餘資源剛好能調度一個須要大規格磁盤的A容器,可是由於B容器先被調度到這臺機器上,剩餘資源就不夠建立一個A容器,那這臺機器上的磁盤就浪費了。
JCQ3.0後,計算節點Broker與存儲節點Store獨立部署,這兩個組件能夠各自選擇適合本身業務的機型,部署在相應資源池中。這樣 JCQ能夠作到與其餘產品混合部署,共用資源池水位,而不用獨自承擔資源水位線。
JCQ3.0中計算節點Broker是無狀態服務,主從切換比較輕量,能在秒級完成故障轉移;且部署時考慮了物理設備反親和,如跨Rack、跨AZ部署。因此,能夠在可用性、資源成本之間作必定的權衡。如可使用M:1方式作高可用冷備,而沒必要1:1的比例高可用冷備,進而達到節省硬件資源的目的。
JCQ 1.0 設計之初就採用Raft算法,來解決服務高可用、數據一致性的問題。Message Log與Raft Log 有不少共同的特性,如順序寫、隨機讀、末端熱數據。因此,直接用Raft Log當成Message Log是很是合適的。
在JCQ演進中咱們也發現了Raft自己的一些性能問題,如順序複製、順序commit、有的流程只能用單線程處理等限制。針對這些問題, 最直接有效的辦法就是擴展Raft的數目、擴展單線程流程數目 ,在必定數量級內,併發能力隨着Raft Group數目的增加,呈線性增加關係,稱之MultiRaft,以下圖所示:
上圖中,每一個StoreNode節點是一個獨立進程,內部有四組邏輯RaftGroup(橙色的節點爲RaftGroup的Leader),各組RaftGroup之間是並行關係,能夠作到Group間並行複製、並行commit。
因爲大量使用了NIO,這些RaftGroup之間能夠共享通訊線程池,擴充RaftGroup數目並不會帶來線程資源線性增加的問題。
在JCQ3.0中,Broker爲輕量的無狀態服務,在主從切換、故障恢復方面相對2.0更爲輕量,自己能更快地恢復對外服務能力 。
同時,Broker將Producer、Consumer的鏈接請求,抽象爲PubTask和SubTask,後文統稱爲Task。Task的概念很是輕量,僅描述Client與Broker的對應關係,由元數據管理器Manager統一調度、管理。轉移Task只須要修改Task的內容,客戶端從新鏈接新Broker便可。
通常來講,Broker的主要瓶頸在於網絡帶寬。Broker按期統計網絡入口流量與出口流量,並上報給管理節點Manager。Manager根據入口流量、出口流量與帶寬閾值進行裁決,發現超過閾值後,經過必定策略將相應的Task轉移到較小負載的Broker上,並通知相應的Producer與Consumer;Producer與Consumer收到通知後,從新獲取Task的路由信息,自動重連到新的Broker繼續進行生產、消費。
設想一個場景,有一個大規格的Topic,建立了n個消費組。消費總TPS是生產總TPS的n倍。增長消費組,會致使消費總TPS線性增加。到達必定消費組規模後,單Broker因爲網卡帶寬的緣由,沒法知足這種高扇出的場景。單服務器是沒法解決這個問題。
在JCQ 3.0 能夠將這些不一樣的消費組對應的SubTask分散到若干個Broker上,每一個Broker負責一部分SubTask,單Broker從Store預讀消息,將數據推送給Consumer。這樣 多個Broker共同完成全部消費組的消息流量,協做一塊兒提供高扇出的能力。
消息中間件很大的特色是:大部分場景下,熱數據都在末端,而回溯幾天以前的消息這個功能是不經常使用的。因此,就有冷熱數據之分。
JCQ 計算節點設計了一層存儲抽象層Store Bridge 能夠接入不一樣的存儲引擎,能夠接入Remote Raft Cluster,或者分佈式文件系統WOS、或者S3。甚者能夠將冷數據按期從昂貴的本地盤卸載到廉價的存儲引擎上。
相對於JCQ2.0,計算節點與存儲節點之間的通訊方式,由接口調用變爲RPC調用,在延遲方面會有必定損失。通過測試,絕大部分延遲都在1ms左右,在大多數場景下犧牲1ms左右的延遲並不會給業務帶來太大的影響。
JCQ將來會主要在多協議兼容,按需自動擴縮容、雲原生等方面演進:
目前JCQ協議爲私有協議,在引導用戶遷移方面有比較大的障礙。後續會抽離JCQ Kernel,外部提供不一樣的協議接入層。方便用戶從其餘MQ接入JCQ。
JCQ是共享消息中間件,但缺乏Serverless自動擴縮容的特性。每逢大促,如618,11.11,服貿會等重要活動。業務方很難預估本身的業務量峯值,或者估計不足,會形成topic限流等問題。如在保證JCQ服務自己能力狀況下,能作到Topic靈活地自動擴縮容,將對用戶有極大的幫助,起到真正的削峯填谷做用。
將來會支持在Kubernetes環境部署與交付,會提供原生的Operator,能快速的部署在K8s環境中,更好的交付私有云、混合雲項目。
歡迎點擊【京東智聯雲】,瞭解開發者社區
更多精彩技術實踐與獨家乾貨解析
歡迎關注【京東智聯雲開發者】公衆號