滴滴分佈式數據庫選型之路
滴滴出行作爲涵蓋網約車、出租車、順風車、代駕等業務的一站式多元化出行平臺,擁有全球客戶 6.5 億。
在平臺出行種類十餘種且服務如此體量的用戶時,滴滴出行的底層數據庫主要採用 MySQL,且擁有上萬套集羣。其中單實例超 2TB 的集羣爲 400 + 套,最大的集羣規模爲幾十分片,數據總量已超百 TB。還有數十套非 Innodb 引擎的 MySQL 服務如 RocksDB、TokuDB 等。
然而,底層數據庫矩陣隨着業務的高速增長逐漸在性能、效率,成本,一致性這四個方面顯露瓶頸。
首先,某業務在訪問 MySQL 百億大表時,延遲高達上百毫秒,造成業務 SQL 超時,影響業務流程。同時,因爲該表有事務依賴,所以無法通過拆表的方式提升其訪問性能。
其次,由於審計和業務需求,核心歸檔服務中需要保留大量歷史數據,導致服務存儲量高達幾十 T 甚至上百 T,每次業務有新增表字段等 DDL 需求時,DDL 過程都會持續數天或數週。嚴重影響業務上線時間,降低產品迭代效率。
再次,某些業務既需要 TP 能力,又需要 AP 能力。因此由 MySQL 提供 TP 能力,然後通過鏈路把數據同步到大數據平臺,業務同學再進行 AP 訪問。這不僅使運維成本增加,還帶來了業務同學的學習和改造成本。因此,我們希望 TP 場景和 AP 類場景可以在內部閉環,降低成本,加速業務迭代效率。
最後,滴滴出行的金融服務對數據一致性有強依賴,無法接受 MySQL 主從上百毫秒級延遲,導致所有的金融服務只能依靠強制讀寫主庫的方式。當業務流量上漲時,我們只能通過不斷地拆分主庫提升性能,這不僅浪費從庫資源,還會造成業務成本翻倍增長。
面對上述 MySQL 痛點和業務挑戰,我們把選型和調研工作投入到分佈式數據庫領域,沒想到也是一波三折。
引入分佈式數據庫某 DB 無法滿足業務需求
根據業務需求,我們確定引入分佈式數據庫必須滿足三個條件。
一是能夠解決當前性能差、效率低、成本高,以及數據一致性方面的問題。根據上文所述,我們希望數據庫有秒級的在線 DDL 功能、更便捷的橫向擴縮容能力、天然的強一致性、更低的學習與運維成本,同時,能夠對下游鏈路提供支持。
二是要足夠穩定,穩定性即我們對業務同學承諾的 SLA 標準,包含可恢復性、Lantency、限流模型、容量模型。這也是我們選型時的基礎要求。
三是要符合滴滴出行的未來業務規劃,其中最重要的是雙活需求。
在 2021 年初,我們調研了幾款發展較爲成熟的分佈式數據庫,並在 2021 年中引入當時的選型結果——某 DB,開始搭建測試集羣,學習分佈式數據庫的基礎知識。
後續,從測試到正式上線歷經四個階段。
• 第一階段:2022 年初,對某 DB 進行 Sysbench 壓力測試、兼容性測試,以及驗證高可用場景、周邊工具可用性、DDL 和擴縮容能力。
• 第二階段:2022 年 8 月,我們搭建了非核心歸檔庫,用於積累線上運維經驗,讓組內同學都能在真實環境中進行實戰演練,同時鍛鍊大家解決問題的能力。
• 第三階段:2022 年 9 月,我們在某 DB 接入公司級監控,編寫運維手冊,期望當我們遇到故障時可以根據預案 SOP 輕鬆解決線上問題,並經過長期實踐能更好地接入自動化平臺。
• 第四階段,2023 年初,我們在某 DB 接入線上歸檔庫和在線集羣。
在某 DB 上線後,解決了部分 MySQL 的使用問題。比如,除索引以外的其它 DDL 操作基本都秒級完成;再比如橫向一鍵擴容的功能非常實用。但是,我們在日常運維以及和業務同學平時的溝通中,發現了一些線上問題。
• 第一個問題是在進行日常集羣擴容、索引添加的整個過程中,業務延遲基本會上漲近 40%。
• 第二個問題在於日常的抖動,在業務流量、業務模型不變的前提下,某 DB 會出現間接性的延遲抖動,抖動範圍在 40%-100% 不等。因爲業務對延遲數據庫的響應延遲非常敏感,當出現延遲變長的情況時,整體響應超過業務閾值,造成大量 SQL 執行失敗,對客戶產生極大影響。
• 第三個問題來自於業務的下游同步需求,比如是否可以依賴當前的 Canal 鏈路,把數據同步到 MQ、Kafka 以供其他業務方使用,用最小的代價達到業務需求。
針對這三個問題,我們做了一些優化和調整,比如參數優化、調小併發度、增加存儲節點數量等,可仍不能達到業務側對延遲的要求。因此,我們開始再次調研是否有更適合的分佈式數據庫方案。
轉角遇到分佈式數據庫 OceanBase
在調研分佈式數據庫的過程中,我們通過技術文章認識到 OceanBase 的能力,比如穩定、性能較高、可靈活擴展、降本表現不錯等,結合對 OceanBase 社區論壇動態的觀察,初步分析其可能滿足我們的業務需求,於是展開了進一步的測試驗證。
基於上一次分佈式數據庫選型失敗的經驗和教訓,我們並沒有對 OceanBase 進行常規的測試流程,而是針對線上問題進行定向壓測和場景演練。我們認爲,只有滿足線上需求,才能進行更深的探索。
首先,測試日常抖動。低峯期業務配合 100% 模擬線上流量直接發壓,我們進行了 4 次壓力測試,每次持續 3 小時以上。在壓力測試的過程中,業務同學還會不斷變化壓力模型,比如 1:1 的讀寫、2:1 的讀寫、3:1 的讀寫等。在測試結束後,DBA 同學根據業務同學提供的 SQL 訪問模型,自己編寫接口模擬業務場景,再通過滴滴出行壓測平臺進行一週持續發壓測試。經過兩輪這樣的壓力測試,OceanBase 在延遲方面表現平穩,整體壓測期間沒有出現明顯的延遲抖動,CPU 負載也很穩定,業務端也沒有像之前線上一樣因延遲問題出現大量報錯的情況,完全滿足我們業務方的需求。
其次,驗證常規業務流量下,擴容、縮容對業務 Latency 的影響。基於 OceanBase 運維平臺 OCP 便捷的 API 接口,我們通過簡單調用幾十分鐘內就實現了之前需要長達數天的自動擴、縮容操作。不斷地觀察切換過程 Latency 的情況。結果顯示,在切換過程中會產生 20s 左右的延遲上漲(滿足業務訴求),其餘時間段均平穩度過,沒有產生擴容期間延遲上漲的問題。
最後,我們基於業務流量對 1T 大表進行多達幾十次的加索引操作,觀察延遲情況。結果顯示,一直到索引添加結束,都無明顯延遲上漲。
在經過上述基於業務場景的測試後,OceanBase 的性能滿足業務需求。在接下來的一個月,我們開始爲上線做準備。
我們驗證了 OceanBase 與 MySQL 的兼容性,對 1000 個 CASE 進行回放,發現有 22 個函數變量未通過驗證,但經過比對,這 22 個函數均未在滴滴出行線上業務使用。因此,OceanBase 100% 兼容線上業務。
在上線任何存儲方案或功能前,我們都會對故障預案進行驗證,涵蓋網絡、磁盤、內存、CPU、節點故障等。我們此次故障預案基於 OCP 運維平臺,這是一個白屏化的操作平臺,即便是剛接觸 OceanBase 的同學,根據預案也能達到線上及時止損的效果。順便一提,除 OCP 外,OceanBase 的其他工具如 OMS 遷移工具、binlog_service、obdiag 巡檢也都符合要求。
爲避免疏漏,我們仍然對 OceanBase 進行了高可用驗證、磁盤 I/O 性能測試、基準壓力測試。
• 高可用驗證:2.5W/s QPS 壓力下進行單點故障測試,1T 集羣 15 秒內可以完成自動切換,15 秒後集羣整體運行穩定. 。
• 磁盤 I/O 性能測試:模擬 OceanBase 順序寫、隨機讀的文件訪問方式對磁盤進行性能測試,以判斷機型的使用極限。
• 基準壓力測試結果如下圖所示:
OceanBase 在滴滴出行的落地效果
滴滴出行在 OceanBase 上線的第一個業務是特徵庫,其特點是對接業務廣泛,公司內很多業務依賴特徵庫做數據聚合與數據分析。因此,當特徵庫在線上出現問題時,影響範圍較大。在 OceanBase 上線初期,業務同學採用雙寫隨機讀的方式驗證其性能,這樣能保證問題發生時可以隨時回滾,還能更直觀地對比上線前後的性能變化。
從下圖可見,OceanBase 上線後,性能提升明顯,其穩定性表現也得到了業務同學的一致認可。
OceanBase 在滴滴出行上線後,我們開始完善基於 OceanBase 的上下游生態。上文提到,我們需要解決下游數據鏈路支持的問題,滴滴出行的大多數業務都需要把上游的 MySQL 或 OceanBase 的數據同步到下游的 MQ 或 Kafka,以供不同業務線或業務場景進行分析。因此,一些業務強依賴於 binlog 同步鏈路。
OceanBase 的 Binlog Service 在 MySQL 兼容模式下,可以將 OceanBase 的日誌轉換成 MySQL Binlog 文件,且全面兼容 Binlog 能力,更方便接入下游生態。當前工具基本無需改造就可以直接使用,避免了重複造輪子。可問題是,Binlog Service 目前爲單機模式,無法滿足高可用需求。我們的解決方案是:將多個 binlog server 部署在不同的 proxy 節點上,實現共同消費模式;Canal 通過文件名 + 時間戳的形式,實現單個 binlog server 故障時,自主切換到另外一個 server 上,實現高可用。
OceanBase 應用經驗總結與未來規劃
上線 OceanBase 之後,不僅解決了此前線上的問題,還讓整體延遲縮短了近 10 倍。並且在執行 DDL、擴縮容、日常流量中,延遲整體表現平穩,沒有產生間接性抖動。完全滿足我們業務對延遲的要求,保證了線上業務的穩定運行。
在使用 OceanBase 過程中,讓我們留下了三個深刻的印象。
第一,分區表設計,是超級大表性能穩定的保障。OceanBase 分區表的設計是它的一大亮點,使我們可以根據不同的維度對錶進行分區。例如,我們有一張大表,既可以根據訂單進行分區,也可以根據司機進行分區,還可以根據乘客進行分區。不僅滿足業務不同維度的查詢需求,而且性能有保障。
第二,日誌、數據分盤存儲,防止資源搶佔以影響性能。起初滴滴出行由於 MySQL 歷史架構導致日誌和數據放在一塊磁盤裏,帶來的問題是當上遊業務量特別大,在 OceanBase 進行轉儲時,日誌和數據會相互搶佔資源,進而影響性能。將日誌和數據分盤存儲,就能避免這個問題,達到 OceanBase 的最佳應用效果。
第三,MySQL Shard 到 OceanBase 的多表合併問題。當我們把上游 MySQL 的多表合併到下游 OceanBase 的一張表時,我們不僅要關心遷移效率和成本,還要關心鏈路問題。例如,我們把 MySQL 20 個庫的分表合併到一個 OceanBase 庫時,可能這 20 個分庫是由 20 個鏈路提供消費,但合併到下游時只能有一個 binlog server 提供鏈路服務。這時,我們需要評估這個 binlog server 和 Canel 能否支持這麼大的流量。
未來,我們計劃擴大 OceanBase 使用規模。首先替換數十套非 InnoDB 引擎;其次逐漸承接線上的核心歸檔服務;最後將 OceanBase 作爲分佈式數據庫方案,並將 MySQL 超大規模核心集羣逐步遷移至 OceanBase。
另外,在運維方面,核心業務場景如多活場景、強一致場景開始接入 OceanBase,同時,將 OceanBase 運維管控平臺接入滴滴出行平臺,加強運維人員的問題定位、故障排查等能力。
目前,OceanBase 在滴滴出行上線的表現滿足預期。在使用過程中,我們積累了三個期望或建議,希望官方能夠支持。
期望實現全局自適應限流。因爲業務方有時候簡單粗暴,會出現大量自動重試操作,基於我們的 SLA 標準,期望 OceanBase 在未來具備全局自適應限流能力,,自動對每種類型的 SQL 限制併發度,,防止重試 SQL 瞬間激增,,導致數據庫 Load 激增。這樣一來,當我們設置全局 SQL 執行的併發度在 10 或 20 的時候,無論歷史 SQL 還是新 SQL 都會自動統一,無需運維手動操作,當出現故障時即可快速止損。目前 OCP 具備單獨對 SQL 限流的能力,但不能全侷限流。
期望增加核心字段校驗,增快遷移速度。在 OceanBase 上線期間,OMS 的遷移只是基於全量的遷移與數據驗證(OceanBase 社區響應迅速,,最新版 OMS 已支持該功能.),但在大表遷移場景下,大表中有一些備註信息、大字段等,業務同學在數據校驗時更側重於核心字段校驗。我們希望 OMS 擁有校驗部分核心字段的能力,分擔業務同學的校驗工作,提高 OMS 的遷移速度。同時希望 OMS 支持多表的旁路導入,替代目前多表合併採用的 SQL 方式。
期望更方便的多租戶拆分能力。在數據使用初期,業務的規模可能都比較小。大家爲了節省資源希望把多個租戶或多個業務線放在一個大的集羣中,但這會遺留什麼問題呢?隨着業務的發展,該集羣將由非核心變爲核心,想把業務從核心集羣中遷移出去,爲了保證數據一致性,採用主備庫模式,且相同的 Proxy 兼容主庫和備庫。在主備庫搭建過程中,讓備庫的延遲與主庫完全齊平後,Proxy 進行主備庫的切換,業務幾乎是無感知的。備庫完全遷移出來後,我們可以通過切換 Proxy,再把業務流量遷移出來。目前據 OceanBase 社區反饋,,下一個 OBProxy 版本將支持透明切換,,幫助用戶完成無感遷移。
作者簡介:吳其朋,滴滴分佈式存儲運維負責人
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/qzSrdP2f2hfznt8Md3b9Pw