订单失效怎么做的_此招一出,数据库压力降低90%,携程机票订单缓存系统实践...
生活随笔
收集整理的這篇文章主要介紹了
订单失效怎么做的_此招一出,数据库压力降低90%,携程机票订单缓存系统实践...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文轉自 | 攜程技術
作者簡介
Chaplin,攜程資深PMO,平時喜歡解決系統相關的問題,包括但不限于分布式/大數據量/性能/體驗等,不畏復雜但更喜歡簡單。本文旨在分享攜程機票后服務訂單處理團隊,在構建機票訂單緩存系統過程中的一些思考總結,希望能給大家一些啟發或幫助。通篇分為以下七大部分:背景,瓶頸,選型,架構,方案,優化,總結,文章概要如下圖:一、背景
近些年隨著攜程機票業務的不斷發展,用戶量和訂單量也穩定地增長,再加上用戶訪問入口的多樣性、機票的有效期特別長等特征,導致查詢流量不斷增長。這些,給基于強依賴訂單數據庫的訂單查詢系統帶來了不小的壓力。不僅業務上帶來的流量壓力,技術改造也帶來了更多的流量,如微服務化的推進、機票前后臺訂單業務解耦,不可避免地使得訂單查詢系統被依賴程度進一步提高。而且我們沒有使用類似GraphQL 的技術,之前的前后臺服務直連數據庫,現在使用查詢API,沒有高度定制化產生了數據冗余,帶來額外的查詢壓力。作為典型的用戶訂單詳情查詢服務,承受著越來越重的壓力,峰值時期訂單詳情查詢QPS數倍于同期訂單TPS。為了保障用戶的使用體驗,支持機票業務的持續發展,保證機票訂單查詢系統的穩定高效,構建和不斷升級機票訂單查詢系統,自然成為重要且緊急的事情。二、瓶頸
大部分應用系統的瓶頸都會出在比較慢的地方,如外部資源及磁盤IO或數據庫,訂單系統的瓶頸顯而易見,重復高頻的訂單數據訪問,最終帶來的是訂單數據庫訪問的壓力。盡管之前通過數據庫主從復制、讀寫分離的手段,一定程度上緩解數據庫的壓力。但是從節點的增加無疑會帶來一些不得不考慮的問題,包括數據同步時的AG延遲問題,數據庫服務器的運維成本等。不僅局部優化有瓶頸,而且我們一直認為局部的優化,不如總線級別的優化來的更有效率,數據庫總線跟內存總線對于訂單系統數據存取速度的提升并不是一個級別。基于以上種種,機票訂單后處理團隊,決定構建一套相對完整的基于內存數據緩存體系,不僅用于緩解機票訂單數據庫的訪問壓力,也用來提高訂單查詢服務的穩定性和容災能力。三、選型
目前各種類型的緩存都活躍在成千上萬的應用服務中,還沒有一種緩存方案可以解決一切的業務場景或數據類型,我們需要根據自身的特殊場景和背景,選擇最適合的緩存方案。目前業內用來做緩存的,通常主要有以下幾種:Memcache、Redis,MongoDB。關于幾者的優劣對比網絡上也有不少的相關文章,這里不再詳細列舉。選型并非是一個固定不變的標準,雖然系統設計沒有銀彈,但是路就在腳下,我們必須要結合自己的業務場景及運維能力做出綜合判斷(取舍),這里說明一下我們關注的點。(1)故障快速恢復,機票訂單的查詢服務面臨的QPS較高,又是許多上層應用服務的依賴項,由于業務比較核心,所以數據安全問題必須考慮。因此第一要求故障快速恢復,攜程的Redis部署是多組多實例多機柜,完全滿足需求。(2)性能要好,機票訂單數據的查詢,超過92%的場景都是根據訂單號的查詢,場景比較單一,很少有使用索引條件的緩存查詢需求。單一機票訂單的數據量并不多,所以要求的緩存性能越高,用于查詢集群機器線程池效率越高,整個查詢集群機器越少,硬件成本及維護成本才會變低。(3)輸出穩定,緩存性能穩定,查詢集群的線程池運行越穩定,尖刺就會少,整個系統穩定性會提高。我們綜合機票訂單業務場景,采用了Redis作為機票訂單緩存的存儲介質。因為Redis的部署特性,要求我們的單個實例不能太大,為了避免實例太大,我們前期做了很多工作,比如容量評估及預測,通過拆分+壓縮來規避容量問題。四、架構
在攜程機票的微服務化架構體系之下,按照業務層級的不同,后臺服務呈現層次化調用的樹狀結構。比如訂單詳情服務輸出機票訂單的狀態、價格、航班、乘客等各類基本信息,同時依賴于機票的改簽業務、退票業務、航變業務,支付業務等提供的查詢服務,而這些獨立的子業務與訂單詳情服務本身一樣需要訂單基本信息數據作為業務支撐。為了避免循環依賴,需要把訂單基本數據查詢業務剝離出來,單獨提供底層數據訪問服務,同時支撐不同業務模塊。所以機票訂單后服務團隊依據服務的層次設計了兩級緩存的體系,如下圖所示。(1)一級緩存一級緩存是訂單查詢服務響應結果級別的緩存。訂單查詢服務作為一系列核心服務,支撐了不同前端渠道的訂單查詢請求,包括APP,Online、H5等,同時也支持后臺訂單處理的各個環節業務對訂單數據的查詢需求。訂單查詢服務的請求QPS很高,對同一個訂單的請求在1秒之內有時會達到十幾次。對于許多業務場景來說,1秒的時間內訂單的數據基本不會發生變化,因此完全可以將該訂單的整個訂單查詢服務響應結果緩存起來,設置秒級別的過期時間。這樣做一方面能夠提高服務的響應速度,另一方面能夠減少對底層數據庫服務的訪問,降低數據庫的壓力,預防意外的或者惡意的流量沖擊。(2)二級緩存二級緩存是針對訂單數據庫熱點數據表的數據的底層緩存。根據對機票訂單業務的梳理和對數據庫數據表的訪問頻率的統計,我們篩選出了80+的熱點機票訂單數據表,對每個表的數據建立緩存,并提供數據查詢服務接口。這樣一來,將不同業務方與訂單數據庫解耦,統一的數據訪問服務層更有利于統一建立和管理數據緩存系統,提高緩存數據的使用效率。同時對底層數據庫的垂直拆分和水平拆分,做到數據使用的業務方無感,提高了系統的擴展性。五、方案
緩存數據一致性的實現方案,一般可以分為兩大類:主動式和被動式緩存。主動式緩存就是提前將可能訪問到的數據加載到緩存中,然后設置過期時間,周期性刷新。等到需要查詢數據的時候,可以優先命中緩存。這種方式比較適合于數據量不大,變化不頻繁的場景。被動式緩存是指每次查詢時先從緩存中查詢數據,沒有則查詢底層數據庫,然后把數據庫的查詢結果加載到緩存,并設置一定的過期時間。數據過期后,當再次遇到查詢請求時重復前面所說的過程。被動式緩存具有延遲加載的特性,也就是只有真正被訪問過的數據才會被加載到緩存中,能夠更有效的利用緩存數據。機票訂單的數據熱度具有階段性,用戶訂單成交的前后階段訂單查詢頻率較高,用戶的歷史訂單查詢頻率就很低了。因此我們采用被動式加載的方案,隨著時間的推移,老的歷史訂單數據會自動逐漸過期,新的訂單數據被逐漸加載。緩存數據的總量保持平穩,同時避免了老舊數據的清理。分布式緩存架構的數據一致性是個難點,這也是訂單處理團隊一直在努力思考并解決的重中之重。緩存數據意味著數據的變更在過期時間之內是被忽略的,可能與實際的數據庫數據有一定差異。一般情況下,一種方案是盡量設置較短的過期時間,以使緩存數據盡快與數據源同步。但是較短的過期時間帶來的是緩存命中率的大大降低,削弱了緩存數據的效果。為了解決數據一致性問題,我們設計了兩套方案來更新緩存數據,保證緩存數據的實時性。兩套方案相互補充,避免其一短暫失效而產生一致性問題。方案一的思路是掃描數據庫的數據變化記錄,比如數據表里面的數據更新時間戳,或者訂閱數據庫的binlog記錄。當掃描到數據變化時,刪除對應的緩存數據。方案二的思路是借助于攜程的消息通知平臺服務。在訂單處理流轉的各個重要環節,會有消息事件產生。通過訂閱這些消息,能夠感知到訂單數據的變化,并且通過對不同消息的影響數據范圍可以精準地配置緩存數據更新。兩套方案的并行實施,保證了緩存數據的延遲控制在了100毫秒以內。緩存的構建過程中,我們也遇到幾個必須慎重處理的關鍵點:緩存穿透、緩存擊穿、緩存雪崩。(1)緩存穿透的解決方案(空標記)緩存穿透是指,在數據存儲系統中不存在的記錄,不會被存儲到緩存中。這種記錄每次的查詢流量都會穿透到數據存儲層。在高流量的場景下,不斷查詢空結果會大量消耗數據查詢服務的資源,甚至在惡意流量攻擊下可能拖垮數據庫系統。以機票訂單為例,有些訂單購買了保險,也有的訂單沒有購買保險的記錄。沒有保險產品的訂單每次查詢時都會從數據庫中查到空的結果,命中不了緩存,消耗了大量的Batch Request。針對這種情況,我們采取了設置空標記的措施,針對查詢正常返回但是記錄為空的數據,將特定的空標記寫入緩存,避免了這部分流量穿透到數據庫。(2)緩存擊穿的解決方案(分布式鎖)緩存擊穿是指,對于一個熱點KEY,在其失效的瞬時,如果有大量的對這個KEY的請求,都會到達數據庫。我們通過分布式鎖的方式,在緩存數據失效的時刻,僅允許單一請求讀取數據庫數據并加載到緩存。(3)緩存雪崩的解決方案(隨機時間差)緩存雪崩是指,在同一時間有大量緩存一起失效。我們使用了一個簡單有效的方法,對不同的緩存數據設置過期時間時,采用不同的時間,比如增加一個小的隨機值。此外,由于不同訂單處理過程中的消息發生時間不同,而訂單處理過程一般會有等待隊列,處理時間會有差異,也降低了緩存同時失效的風險。六、優化
做完以上這些,應該算個及格的緩存系統,但是我們相信更優秀的系統是通過一步步的迭代及演進出來的。機票訂單緩存系統的優化,必然要與機票訂單的自身特征深度吻合,高度定制化,才能發揮更加有效的作用。我們通過對攜程機票訂單以及機票用戶行為的大量數據分析,制定了一些針對性的優化措施。(1)全天候分段緩存過期策略(按時間)根據對機票訂單系統每日實時訂單量數據的分析,實時訂單量呈現雙駝峰的形態,上午9點到11點以及下午1點到4點之間這兩個時間段內,訂單量處于峰值狀態,中午處于相對的低谷。而夜間訂單量為逐漸下降的趨勢,直至凌晨1點到凌晨3點達到最低點。這與人們的出行作息時間是非常吻合的。在訂單量的峰值時段,數據庫訪問壓力比較大,反之低谷時段則壓力較小。對此我們為訂單查詢服務的一級緩存設置了分時段的過期時間策略,業務高峰時間段緩存時間相對調整變長,低峰時段調整變短。每個查詢服務可以單獨配置這套規則,隨時動態調整。這樣對于數據存儲端壓力來說也就是起到了削峰填谷的作用。(2)訂單狀態分類策略(按業務)機票訂單根據業務定義有各種不同的狀態,表示著訂單處理流轉的各個階段。基于對訂單狀態及其后續變更行為數據的分析,對于已退票或取消的終態訂單,其訂單數據基本不會再發生變化。這類訂單的緩存過期時間可以設置的相對較長;對于已過起飛時間的訂單,用戶再查看訪問訂單數據的概率也大大降低,其訂單數據緩存時間也可以相對長一些;而訂單處理中未出票等過程態訂單,短時間狀態變更的可能性很高,因此不應該放入緩存之中。(3)用戶行為的訂單訪問預測(預加載)根據統計,用戶乘機前的幾個小時內,出于關注出發時間、機場航站樓、航班變動,辦理登機手續等需要,會頻繁查看訂單數據。數據訪問的壓力集中在了白天的峰值時間段內。基于這種對用戶行為的預測,我們考慮了在前一天的凌晨業務低峰階段,將第二天業務高峰時間段內起飛的訂單數據,提前加載到緩存中預熱,將高峰時間段的一部分緩存構建壓力,轉移到了低峰時間段,既提高了低峰時間段的系統資源利用,也緩解了高峰時間段數據庫的壓力。不僅如此,更大的好處是,第二天訂單數據庫即使有短暫的故障,用戶查詢當天出行訂單也不會受到影響,因為數據都已經提前構建在緩存里了。七、總結
經過查詢系統的不斷迭代,埋點數據的統計顯示,訂單緩存數據的命中率達到了90%以上,也就是說對數據庫的訪問壓力降低到了原來的十分之一的水平。從數據庫層面的性能統計監控來看,數據庫服務器的cpu利用率峰值由60%降低到了15%,均值由20%以上降低到了10%以下。對數據系統的可用性來說改善效果非常顯著。在服務響應性能方面,緩存系統的建立也帶來了性能的提升。以訂單詳情服務為例,服務響應時間(PT99)均值由150ms降低到了120ms以下。以下列舉一些保證性能及可靠性的具體技術點:1)采用了Redis Pipeline技術,節省了建立鏈接的時間。2)采用了GZIP壓縮技術,節省4-5倍的Redis存儲空間。3)采用了NIO技術,讓我們的緩存服務支撐更多的鏈接。4)采用了Hystrix熔斷技術,保證了單個Redis實例異常時候,可以放棄該實例,保證其他正常讀取,保證高可用。整個緩存系統的構建,沒有侵入到復雜的機票業務中,更像一個“外掛”系統,工作量及業務風險可控。除緩存系統外,未來的訂單查詢業務核心挑戰依然是穩定性,包括故障的快速定位,調用鏈的梳理及簡化。中國程序員VS美國程序員,這也太形象了吧...研究主攻數據庫和磁盤故障優化,曾經復讀才考上三本,他如今讓華為開出201萬年薪DBA林工:OracleDG 環境主備業務數據不同步備庫報 ORA-600 錯誤怎么整?那個從深圳流水線去了紐約做程序員的女工,最近失業了乘風破浪的中國數據庫有個程序員老公有多爽???做一個國產操作系統,有多難?MySQL 的這個 BUG,坑了多少人?為什么不建議把數據庫部署在docker容器內?A里正在拆中臺,你還在建中臺嗎?騰訊技術專家:解密小程序云開發數據庫 | 干貨微服務架構框架?這里為你匯總了15種阿里P8稅后收入170萬?P8、P9 及以上到底是什么水平?機房生存指南交易、賬務系統去 Oracle 經驗誤執行了 rm -rf /*刪庫之后,除了跑路還能怎么整?!DTCC中國數據庫技術大會2020-2019SACC2019中國系統架構師大會PostgreSQL 2019中國技術大會點擊上方文字可以直接進入小程序瀏覽,下載請在后臺分別回復關鍵詞??DTCC、SACC、PG19即可直接收到完整版 PPT 下載鏈接你「在看」嗎?總結
以上是生活随笔為你收集整理的订单失效怎么做的_此招一出,数据库压力降低90%,携程机票订单缓存系统实践...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows Server:客户端脱机
- 下一篇: 五子棋执黑必胜(转载)