1. 程式人生 > >京東消息中間件JMQ

京東消息中間件JMQ

查詢 其中 協調 tail 利用 網頁緩存 復制 避免 報警

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

[京東技術]京東的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,主要負責公司內部高性能、高可用消息中間件的架構。

京東消息中間件JMQ