京東消息中間件JMQ

http://blog.csdn.net/javahongxi/article/details/54411464java

 

[京東技術]京東的MQ經歷了JQ->AMQ->JMQ的發展,其中JQ的基於關係數據庫,嚴格意義上講稱不上消息中間件,JMQ的存儲是JFS和HBase,AMQ即ActiveMQ,本文說說JMQ。數據庫

JMQ是京東自主研發的一款消息中間件系統,具備高可用、數據高可靠等特性。普遍應用於公司內部系統,包括訂單、支付、庫房等場景。緩存

總體結構服務器

  系統包括服務端、客戶端、管理端與其餘支撐模塊。網絡

  

  

       詳細架構架構


                                                                      AMQ
 

                                                                       JMQ異步

 

       服務端分佈式

  服務端提供了配置信息分發、重試消息管理和消息存儲與分發這三大類功能。每一個服務端實例都具有這三類功能的服務能力,可是在實際部署上這三類功能對應三個不一樣的集羣,對應每個實例功能不疊加。在測試環境和庫房等資源有限的環境下,這三類功能由同一個服務端實例提供服務。性能

  配置信息分發:負責客戶端參數變動時與消息分配的服務端實例變動時通知客戶端。測試

  重試消息管理:主要用於對業務系統臨時處理不了的消息進行存放,而後再按照必定的策略投遞給客戶端處理。能夠提供錯誤緣由、錯誤處理次數等查詢。

  消息存儲與分發:接收生產者投遞的消息,把消息存放在本地磁盤上,消費者從該服務上拉取消息進行消費。

  

  客戶端

  目前只提供了JAVA語言的SDK和支持HTTP協議的proxy,非JAVA語言經過proxy接入。

  管理端

  主要功能有:接入申請、消息元數據管理、重試消息信息查詢、消息發送和消費日誌查詢、服務端狀態信息管理查看、客戶端鏈接信息管理查看等。

  支撐模塊

  主要有報警模塊、任務模塊、歸檔模塊、信息採集模塊等。

  數據可靠性

  針對公司的業務特色,消息服務主要應用於訂單、支付、物流等環節。服務端採用MASTER-SLAVE結構,消息在正常狀況下會同時存放兩份,其中一份會強制持久化到磁盤,磁盤作RAID-5。默認狀況下客戶端採用同步發送,每條消息到達服務端MASTER後會強制刷入磁盤同時並行推送一份到SLAVE上,SLAVE寫入文件系統後不等待強制刷盤就反饋給MASTER。根據不一樣的場景爲了提升服務的可用性,普通級別的消息SLAVE斷開後,該組服務能夠正常使用,當SLAVE鏈接上後又會自動切換爲保存兩份。固然對數據可靠級別高的消息是強制要求數據必須寫兩份纔算成功的。

  服務高可用

  每類消息通常都會分配3組及以上的服務組,每組服務包括一個MASTER和一個SLAVE,固然若是有須要也能夠掛載多個SLAVE。

  客戶端發送消息時,若是其中一組出現故障會重試發送給其餘的組。

  雖然MASTER-SLAVE支持切換,提升服務的可用性,可是在實際生產中MASTER出現故障時會優先採用經過其餘服務組自動接替生產服務的方式,本組服務只提供從SLAVE讀取的方式,而不是讓SLAVE接替MASTER的寫入,避免臨界狀態下丟失消息。

  對要求嚴格順序的消息,不能經過簡單的切換服務組實現,具體實現方式參考《高可用保證消息絕對順序消費的BROKER設計方案》(http://wely.iteye.com/blog/2347823)。

  消費模型

  因爲公司之前有使用基於ACTIVEMQ二次開發的服務,服務端會存放客戶端的消費位置,所以在自主研發JMQ時也延續了這種方式(能夠兼容ACTIVEMQ的客戶端)。可是ACTIVEMQ生產和消費都會操做索引文件,影響性能,JMQ吸收了這個經驗教訓。消費者在消費時按照索引分區順序的消費,消費確認時只須要變動最後確認位置的值,不須要操做索引文件,並且多個消費者共用一個索引文件,各自保存本身的消費偏移位置就能夠了。

  固然在實踐過程當中,因爲一些特殊場景須要,會容許必定範圍內不徹底按照順序消費,可是服務端會記錄已經消費的索引區間。

  

與KAFKA的對比

  JMQ在服務端存儲設計上與KAFKA有一些類似的地方,借鑑了文件按照偏移位置管理、順序追加等特色。不過JMQ的存儲和消費模型有本身的特色:

  消息存放

  JMQ每一個存儲系統只有一個分段存儲的日誌文件,不一樣類的消息按照服務端接收的順序存放在日誌文件中,經過索引程序按照不一樣的消息(主題)分類名異步建立各自的索引,方便消費端獲取消息時快速定位該客戶端所關心的(主題)分類消息。每一個(主題)分類的索引劃分了多個分區,同一(主題)分類的消息分配在多組服務器上的分區數是相同的。每一個索引分區都是以鏈表按照時間序存放消息引用信息。

  消費

  JMQ也採用客戶端主動拉取的方式,可是客戶端不須要協調本身應該從哪一個服務器上獲取消息,服務端會控制好每一個索引分區裏對應的消息在同一時刻只會被一個客戶端線程取走,直到客戶端反饋消費成功或者消費異常,消費異常會被重試程序轉移到重試服務中。若是客戶端長時間沒有反饋信息,達到了超時時間,那麼鎖定的消息能夠被其餘的線程拉取走。

  因爲服務端儲存了每一個消費者消費的位置,所以服務器能夠隨時把已經消費的消息移除走。

主要特性與場景

  發佈與訂閱

  目前公司接入的消息絕大部分都採用這種方式,不一樣類的消息經過主題名進行區分,多個消費者分組之間各自消費一份完整的消息內容,他們看到的消費視圖如出一轍,惟一的區別就是各自消費進度不一樣。

  同一個消費分組內的消費實例只會消費到其中一部分消息,各自鏈接服務端,經過搶佔的方式進行消費。

  場景:

  以訂單消息爲例,訂單系統在訂單的生命週期裏的每一次變動都會發送消息,訂單查詢系統、結算系統、庫房生產系統等都會訂閱該類型的消息,每一個系統拿到一份完整的消息,各自進行處理。

  廣播

  因爲發佈訂閱型的主題消息,若是要獲取一份完整的消息就須要命名一個消費組,若是一類消息每一個消費者實例都須要獲取一份完整的消息,若是還按照主題消息管理那麼就須要爲每個實例命名一個惟一的標識,使用時很是不方便,這時可使用廣播類型的消息,每一個消費廣播消息的實例都會拿到一份完整消息。

  場景:

  分佈式數據庫接入層對應的服務端拓撲信息須要調整,客戶端能夠訂閱一個拓撲變動的廣播消息,提早把須要變動的拓撲信息下發給每一個客戶端備用,當捕捉到拓撲變動的異常後就啓用備用拓撲信息。

  順序消費

  消息的消費會根據服務端接收到的順序,依次推送給客戶端消費,消息若是亂序可能會引發最終結果不正常。

  場景:

  數據庫binglog日誌基於消息系統進行復制,接收到消息的客戶端能夠更新ElasticSearch中的索引信息,能夠修改Redis中的值,同時也能夠基於日誌重放同步數據到一個全量的數據庫中。若是有一條記錄的更新和刪除操做亂序到達消費端,那麼各個系統的狀態將會不一致。

  索引分區並行消費

  默認狀況下,每一個索引分區的消息只可以按照順序依次進行消費,若是索引分區內有一條消息處理比較慢,就會阻塞後面消息的處理,致使消息積壓,影響消息的實時性。爲了解決這個問題,能夠增大索引分區數,可是每一個索引分區對應獨立的文件夾,增大會致使文件夾數目擴大,並且不能根本解決,只是必定程度緩解積壓的消息數目。若是讓單個索引分區內的消息能夠並行的把不一樣區間的消息發送給客戶端處理,這樣若是有某條消息處理慢,服務端能夠把後面的消息交給空閒的客戶端線程去處理,當連續多個區間的消息都消費後再統一合併爲一個大的消費區間,減小服務端須要記錄的已消費區間數。

  場景:

  有一個經過消息派發任務的應用,每一個任務執行時間長短不一,消費端獲取到消息後,根據消息構建任務執行,任務完成後反饋給服務端消費成功。因爲任務執行時間長短不同,所以客戶端的超時時間只能以最長的時間爲參考進行設置,避免任務在執行過程當中因爲超時被其餘線程重複處理。可是當一個時間相對長的任務在執行時,它會佔用該消息所在索引分區被鎖定,後面的任務不能及時派發給空閒的客戶端處理。這時服務端若是啓用索引分區並行消費的特性,就能夠及時的把後面的任務派發給其餘的客戶端去執行,同時也不須要調整索引的分區數。

  事務消息

  事務消息具備回滾的特色,當消息發送給服務端未提交前,若是關聯的其餘業務操做失敗,客戶端能夠主動發起回滾,當回滾或者提交事務消息時網絡故障,消息系統會主動調用客戶端的事務狀態查詢接口,根據客戶端查詢到的事務狀態決定消息是否提交或回滾。這樣就可以保證消息系統和業務系統數據狀態最終徹底一致。利用消息系統會主動查詢不肯定狀態消息的特色,能夠作爲多個資源的事務協調器使用。

  場景:

  變動缺貨商品的庫存信息時,須要更新下單系統中的庫存數,須要通知搜索系統修改商品索引,須要通知網頁緩存系統刷新。各個系統之間因爲各類網絡或服務等緣由形成狀態不一致。可能出現庫存變動了,其餘系統的商品可銷售狀態沒有修改正確,或者出現庫存數據修改失敗,可是其餘系統的商品狀態發生了變動。只能經過一些覈對系統按期的把各個系統中的不一致狀態變動爲一致,加大了開發工做量,並且按期掃描可能引起性能問題。

  經過事務消息,能夠很好的解決這類場景,不會由於網絡不可用等緣由出現系統之間狀態不一致。

  當更新任何一個服務出現故障時就拋出異常,事務消息不會被提交或回滾,消息服務器會回調發送端的事務查詢接口,肯定事務狀態,發送端程序能夠根據消息的內容對未作完的任務從新執行,而後告訴消息服務器該事務的狀態。

  

  做者介紹

  丁俊,有10年工做經驗,目前就任於京東商城雲平臺,爲消息中間件研發小組leader,主要負責公司內部高性能、高可用消息中間件的架構。

相關文章
相關標籤/搜索