“
同程藝龍的機票、火車票癣猾、汽車票敛劝、酒店相關業(yè)務已經(jīng)接入了 RocketMQ,用于流量高峰時候的削峰纷宇,以減少后端的壓力夸盟。
同時,對常規(guī)的系統(tǒng)進行解耦像捶,將一些同步處理改成異步處理上陕,每天處理的數(shù)據(jù)達 1500 億條。
在近期的 Apache RocketMQ Meetup 上拓春,同程藝龍機票事業(yè)部架構師查江释簿,分享了同程藝龍的消息系統(tǒng)如何應對每天 1500 億條的數(shù)據(jù)處理。
通過此文硼莽,您將了解到:
同程藝龍消息系統(tǒng)的使用情況
同程藝龍消息系統(tǒng)的應用場景
技術上踩過的坑
基于 RocketMQ 的改進
同程藝龍消息系統(tǒng)的使用情況
RocketMQ 集群分為 Name Server 和 Broker 兩部分庶溶,Name Server 用的是雙主模式,一個是考慮性能懂鸵,另一個考慮安全性渐尿。在純數(shù)據(jù)的 Broker 分成很多組,每個組里面分為 Master 和 Slave矾瑰。
目前砖茸,我們的機票、火車票殴穴、汽車票凉夯、酒店相關業(yè)務已經(jīng)接入了 RocketMQ,用于流量高峰時候的削峰采幌,以減少后端的壓力劲够。
同時,對常規(guī)的系統(tǒng)進行解耦休傍,將一些同步處理改成異步處理征绎,每天處理的數(shù)據(jù)達 1500 億條。
選擇 RocketMQ 的原因是:
接入簡單,引入的 Java 包比較少
純 Java 開發(fā)人柿,設計邏輯比較清晰
整體性能比較穩(wěn)定的柴墩,Topic 數(shù)量大的情況下,可以保持性能
同程藝龍消息系統(tǒng)的應用場景
退訂系統(tǒng)
這個是我們退訂系統(tǒng)中的一個應用場景凫岖。用戶點擊前端的退訂按鈕江咳,系統(tǒng)調用退訂接口,再去調用供應商的退訂接口哥放,從而完成一個退訂功能歼指。
如果供應商的系統(tǒng)接口不可靠,就會導致用戶退訂失敗甥雕,如果系統(tǒng)設置為同步操作踩身,會導致用戶需要再去點一次。
所以社露,我們引入 RocketMQ 將同步改為異步挟阻,當前端用戶發(fā)出退訂需求,退訂系統(tǒng)接收到請求后就會記錄到退訂系統(tǒng)的數(shù)據(jù)庫里面呵哨,表示這個用戶正在退訂。
同時通過消息引擎把這條退訂消息發(fā)送到和供應商對接的系統(tǒng)轨奄,去調用供應商的接口孟害。
如果調用成功,就會把數(shù)據(jù)庫進行標識挪拟,表示已經(jīng)退訂成功挨务。同時,加了一個補償?shù)哪_本玉组,去數(shù)據(jù)庫撈那些未退訂成功的消息谎柄,重新退訂,避免消息丟失引起的退訂失敗的情況惯雳。
房倉系統(tǒng)
第二個應用場景是我們的房倉系統(tǒng)朝巫。這是一個比較常規(guī)的消息使用場景,我們從供應商處采集一些酒店的基本信息數(shù)據(jù)和詳情數(shù)據(jù)石景,然后接入到消息系統(tǒng)劈猿,由后端的分銷系統(tǒng)、最小價系統(tǒng)和庫存系統(tǒng)來進行計算潮孽。
同時當供應商有變價的時候,變價事件也會通過消息系統(tǒng)傳遞給我們的后端業(yè)務系統(tǒng)揪荣,來保證數(shù)據(jù)的實時性和準確性。
供應庫的訂閱系統(tǒng)
數(shù)據(jù)庫的訂閱系統(tǒng)也用到了消息的應用往史。一般情況下做數(shù)據(jù)庫同步仗颈,都是通過 binlog 去讀里面的數(shù)據(jù),然后搬運到數(shù)據(jù)庫椎例。
搬運過程中挨决,我們最關注的是數(shù)據(jù)的順序性请祖,因此在數(shù)據(jù)庫 row 模式的基礎上,新增了一個功能凰棉,以確保每一個 Queue 里面的順序是唯一的损拢。
雖然 Queue 里面的順序天然都是唯一的,但我們在使用上有一個特點撒犀,就是把相同 ID 的消息都是放在同一個 Queue 里面的福压。
例如,圖中右上角 id1 的消息或舞,數(shù)據(jù)庫主字段是 id1荆姆,就統(tǒng)一放在 Queue1 里面,而且是順序的映凳。
在 Queue2 里胆筒,兩個 id3 之間被兩個順序的 id2 間隔開來了,但實際消費讀出來的時候诈豌,也會是順序的仆救,由此,可以用多隊列的順序來提高整體的并發(fā)度矫渔。
技術上踩過的坑
供應商系統(tǒng)的場景
上圖中彤蔽,一個 MQ 對應有兩個消費者,他們是在同一個 Group1 中庙洼,起初大家都只有 Topic1顿痪,這時候是正常消費的。
但如果在第一個消費者里面加入一個 Topic2油够,這時候是無法消費或消費不正常了蚁袭。
這是 RocketMQ 本身的機制引起的問題,需要在第二個消費者里面加入 Topic2 才能正常消費石咬。
支付交易系統(tǒng)的場景
另外一個是支付交易系統(tǒng)揩悄,這個場景下也是有兩個應用,他們都是在同一 Group 和同一 Topic 下鬼悠,一個是消費 Tag1 的數(shù)據(jù)虏束,另一個是消費 Tag2 的數(shù)據(jù)。
正常情況下厦章,啟動應該是沒問題的镇匀,但是有一天我們發(fā)現(xiàn)一個應用起不來了,另外一個應用袜啃,他只消費 Tag2 的數(shù)據(jù)汗侵,但是因為 RocketMQ 的機制會把 Tag1 的數(shù)據(jù)拿過來,拿過來后會把 Tag1 的數(shù)據(jù)丟棄。
這會導致用戶在支付過程中出現(xiàn)支付失敗的情況晰韵。對此发乔,我們把 Tag2 放到 Group2 里面,兩個 Group 就不會消費相同的消息了雪猪。
個人建議 RocketMQ 能夠實現(xiàn)一個機制栏尚,即只接受自己的 Tag 消息,非相關的 Tag 不去接收只恨。
大量老數(shù)據(jù)讀取的場景
在火車票消費的場景中译仗,我們發(fā)現(xiàn)有 200 億條老數(shù)據(jù)沒有被消費。當我們消費啟動的時候官觅,RocketMQ 會默認從第 0 個數(shù)據(jù)開始讀纵菌,這時候磁盤 IO 飆升到 100%,從而影響到其他消費端數(shù)據(jù)的讀取休涤,但這些老數(shù)據(jù)被加載后咱圆,并沒有實際作用。
因此功氨,對于大量老數(shù)據(jù)讀取的改進方式是:
對于新消費組序苏,默認從 LAST_OFFSET 消費。
Broker 中單 Topic 堆積超過 1000 萬時捷凄,禁止消費忱详,需聯(lián)系管理員開啟消費。
監(jiān)控要到位纵势,磁盤 IO 飆升時踱阿,能立刻聯(lián)系到消費方處理管钳。
服務端的場景
①CentOS 6.6 中 Futex Kernel bug, 導致 Name Server, Broker 進程經(jīng)常掛起钦铁,無法正常工作
解決方法:升級到 6.7
②服務端 2 個線程會創(chuàng)建相同 CommitLog 放入 List,導致計算消息 offset 錯誤才漆,解析消息失敗牛曹,無法消費,重啟沒法解決問題醇滥。
解決方法:線程安全問題黎比,改為單線程
③Pull 模式下重置消費進度,導致服務端填充大量數(shù)據(jù)到 Map 中鸳玩,Broker CPU 使用率飆升 100%阅虫。
解決方法:Map 局部變量場景用不到,刪除
④Master 建議客戶端到 Slave 消費時不跟,若數(shù)據(jù)還沒同步到 Slave, 會重置 pullOffset颓帝,導致大量重復消費。
解決方法:不重置 offset
⑥同步?jīng)]有 MagicCode,安全組掃描同步端口時购城,Master 解析錯誤吕座,導致一些問題。
解決方法:同步時添加 magicCode 校驗
基于 RocketMQ 的改進
新增客戶端
新增 .net 客戶端瘪板,基于 Java 源代碼原生開發(fā)吴趴;新增 HTTP 客戶端,實現(xiàn)部分功能侮攀,并通過 Netty Server 連接 RocketMQ锣枝。
新增消息限流功能
如果客戶端代碼寫錯產(chǎn)生死循環(huán),就會產(chǎn)生大量的重復數(shù)據(jù)魏身,這時候會把生產(chǎn)線程打滿惊橱,導致隊列溢出,嚴重影響我們 MQ 集群的穩(wěn)定性箭昵,從而影響其他業(yè)務税朴。
上圖是限流的模型圖,我們把限流功能加在 Topic 之前家制。通過限流功能可以設置 rate limit 和 size limit 等正林。
其中 rate limit 是通過令牌桶算法來實現(xiàn)的,即每秒往桶里放多少個令牌颤殴,每秒就消費多少速度觅廓,或者是往 Topic 里寫多少數(shù)據(jù)。以上的兩個配置是支持動態(tài)修改的涵但。
后臺監(jiān)控
我們還做了一個監(jiān)控后臺杈绸,用于監(jiān)控消息的全鏈路過程,包括:
消息全鏈路追蹤矮瘟,覆蓋消息產(chǎn)生瞳脓、消費、過期整個生命周期
消息生產(chǎn)澈侠、消費曲線
消息生產(chǎn)異常報警
消息堆積報警劫侧,通知哪個 IP 消費過慢
其他功能:
HTTP 方式生產(chǎn),消費消息
Topic 消費權限設置哨啃,Topic 只能被指定 Group 消費烧栋,防止線上錯亂訂閱
支持新消費組從最新位置消費 (默認是從第一條開始消費)
廣播模式消費進度同步 (服務端顯示進度)
以上便是同程藝龍在消息系統(tǒng)建設方面的實踐。
結尾:
順便在此給大家推薦一個Java方面的交流學習群:957734884拳球,里面會分享一些高級面試題审姓,還有資深架構師錄制的視頻錄像:有Spring,MyBatis祝峻,Netty源碼分析魔吐,高并發(fā)次坡、高性能、分布式画畅、微服務架構的原理砸琅,JVM性能優(yōu)化這些成為架構師必備的知識體系,主要針對Java開發(fā)人員提升自己轴踱,突破瓶頸症脂,相信你來學習,會有提升和收獲淫僻。在這個群里會有你需要的內容 朋友們請抓緊時間加入進來吧