日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

高性能平台设计—美团旅行结算平台实践

發布時間:2024/7/5 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高性能平台设计—美团旅行结算平台实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文根據第23期美團技術沙龍演講內容整理而成。

背景

美團酒旅有很多條業務線,例如酒店、門票、火車票等等,每種業務都有結算訴求,而結算處于整個交易的最后一環不可缺少,因此我們將結算平臺化,來滿足業務的結算訴求。結算平臺通過業務需求以及我們對業務的理解,沉淀了各種能力并構建了豐富的能力地圖。

我們將業務的發展歸納為幾個階段,例如業務孵化階段,快速搶占市場擴大覆蓋階段,市場穩定后急需盈利階段,國內業務穩定后的國際化階段,業務發展的各個階段都能在結算平臺找到相應的能力支持。業務孵化階段講究的是低成本試錯,我們將結算的核心流程,賬單->付款->發票等模塊平臺化,新業務接入只需要5~10天。我們的預付款結算、分銷結算、階梯返傭結算、地推結算能力能快速的幫業務搶占市場實現盈利。

我們的匯率管理,多幣種,多時區結算能力可以助力業務開展海外市場。當前結算平臺支持美團酒旅4個事業部、17條業務線,涵蓋境內、境外等業務的線上結算,后邊我主要介紹下對賬平臺的實踐即賬單的實踐。

對賬平臺的重要性

對賬是平臺化的第一環,它需要算清楚商家和美團的收益明細,后續的付款,發票等,都是基于對賬進行開展的。同時它需要對接酒旅的各個訂單中心,不同業務的訂單具體實現和業務流程不同,不同的業務對賬規則和時機也不相同,同時對賬每天需要處理數百萬條交易明細。

如何解決訂單、對賬層面的差異?每天處理數百萬交易明細,如何高效準確的處理這些數據?17條業務線如何做隔離、定制、個性化擴容?其中面臨了很多挑戰,這也是為什么要講對賬的原因。

早期的系統實踐及優化

早期系統實踐

賬單的生成邏輯主要分兩部分:

  • 通過訂單中心,供應鏈分別獲取交易數據、商家基本信息、結算規則。
  • 基于交易數據、商家信息、結算規則生成對賬單。
  • 早期結算系統基于酒店業務實現,有很重的業務特性,模式是期末模式。比如賬期是6月1日到6月30日,會在7月1日時執行以上兩步操作,結算需要關注業務邏輯。這種模式存在很多問題,比如業務是靈活多變的,結算往往7月1日時才能感知到業務的變化,同時需要處理整個月的交易數據,這樣就需要結算有很強的機動能力應對變化,很強的數據處理能力。

    早期的系統架構和實現有一些問題,比如采用單線程,Pull的模式去獲取數據,生成賬單,雖然部署了很多臺Server,但其實同一時刻只有一臺Server在工作,有嚴重的資源浪費,同時數據處理效率較低。本應7月1日進行結賬,因為業務變更,數據處理效率低,出賬往往會拖到7月底,商家體驗非常差。當時除了酒店業務之外,門票、火車票業務都處于孵化階段也有結算需求,比較緊迫的任務有兩個,一個是快速的解決酒店結賬不及時的問題,另外一個是支持新業務的結算需求。所以當時的策略是,優化老系統讓酒店業務平穩運行,搭建新的結算平臺支持新業務的孵化。

    按時結賬優化

    優化的策略有兩點:

  • 和上游約定業務變更流程,需要提前告知結算,結算提前做系統升級。
  • 結算提高數據處理能力。
  • 提高數據處理能力思路是:單線程改多線程,串行改并行,單機計算改分布式計算。具體做法是:商家ID維度用取模的方式分片,通過配置將不同的分片配置到不同的Server,同時每個Server上有單獨的線程池,可以在商家ID的維度并行獲取數據,處理賬單。這樣雖然能快了起來,但是它又引入了一些新的問題。

    比如單點問題,如果Server2宕機了,配置不具備自動Rebalance的能力,就需要結合報警來人工處理,運維壓力會變大。如果繼續提升處理能力,就需要更多的數據分片,更多的Server資源,這時需要去重新處理分片和配置的邏輯,雖然它是可擴展的,但是并不靈活。

    資源利用率波動也比較大,在7月1日處理整個月的數據,資源利用率(藍線),在月初的時候最高,平時的時候基本上接近于0。比較健康的資源利用率,應該像黃線一樣,雖然會有業務的峰值,但是整體上來看是趨于平穩的。如果是藍線這樣的資源利用,就會導致訂單系統、結算系統、DB,都需要按照業務的峰值來部署,會產生資源浪費,最后我們在速度和資源的使用上求一個平衡,通過這些優化做到了及時結賬。

    但還遺留了如下問題:

  • 單點問題。
  • 提升數據處理效率產生資源浪費。
  • 系統處理能力可擴展,但是不夠靈活優雅。
  • 業務邏輯和結算邏輯嚴重耦合。
  • 對賬平臺化及高性能實踐

    上邊這些問題在對賬平臺化時都需要解決,尤其是邏輯耦合問題,如果不解決,后續對接的業務越多,步伐越沉重,最終會拖慢業務的發展。解決這個問題需要優化結算系統的業務架構,需要抽象一套訂單模型,商家模型,計算規則模型,這些模型要足夠通用,在兼容各個業務差異同時又要有一定的擴展和定制能力,模型的抽象是平臺化的關鍵。

    業務架構優化

    訂單模型抽象

    如上圖訂單狀態機所示業務非常復雜,狀態變更的軌跡訂單如果不記錄清楚,事后結算時很難回溯出來當時的交易情況。結算關注金錢變更和結算時機因此需要分析訂單的狀態機,過濾出結算要關注的狀態,在上圖中我用藍色表示,業務變更會導致狀態機的設計變更同時會影響過濾邏輯,這個是業務和結算耦合的關鍵點,不同的業務玩法不一樣,狀態機也不一樣,過濾邏輯完全無法復用。

    結算抽象了一組統一的訂單狀態來描述訂單的整個生命周期:支付成功,使用前退、使用、取消使用、使用后退。它們所代表的含義如字面上一樣,簡單便于理解,每來一條業務線,將訂單的原始狀態和結算抽象的狀態做映射,就能解決訂單層面的差異。以酒店為例:預定周日晚上的酒店,周四行程變更無法入住,周五找客服退款,客服退款成功,這個對應使用前退,客服退款在一些特殊的場景也會對應到使用后退,最終解決了訂單狀態層面的差異。

    計算規則抽象

    狀態過濾出來后要計算這筆交易商家和美團分別的收入和支出是多少。如上圖所示酒店要計算收入和支出需要訂單的基礎信息、間夜信息等因子,這些因子可能散落在各個數據表中,收集和計算非常復雜,業務變更會導致計算因子和計算邏輯變更,不同業務計算因子不相同,所以它很難復用。

    結合前邊抽象的訂單狀態,以及結算關注的收入和支出,我們抽象出來一套資金語言,它由5種狀態+資金描述組成,所有訂單通用,從而做到結算和訂單的徹底解耦。例如“支付成功狀態”、“使用狀態”對應收入;“使用前退狀態”、“取消使用狀態”、“使用后退狀態”對應支出。資金描述包含具體的收入、支出金額,以及收入、支出的具體描述。商家收入= 單個進價 * 購買數量 - 商家承擔促銷;美團收入=總賣價 - 總進價 - 美團承擔促銷,最終商家的收入=總收入-總支出,通過資金語言能推算出收入和支出的具體由來。

    資金語言是結算和訂單的標準協議,不管什么樣的業務,數據結構和業務流程怎么設計,都按照標準協議來,只要協議不變,不管是訂單變化還是結算變化都不會相互影響,訂單和結算也就具備了獨立演進的可能。

    商家信息抽象

    商家關聯的信息有很多,例如合同、資質等等,但是結算關注的是這個商家的身份信息,我們將這類信息抽象為商家的基本信息,同時也需要關注商家的對賬和付款規則,我們將這類信息抽象為結算信息,結算信息包含對賬和付款的維度和時機。對賬和付款不同業務維度和時機都不相同,我們將這些信息抽象出來,只要新業務維度和時機在這些規則之內,就能很好的復用,最終解決了供應鏈層面的差異。

    對賬平臺設計

    如上圖所示。

    老架構

    數據獲取采用PULL模式,如果上游故障會導致無法獲取數據,從而影響賬單計算,重度外部依賴。不管是數據獲取還是計算賬單都需要穿透兩層業務邏輯,業務邏輯嚴重耦合難以復用。

    新架構

    抽象了資金語言,商家信息,結算規則,標準化了接入規范,數據接入采用PUSH的模式,業務產生了交易,新簽約了商家只要能將數據按時的PUSH過來就能按時結賬,結算被動接收數據,輕度外部依賴。新架構設計了適配層,用來做業務數據和標準協議的適配,適配層邏輯結算和業務都可以做,但是考慮到業務側的同學更了解業務,業務變更自己修改適配層不需要找結算排期更靈活,我們將適配層交給業務團隊來做,每來一個新業務只需要一個小的適配塊,就能快速接入。通過抽象的模型和標準協議,對賬平臺做到了數據聚合統一,計算規則統一,數據模型統一,從而達到了高度復用,結算和業務解耦。歷史上酒店和旅游訂單發生過多次重構,對結算基本無影響。人員也得到了高度復用,當前對賬模塊只有4名RD對接了17條業務線。

    對賬平臺具體實踐

    對賬平臺實踐主要關注如下四點:

  • 實時性設計,我們希望訂單產生交易商家立刻能看到自己的收入,同時希望解決資源利用率的問題。
  • 高性能設計,每天數百萬交易明細,每個賬期需要處理數百萬賬單,怎么保證這些數據的生產和計算準確、高效?
  • 隔離和定制,結算對接了17條業務線,每個業務體量不同,業務邏輯也會有一定的差異,多個業務之間怎么隔離?怎么做到業務之間相互不影響?
  • 可擴展性設計,業務快速規模化以后,系統的處理能力可擴展,滿足業務的發展預期。
  • 實時性設計

    數據接入

    訂單產生交易,將交易轉為資金語言,通過消息中間件(Mafka)實時的推送給結算,結算只做必要的校驗,完成后數據落到MySQL中,此時數據的狀態是未處理,這一步設計了ACK機制保證數據不丟。落庫后會給賬單引擎發一個消息,說有一條數據要處理了。數據的接入和賬單引擎的計算做了分離,數據的接入非常快,基本延遲在毫秒級別。

    賬單引擎

    賬單引擎會在6月1日生成6月1日到6月30日的空賬單,數據經過聚合規則,進入到相應的賬單,同時觸發賬單計算規則,完成賬單的實時計算。一些特殊的情況例如數據產生在6月1日,結算日期是6月2日,會將這個消息轉發到Mafka的延遲隊列,在6月2日重新消費這條消息,數據處理成功后,數據的狀態變更為已處理。

    賬單引擎的補償和監控機制是通過對數據的狀態控制來實現的,例如6月1日到30日,商家A一共產生了1萬條交易明細,已處理的數據只有8千條,那剩下的2千條要么就是在途,要么就是消息丟了,或者系統Bug,會有一定的監控和補償策略來保證數據的完整性,賬單引擎處理具體的交易明細延遲在秒級。

    高性能設計

    提高賬單的處理效率需要從兩個維度出發:

  • 每天要處理對賬單數量大概在百萬級別,一個一個處理是非常慢的,所以要盡可能在對賬單維度提高并發度。
  • 每個對賬單要接收的流水數量也不相同,可能單對賬單同一時刻的并發度會很高,所以要盡可能提高單對賬單的并行度。
  • 提高高并發設計

    我們通過消息中間件Mafka來提高并發度,在Topic的維度拆分多個Partition,不同的ConsumerGroup配置不同的消費線程數,Mafka基于滑動窗口機制實現了多線程消費同一個Partition的數據,所以可以做到并發度= Partition數量 * 消費線程數,在數據處理上做了冪等性保障,能確保數據的正確處理。從架構上來看除了DB之外全鏈路無單點,比如某個Server掛了以后,通過Mafka的Rebalance機制,將Partition自動分配給別的Server,消除了Server層面的單點問題。

    提高并行度設計

    單個對賬單包含了多條交易明細,賬單的總金額是多條交易明細金額的累加,并發度上來以后,會產生線程安全性問題,怎么保證賬單總金額的數據準確性?常規實現:

    //事務保證原子性 try {Lock lock = distributedLockManager.getReentrantLock(statementId);//賬單維度鎖lock.lock(); //獲取鎖,存在阻塞insert(detail);//寫入明細compute(statementId);//計算賬單 } finally {lock.unlock();// 釋放鎖 }

    如上邊的偽代碼所示,要有一個事務保證明細寫入和賬單金額計算的原子性,其次是獲取分布式鎖,寫入明細,計算賬單,因為鎖的緣故單賬單的并發度是N,并行度是1,并行度低的結果會導致消息出列變慢,單個賬單的處理效率變低,有了事務也會有一定的性能開銷。怎么提高并行度,怎么減少事務的粒度成為單賬單維度高性能計算的關鍵問題。

    我們對商家的操作習慣進行了分析,商家更關注賬單的總金額,不太關注交易明細,只要能保證賬單總金額的計算相對實時,最終是正確的就好了,所以我們將賬單明細的寫入和賬單的計算做了分離,不保證原子性,這樣就省去了事務的性能開銷,賬單明細只管寫入,不用關注賬單的計算,全程不顯式加鎖,提高了明細的寫入效率,Mafka的消息出列也變的更快。

    另外一方面,我們為每個賬單抽象了寫入時間軸,通過寫入時間推算賬單的計算時間。假設我們配置賬單的延遲計算窗口為3秒,賬單A在第2秒和第4秒的寫入都會在第4秒合并成一次計算,賬單B在第3秒和第5秒的寫入都會在第5秒合并成一次計算,賬單沒有明細寫入不觸發計算。這樣在商家的視角賬單總金額會有最多3秒鐘的延遲,從體驗上來看也是完全可以接受的。

    每個賬單的寫入時機不同,每個賬單的計算時機也不同,所以可以將多個賬單的計算時機隨機相對均勻的分散開,減輕DB的壓力,每個賬單在最終結賬時都會有一次終極的兜底計算,防止計算異常。最終做到了無事務、無鎖,單賬單并行度也從1變成了N,提高了單賬單的處理效率。

    提高讀性能

    場景一

    以前邊所提賬單的計算為例,核心語句如下:select sum(金額) from 賬單明細表 where 賬單ID = X,當數據規模在億級怎么保證效率?我們除了在賬單ID維度增加索引以外,還通過分表,數據備份的方式盡可能保證單表里數據量不至于太大,來提高處理效率。

    通過中間件atlas,賬單明細按照賬單ID取模的方式進行分表,保證同一個賬單明細在一張表中,雖然會有一定的數據分布不均勻的問題,但是在很大程度上也能避免同一個表過于龐大,從而提高的SUM操作的性能。

    賬單明細有一個特性是不可變更,我們的業務場景是寫多\讀少,HBase也支持水平擴展,很適合做數據備份,所以我們通過Databus將數據同步到HBase中一份,還設計了一個程序定期的去對比MySQL和Hase的中的數據,賬單結賬后就不需要SUM操作了,經過一定的周期以后可以將MySQL中的明細做清除,釋放MySQL的存儲空間,只要一開始賬單明細容量預留的足夠大,通過這樣的策略基本上能避免后續業務規?;髷U容產生的數據遷移問題,但是會有另外一個問題是需要定期處理數據庫因為刪除操作而產生的表空間空洞問題。

    場景二

    數據完整性校驗,保證一個商家的一個賬單數據是完整的,核心語句如下:select count(1) from 流水表 where 業務線=酒店 and 商家ID=1 and 流水時間 > X and 流水時間 < Y and 數據狀態 = 未處理 。數據量在億級如何保證效率?

    我們將交易明細做了冷熱隔離,將已結算的數據備份到備庫中,未處理的數據整體量級在10萬條以內,主要是不到結算時機或者在途的一些數據,在配合一些索引,整體的處理效率是非常高的。

    DB讀寫未來的規劃

    未來會根據業務和商家分庫,前期采用多庫,少物理機的模式部署,避免資源浪費。當物理機容量不足時按需遷移到新的物理機,整個過程只會較短時間的block寫,對讀無影響,遷移較為方便,目的是為了消除DB單點問題,故障只影響部分商家,部分業務。另一方面通過分庫,多物理的機的形式也能提高DB層面的讀、寫能力。

    隔離和定制

    結算平臺對接了17條業務線,不同業務體量不同,所需要的系統容量也不同,怎么定制化擴容?業務也會有一些特殊流程和邏輯怎么做邏輯定制?怎么做到A業務線故障不影響B業務線?

    如上圖,我們根據一定的路由規則,將數據灌到不同的Topic中,酒店體量比較大可以針對酒店Topic配置較多的Partition,火車票體量沒有酒店大可以配置相對少的Partition,針對不同的消費組配置不同的消費線程數,從而做到給不同業務分配不同的系統容量。賬單引擎由通用邏輯+定制邏輯實現,定制邏輯以消費組維度做隔離,每個消費組配置單獨的開關,當業務產生異常需要暫停結算時,關掉開關,對其他業務無影響。Server集群公用,通過Mafka的機制根據Topic和Partition自動劃分資源,最終做到個性化擴容,多業務隔離相互不影響。

    整體擴展性設計

    主要分三層:

  • 第一層是消息中間件,可以通過拆Topic、Partition,增加消費線程數,來提高整體的并發度。
  • 第二層是通過程序優化,增加機器,從而提高并行度和整體的處理能力。優化程序如前邊提到的減少鎖和事務,分散數據壓力等手段。
  • 第三層DB這塊可以通過分庫、分表、冷熱隔離,提升整體的讀寫能力。
  • 整體的擴展是需要多層進行配合的,比如Mafka的并發度特別高,Server數也特別多,但是只有一個DB,DB可能就是一個瓶頸,那就需要在DB的層面做一些擴展和優化。

    最后呈現出的效果是,數據接入基本上延遲是在毫秒級別,對賬單是實時對賬單,產生交易后商家立刻就能在賬單上看到收入明細,對商家來說體驗非常好,對接了17條業務線,從不交叉影響。

    作者簡介

    • 子鑫,2015年7月加入美團,目前是酒旅結算平臺技術負責人。之前在京東和去哪兒從事訂單交易相關的一些工作。

    招聘信息

    結算平臺目前在招Java后臺研發工程師,感興趣的可以投遞個人簡歷到郵箱:zhangzixin03#meituan.com,歡迎您的加入。

    總結

    以上是生活随笔為你收集整理的高性能平台设计—美团旅行结算平台实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。