車好多集團系國內領軍的汽車消費服務一站式平臺,旗下擁有瓜子二手車、毛豆新車、車好多車後三大核心業務。
車好多集團關注 TiDB 始於 2018 年初,像大多數公司同樣,公司發展初期爲了快速適配業務開發,大部分數據都存儲在 MySQL 中。但隨着業務快速發展,存量數據愈來愈多,咱們在 MySQL 面臨着以下痛點:git
公司業務發展快,單實例的 QPS 和數據存儲會超出預期,這時候須要對業務線實例進行拆分。 每次業務線拆分須要從數據產生端 (APP) 到數據流轉端 (CDC) 最後到數據倉庫(DW)一塊兒配合調整; 若是涉及到多方同時使用相同庫表,還須要多個應用的負責人協調; 同時一些腳本類程序可能在遷移時被忽略,部分業務數據會受到影響。 每次業務線拆分的週期大概在 2-4 周,耗費人力。github
業務發展到必定程度以後,一些數據表的數據量超過千萬級別,常規作法是分庫分表。這裏有幾個可能遇到的問題:sql
咱們公司的業務模式變化快,爲了快速響應業務,表結構常常調整。在對一些數據在百萬級別以上的大表作 DDL 的時候,會藉助第三方工具,如 pt-osc。修改過程當中須要先複製一份臨時表,這種方式修改的時間較長,對存儲空間、IO、業務有必定的影響。數據庫
面對以上痛點,咱們開始考慮對數據庫的架構進行升級改造,咱們根據業務方的訴求,將一些常見數據庫技術方案,作了一些對比:後端
數據庫類型 | 優勢 | 缺點 |
---|---|---|
MySQL 分庫分表 | 1. 根據 ID 查詢的層面基本上無多餘工做量。2. 短時間技術實現成本低。 | 1. 庫表數量線性增加,運維壓力大,按百萬級別數據量分表計算,每一年增加表的數量至少 30 張,且單表容量仍然較大。2. 分庫分表在代碼層實現需改動代碼。3. 如引入分庫分表中間件,則須要投入專門人員。 |
MongoDB | 1. 技術比較成熟。2. 大數據量下,可經過分片進行擴展。 | 1. 業務須要所有重構,短時間內沒法實現。2. 文檔型數據庫,須要業務來控制數據較驗。 |
ElasticSearch | 搜索功能強大(多二級索引)。 | 1. ElasticSearch 寫入性能稍差,遇到大量寫入操做時候,可能延遲。2. 無 schema 管理,長期維護成本較高。 |
HBase | 1. 技術比較成熟。2. 普通根據 rowkey 查詢,無工做量。3. 可橫向擴展。 | 1. 沒法經過 rowkey 直接獲取數據的場景,都須要額外開發,接口通用性較低。2. 不支持二級索引。3. 協議與現有程序不一致,須要從新開發相關讀寫程序。 |
HBase+phoenix | 1. 底層 kv 存儲複用 HBase,存儲引擎的穩定性強。2. 可橫向擴展。 | 1. SQL 語法小衆。好比只有 upsert,沒有單獨的 insert 和 update。2. Phoenix 的事務功能依賴開源的 percolator 實現,可信度略低。事務仍是一個比較嚴謹的技術,Phoenix 社區和 Google 也沒能查到太多事務相關的信息。 |
HBase+ES | 1. HBase 做爲 OLTP 的記錄存儲,ES 做爲 HBase 的二級索引。2. 兼顧了 HBase 的優勢(快速的 kv 能力,海量存儲能力,可變字段能力)和 ES 的優勢(強大的二級索引能力)。 | 1. 不支持事務。2. HBase 和 ES 兩端的數據一致保障難度高。 |
TiDB | 1. 徹底兼容 MySQL 協議,業務層幾乎不須要改動。2. 分佈式存儲,節點無限擴容,高可用。3. 完美替代 MySQL 分庫分表。4. 大表 DDL不影響業務。5. 支持事務,隔離級別爲'快照級別隔離' [見附錄]。6. 可兼容 CDC 鏈路。 | 1. 資源需求較高。2. 無觸發器、存儲過程、某些語法不兼容。 |
TiDB 具備水平彈性擴展,高度兼容 MySQL,在線 DDL,一致性的分佈式事務等特性,符合車好多部分數據量大,業務變動頻繁,數據保存週期長等場景。 咱們通過 TiDB 的內部測試後,確承認以知足現有業務需求。咱們最終選擇了 TiDB 作爲這類需求的數據存儲。架構
綜合 TiDB 的特性和車好多集團的業務場景,咱們比較適合引入 TiDB 的場景有: 工單分配 / 流轉、電話銷售系統、業務中臺-帳務系統等業務。首先這些業務積累的數據量比較大,在此基礎上一部分業務會有頻繁增長字段的需求,也有一部分業務會使用到事務,這些場景都很是適用於 TiDB。運維
與目標業務方進行了一輪溝通以後,業務方給咱們介紹了一些數據的現狀和業務上的需求:分佈式
因爲 TiDB 的資源要求較高,咱們對接入的業務提出瞭如下要求:工具
面對一個新的數據庫,大部分核心業務仍是擔憂數據庫的穩定性和數據的可靠性,不敢直接嘗試。咱們優先選擇一些數據量比較大而且實時性需求相對較低的場景進行試點,可是業務方仍然擔憂服務的穩定性和性能等諸多問題。咱們屢次與業務方溝通,制定和實施了分段落地的計劃:性能
第一步,將 TiDB 做爲 MySQL 的從庫使用,經過 DM 工具同步數據。業務方使用這套 TiDB 集羣做爲從庫,驗證數據的準確性 / 服務的穩定性 / 查詢的性能等是否符合業務需求,測試正常後灰度小比例的線上流量到該集羣上進行查詢,確認數據正常後逐步放大灰度的比例直至全流量。這一步充分的驗證了 TiDB 的數據同步和數據查詢,業務方對 TiDB 有了初步的認知,也逐漸積累了對 TiDB 和維護人員的信任。
第二步,業務方改造程序,對 MySQL 和 TiDB 進行雙寫,斷開 DM 同步。業務方將 TiDB 做爲主庫直接讀寫,但仍然保留了 MySQL 中的數據寫入,將 MySQL 做爲 TiDB 發生異常以後的降級方案。這個階段持續了 2 個季度左右。在這期間讀寫 TiDB 的程序運行正常,天天的數據校驗保持一致。
第三步,下線雙寫,僅保留直接操做 TiDB 的部分。經過第一步和第二步的驗證和積累的信任,TiDB 正式做爲獨立的數據庫投入到生產環境使用.
新車業務接入 TiDB 以後,業務上將原先只支持近期三個月的查詢擴展到支持全量查詢,這部分數據對用戶行爲精細化管理帶來了必定的幫助。隨着業務發展,存量數據從千萬級別逐步上升到億級別,到如今將近十億,在 1000 QPS 下查詢的 99.9th 延遲低於 128 毫秒,用戶體驗良好。通過了整個接入過程後,新車計劃將存在數據庫瓶頸的業務逐步遷移到 TiDB 中來。通過一年的發展,目前車好多的二手車收售車管理、臺帳、支付網關、用戶社羣等業務逐步嘗試 TiDB,而且在試用以後慢慢從 MySQL 中遷移更多的業務模塊到 TiDB 中。
在推動 TiDB 的過程當中,咱們也遇到了各類問題,除了一些常見的慢 SQL、熱點讀寫、DM 同步數據異常等問題外,咱們在車好多的業務背景下,遇到了一些相對特殊的問題:
TiDB 是一項比較新的技術,社區的版本在不斷的迭代更新,有不少 bugfix 和新特性在持續集成到 TiDB 中。咱們從開始調研到如今,經歷了 2.X 到 4.0.X 的多個版本。咱們選擇了一些比較關心的內容進行跟進,如: Lightning 導入數據 bug 修復、悲觀鎖、TiFlash、TiUP 管理工具、TiCDC 等等。有一次咱們從 2.1.x 的版本升級到 3.0.x 版本,未注意到 sql mode 變動,剛好業務上正好有 SQL 被 ONLY_FULL_GROUP_BY 規則影響,緊急修改 SQL 後從新上線。咱們增量的業務選擇版本的時候,一般會選擇一些已經平穩運行一段時間的版本,上線以後,若是沒有嚴重的 bug 或者急需的特性,一般再也不進行升級,以保障業務不由於數據庫的升級受到影響。
使用 TiDB 一段時間後,某個業務線單表存量數據數據已經超過 5 億,QPS 也超過了 200。某天業務方反饋,線上系統發生大量查詢超時,結果無返回,TiDB-admin 協助排查問題。觀察監控數據,發現 CPU 被打滿,IO 上升明顯。繼續觀察慢 SQL 日誌,發如今 analyze 收集統計信息的末尾階段,有一類 SQL 索引的選擇發生了改變,每次掃描的 key 從正常索引下的百級別到異常索引下的百萬到千萬的級別。爲了快速恢復業務,結合 TiDB 承載的業務的特性,將影響優化器選擇的未使用到的索引刪除,同時將自動 analyze 操做設置爲業務低谷時間段執行。
咱們以這個案例諮詢了 PingCAP 官方,由於 TiDB 使用的是基於成本的優化器(CBO),在統計信息變動的時候,有可能選擇與以前不一致的索引,建議經過 SQL binding 解決此類問題。不久時間後,另外一條業務線的 SQL 由於相似問題,使用了 SQL binding 進行了綁定,在程序使用到 prepare statement 的時候遇到了另外一個 bug [見附錄] ,上報社區後已經加入到修復計劃中。
隨着 TiDB 技術在車好多集團的推動,和第一批吃了螃蟹的業務方的推薦,愈來愈多的業務線但願嘗試 TiDB。受機房設備採購週期的限制,咱們很難短時間內湊出多套獨立的 TiDB 集羣,服務忽然上升的需求量。結合這些新增需求的業務特性: 大部分是增量比較高可是沒有存量數據的業務,前期對資源的需求並非很是高,因而咱們 TiDB-admin 開始調研在同一組機器中混和部署多套集羣,而且進行進程之間的資源隔離。TiDB 分爲多個組件,PD 對資源的需求不高,暫時忽略;TiKV 能夠經過軟件層配置最大的 CPU 和內存,IO 的隔離咱們選擇在同一臺機器部署多塊 SSD 進行物理隔離,也比較好控制;TiDB 雖然能夠經過軟件層配置最大的 CPU 和內存,可是沒法阻止瞬時的內存暴增,調研後發如今經過 TiUP 部署的時候,能夠設置 systemd 的參數 memory_limit,經過系統的 cgroup 限制最大使用內存,這也催生了咱們經過 K8s+Docker 來全面控制資源的想法。咱們在混合部署以後,提供給了業務方進行驗證,確承認以隔離某一方的異常 SQL 對通物理機下其餘TiDB 集羣的影響,新業務逐步用上了 TiDB。
附錄:
https://docs.pingcap.com/zh/t...