做者:何志勇
本文轉載自公衆號「平安科技數據庫產品團隊」。mysql
2019 年 5 月 9 日,平安科技數據庫產品資深工程師何志勇在第十屆數據庫技術大會 DTCC 上分享了《TiDB 在平安核心系統的引入及應用》,經過對 TiDB 進行 POC 測試,詳細解析如何選擇適用於金融行業級別的開源分佈式數據庫,以及平安「財神節」活動中引入 TiDB 的全流程應用實踐案例分享。本文根據演講內容整理。
<center>何志勇 平安科技數據庫產品團隊 資深工程師</center>redis
做爲一名運維人員,引入一個新的數據庫產品前必需要明確幾點:spring
因此在咱們引入前從如下六個方面分別對 TiDB 進行測試驗證,其中功能與架構、配置與管理、備份與恢復都是針對咱們運維管理,SQL 特性、基準測試、應用場景測試則是應對業務需求和業務場景的。sql
TiDB 事務隔級別爲 SI,支持 Spark 生態,支持動態擴容,跨數據中心部署。數據庫
這是 TiDB 官網最新的架構圖:編程
從左至右看,能夠經過 MySQL 或 MySQL 客戶端接入 TiDB,TiDB 有 TiDB、PD、TiKV 三個組件,組件之間功能相互獨立,需獨立部署,分別負責計算、調度、存儲功能;同時又相互協做,共同完成用戶請求處理。在 TiKV 層各節點是使用 Raft 協議保證節點間數據的一致性,同時它還提供 Spark 接口供大數據分析。 服務器
從上往下看,可經過 Data Miaration 工具從 MySQL 遷移到 TiDB,同時提供備份恢復功能、內部性能監控監測及診斷、支持容器化部署。多線程
TiDB 從架構及生態上基本上具有了傳統數據庫應有的功能。架構
兼容 mysql 語法,2.0 版本不支持窗口函數、分區表、視圖、trigger 等。併發
支持在線 DDL,2.0 只支持串行的 DDL、不支持併發,在優化器上支持 RBO 與 CBO,能對單會話進行管理,能夠支持複雜的 SQL。
備份恢復工具均爲開源,支持多線程備份恢復,當前版本不支持物理備份,loader 恢復時間偏長。
TiDB 在單條 SQL 的性能較好,高併發場景下性能較穩定,但 DML 事務大小有限制。
支持標量子查詢,能支持很是複雜的查詢,查詢引擎可朔性強。
這個應用場景是咱們的產險的實際分析場景,表數據量不大可是 SQL 較爲複雜,是典型的星型查詢。在 Oracle 用了 134 秒,可是 TiDB 用了 50 分鐘,咱們以爲很詫異,與 TiDB 的同事諮詢後,他們經過現場支持咱們優化底層代碼後 34 秒能夠跑出來。
「財神節」是中國平安綜合性年度線上金融狂歡節。2019 年平安集團「財神節」活動於 1 月 8 日正式啓動,涉及壽險、產險、銀行、養老險、健康險、普惠、證券、基金、健康互聯、陸金所、壹錢包、互娛、不動產等多個領域,活動參與的 BU 數量與推廣的力度是歷年之最。單日成交額超過 1000 億,在單日交易額破千億背後是幾百個後臺數據庫實例的運維保障。
咱們看下活動業務場景的特色:
平安在用的開源數據庫有不少,那在這麼多數據庫中,咱們選擇什麼數據庫呢?
綜合對比考量最終咱們選擇 TiDB,在選擇的同時也面臨着挑戰:
2018 年 12 月 17 日~2019 年 1 月 7 日,20 天時間內完成開發測試到生產上線,時間短,風險大
現有開發大都是基於傳統 Oracle 保險業務,對於 TiDB 沒有使用經驗
互聯網業務併發需求前期不可徹底需求,前期不能很好的以實際壓力進行測試,與資源準備
TiDB 還處於生產落地階段,一類系統還沒有使用過 TiDB,沒有大規模應用運維經驗
基於以上挑戰,咱們在 9 臺 PC 服務器上作了驗證測試,測試工具是 jmeter,TiKV 節點數咱們是逐步增長的,具體的測試過程以下:
總結一下,就是:
上線時咱們作了如下兩方面改善:
1. 優化表的定義與索引
表定義:不使用自增加列(自增加的 rowid)做爲主鍵,避免大量 INSERT 時把數據集中寫入單個 Region,形成寫入熱點。
索引:使用有實際含義的列做爲主鍵,同時減小表沒必要要的索引,以加快寫入的速度。
2. 對錶的 region 進行強制分裂
查找表對應的 region:curl http://$tidb_ip:$status_port /tables/$schema/$table_name/regions
使用 pd-ctl 工具 split 對應表的 region:operator add split-region $region_id
打散表的隱式 id,打散表的數據分佈:alter table $table_name shard_row_id_bits=6;
咱們使用了 25 臺機器,後面還臨時準備了 10 臺機器去應對高併發的不時之需。
在使用過程當中遇到以下問題:
(1) 2.0.10 版本下 in 不能下推到表過渡問題
你們看到咱們兩個相同的表結構,同時寫入一些數據,在兩個表進行關聯的時候,發現過濾條件 t1.id=1 時,上面那個執行計劃能夠下推到兩個表進行過濾,兩個表能夠徹底精準的把數據取出來,可是下面把等號後改爲 in 的時候,對 t2 表進行全表掃描,若是 t2 表數據量很大時就會很慢,這是 TiDB 的一個 bug,解決方案就是不要用 in,在 2.1 版本修復了這個 bug。
(2) 2.0.10 下時區設置致使客戶端不能連
咱們在跑命令的時候沒有問題,而且結果是能夠的,可是跑完後就斷掉了,從後臺看也是有問題的,重啓 TiDB 組件也不行,後來找到代碼咱們發現這是一個 bug。
緣由:這個 bug 會在你鏈接時 check 這個時區,致使用戶不能鏈接。
解決辦法:咱們找研發同事從新編譯一個 tidb-server 登入服務器,把時區設置爲正確的,而後使用最初的 TiDB 組件登陸,2.1 版本後這個 bug 修復。
(3) Spring 框架下 TiDB 事務
這個問題是比較重要的問題,有個產品須要生成一個惟一的保單號,業務是批量生成的,當時在 TiDB 中咱們建了一個表,表中只有一條數據,可是咱們發現會有重複保單號出來。
緣由:TiDB 使用樂觀事務模型,在高併發執行 Update 語句對同一條記錄更新時,不一樣事務拿的版本值多是相同的,因爲不一樣事務只有在提交時,纔會檢查衝突,而不是像 Oracle、MySQL、PG 那樣,使用鎖機制來實現對一記錄的串行化更改。
解決辦法:Spring 開發框架下,對事務的管理是使用註解式的,沒法捕獲到 TiDB commit 時的返回狀態。所以須要將 spring 註解式事務改爲編程式事務,並對 commit 狀態進行捕獲,根據狀態來決定是重試機制,具體步驟:
捕獲事務 commit 狀態,並判斷更新成功仍是失敗: