股份制銀行互聯網理財場景中 TiDB 的選型和應用適配實戰

作者:鄒建偉,北京開科唯識技術有限公司 技術專家。

一、互聯網理財的興起

在經濟和科技飛速發展的趨勢下,相比於以前傳統的線下理財模式,互聯網理財的模式,因其入圍門檻相對較低,選擇範圍廣,加上隨時隨地用電腦或者手機就能夠進行理財,導致便捷性和靈活性的提升,從而讓越來越的人們開始接受理財、樂於理財,理財的意識和投入的形態也越來越多。但隨着監管制度的管控、用戶規模、渠道規模、業務形態、高併發業務請求的不斷增長和變化,傳統的理財 IT 基礎設施建設已經無法滿足用戶的使用體驗,基於分佈式系統建設新的業務系統必將破浪前行。

這次我們在中國某大型股份制銀行—— G 行的互聯網理財系統建設中,也是採用了分佈式的數據庫系統來取代傳統 Oracle 數據庫系統,在使用分佈式數據庫 TiDB 時,遇到了新技術適配的一些問題,通過遷移、開發改造和聯調優化,積累了互聯網理財場景中的一些分佈式數據庫 TiDB 的經驗。本篇文章分享下在建設中遇到的問題和最終的解決方案,希望對所有準備建設和正在建設互聯網理財系統的的用戶有所幫助。

二、互聯網理財業務簡介

互聯網理財最早於 2003 年就已經開展業務,主要承載基金代銷、理財銷售等線上業務,2018 年 4 月隨着“資管新規”的發佈,銀行理財產品起售點由 5 萬下調至 1 萬,大大促進了銀行資管理財業務的發展,更加激發了客戶購買理財產品的熱情,部分明星熱銷產品,更是吸引了大量客戶集中搶購。G 行互聯網理財系統主要涉及兩大類業務場景:

  • 聯機交易場景 :處理開戶申請請求,對單筆交易的響應時間有較高的要求;
  • 批量任務場景 :處理理財批量業務,屬於計算密集型的工作,對數據庫大數據量下的吞吐能力要求較高。

2.1 業務功能拓撲

互聯網理財系統主要包含文件傳輸、實時開戶、交易確認、份額登記、收益結轉、產品管理、產品運營等功能,拓撲圖如下:

image

業務對數據庫處理能力提出了明確的技術指標要求:

  • 批量任務:要求數據庫提供在 2h 內對 5000w 筆交易記錄,能夠跑完夜間批量任務的能力。
  • 聯機任務:要求數據庫提供事務平均響應延時不超過 100ms 的能力。

2.2 數據存儲拓撲

同城兩中心

整套集羣服務器使用接近 30 臺物理服務器,每臺物理服務器均配置 4 塊 NVMe 盤、2 個萬兆網卡、2 個千兆網卡、72vcore、512G 內存,預期可以保留 3 個月的在線數據。

三、選型之路

3.1 背景與依據

在傳統理財業務系統使用集中式的 IOE 架構,原有傳統數據庫 Oracle 數據庫遇到支撐的瓶頸,已無法適應互聯網+理財業務模式的發展需求, 取而代之的是通過開源自主可控、分佈式數據庫的技術方案來支撐當下的互聯網技術模式的系統建設,現有 Oracle 主要遇到亟待解決的的問題如下:

  1. 容量上限不能擴展 (存不下、查不出來,索引優化已沒有用)。

  2. 分佈式改造和適配如何取捨。

在當前分佈式數據庫解決方案領域內,可以聚焦的數據庫選擇範圍就剩下分庫分表方案 和 NewSQL 原生分佈式方案(順帶的說明下,這裏我們不爭論分庫分表究竟算不算分佈式架構,我們相信技術是爲場景存在的)。選型我們主要考慮三點:首先是數據庫功能,例如括高可用性、SQL 兼容、橫向擴展、擴容等等;其次是技術架構的前瞻性、發展潛力、社區活躍度;最後是大數據量下的數據庫性能最爲看重。前期我們與候選的數據庫廠家的工程師合作模擬了 daemon 業務程序,來驗證數據庫的性能,主要兩個部分內容:

  1. 數據初始化能力

來自互聯網渠道的理財數據,預估每小時至少千萬級別,在 1 個小時內我們有一系列的批量任務,留給數據庫入庫的時間最多 10 分鐘。

  1. 業務性能測試

理財業務具有多任務並存的特點,大方向說包括聯機交易任務和跑批任務兩部分,跑批任務包括日間任務和夜間任務以及數倉 edw 任務。聯機任務要求事務平均響應延時不超過 100ms,批量任務即使並存時也不可以超過總體執行時間。

經過多輪的測試、評審,分庫分表對業務設計上的不解決夠優雅,由於拆分字段的規則限制了業務實現的一些方式,不能靈活進行業務處理,並且在批量的複雜邏輯SQL 處理上性能無法滿足業務要求,最終我們選擇 TiDB 來進行分佈式數據庫的建設。驗證下來,完全滿足業務數據初始化效率、提升聯機交易和批量處理響應能力、縮短批量處理時間週期,而且也無需限制業務場景的處理邏輯,根據壓力需求靈活的進行在線擴展和在線收縮。上線前的非功能測試中,聯機交易部分:在併發用戶 30 下,數據庫處理能力爲 536 筆/s,響應時間爲 0.0558s,滿足預期 200TPS。批量入庫:64 併發下,5kw 數據入庫 9.7min,當然這並非極限值。

3.2 TiDB 的特性優勢

水平彈性擴展

這裏說的水平擴展包括兩方面:計算能力和存儲能力。TiDB Server 負責處理 SQL 請求,隨着業務的增長,可以簡單的添加 TiDB Server 節點,提高整體的處理能力,提供更高的吞吐。TiKV 負責存儲數據,隨着數據量的增長,可以部署更多的 TiKV Server 節點解決數據 Scale 的問題。

高可用

TiDB 集羣核心三大組件:TiDB/TiKV/PD 都能容忍部分實例失效,不影響整個集羣的可用性。TiDB 本身是無狀態的,支持動態的增加刪除。TiKV/PD 採用 Raft 協議,在大多數存活的前提集羣便是可用的。

數據強一致

TiDB 的分佈式算法使用 Raft,其事務可以跨分片、跨節點執行,並且強一致。

生態強大

這個特點應該毋庸置疑,說是“風口的豬”也不過分。TiDB 分佈式數據庫從 2015 年 4 月份開源以來,有來自社區的開發者、用戶、佈道師、設計師等不同角色的貢獻者們的細心呵護,也有來自 PingCAP 持續不斷的資源投入,截止到 2020 年 3 月,TiDB 社區項目已經聚集了來自全球的 760 多位 Contributor,100 多位核心用戶,30000+ GitHub Stars 支持,TiDB 現已被近 1000 家不同行業的領先企業應用在實際生產環境。TiDB 詳細的架構和原理可以參照官網(不再贅述)

四、開發改造中的思考&問題

G 行採用的 TiDB 版本是 3.0 早期版本,僅提供樂觀鎖機制, 這個問題在 TiDB 3.0.8 後引入了悲觀鎖後得到了解決。作爲一名“重度”悲觀鎖使用者,TiDB的樂觀鎖是我剛開始接觸 TiDB,所認爲的開發改造過程中最大“阻礙”。但實際開發過程中,這裏的碰到的問題其實很少,更多是認知理解的過程。整個改造過程中主要遇到了以下幾個方面的問題,也都通過 TiDB 提供的最佳開發實踐獲得了很好的處理效果。

問題 1:熱點賬戶更新

select for update 語句是悲觀鎖機制下熱點賬戶更新場景常被利用的機制,Oracle 數據庫中,這個語句的作用是:

The FOR UPDATE clause lets you lock the selected rows so that other users cannot lock or update the rows until you end your transaction.

也就是說利用它可以實現數據行的鎖定,阻塞其它事務對該行數據的 DML 操作。TiDB 也支持這個語句,不過在樂觀鎖機制下,這個語句不會在事務開啓就鎖住數據,而是其他事務在提交的時候進行衝突檢查,如有衝突,會進行回滾。

問題 2:Rows Affected 不可信

悲觀鎖機制下,顯式事務每條 DML 語句執行完成後數據庫會返回影響行數:affect rows,業務會利用 affect rows 實際值不同進行不同的邏輯處理,這個是沒問題的。不過 TiDB 樂觀鎖機制,顯示事務每條 SQL 執行完成後返回的 affect rows 是不可信,究其根本原因,悲觀鎖是先加鎖再更新,而樂觀鎖機制下,行衝突檢測和數據上鎖是放在事務提交時檢測的,這裏舉一個例子:

image

對於事務 B 來說,update 語句執行後數據庫返回 1 row affected,不過顯而易見,這個語句提交時並沒有發生更新,也即此時的 Affected rows 是不可信的。如果業務還希望使用 affected rows 來做程序執行邏輯的判斷條件,可行的方式是:顯示事務下,先判斷事務成功的條件,然後再根據 affected rows 進行邏輯處理。而隱示事務下,可以直接使用 affected rows 進行邏輯處理。

問題 3:大事務

熟悉 MySQL 的同學會對事務大小設計比較熟悉,開發規範中會盡可能拆分大事務爲多個小事務。TiDB 對大事務也有類似的要求,並給出了限定具體限定標準:

  • 每個事務內的 SQL 數量不超過 5000 條(可配置)。
  • 每個鍵值對不超過 6MB。
  • 鍵值對的總大小不超過 100MB。
  • 鍵值對的總數不超過 300,000。

開發使用過程中,體會最多的限制是鍵值對的總數不超過 300,000,老系統稍不注意就超出了這個限制,造成處理失敗。這裏要着重說明,鍵值對數與行數不等價。舉例說明:一行數據是一個鍵值對,一行索引也是一個鍵值對,當一張表只有 9 個索引時,每 insert 一行數據會寫入 10 個鍵值對。這裏的原因涉及到 TiKV 使用的存儲格式,感興趣的同學可以搜索 TiDB 相關文章進一步閱讀。

問題 4:WRITE CONFLICT

WRITE CONFLICT 是開發中碰到的頻率最多的問題之一,報錯示例信息:

Err:[kv:9007]Write conflict, txnStartTS=411771139330670593, conflictStartTS=411754809751764993, conflictCommitTS=0, key={tableID=698, handle=391317290} primary={tableID=698, indexID=5, indexValues={0, 391317246, }} [try again later], ErrCount:313, SnapshotVersion:411752587989614594

問題的成因這裏不贅述,感興趣的同學可以搜索相關文檔查看。TiDB 默認針對這個錯誤不會進行事務重試,由參數 tidb_disable_txn_auto_retry 控制,3.0 版本默認值是 1,而在更早的 2.1 版本里沒有這個參數,默認行爲是會自動重試,默認值更改的原因是優化事務處理邏輯,適應更多場景。

五、總結

目前互聯網理財業務系統穩定的運行在 TiDB 3.0 版本樂觀鎖下,TiDB 4.0 馬上要 GA 了,我們當初能趕上基於 4.0 的改造該有多好啊,據說 4.0 版本有了更多的新特性
,讓後續遷移到 TiDB 數據庫的同學會更加的通用、易用。比如:

4.0 有了大事務

對於開發人員說,TiDB 4.0 以前事務的限制始終有點「達摩克利斯之劍」的意味,總是擔心一個不留心就撞牆。4.0 版本開始,對事務的限制鬆綁很多,鍵值對的總大小允許 10GB 以內。

有了悲觀鎖

相比大事務帶來的彆扭,悲觀鎖個人覺得是最期待的特性。最早在 TiDB 3.0.8 版本引入,4.0 版本開始默認開啓悲觀鎖。悲觀事務模型是對於金融場景非常重要的一個特性,有了悲觀鎖我相信 TiDB 纔會走的更高更遠。

新特性很期待

TiDB 4.0 GA 版本即將發佈,除了本文涉及的大事務、悲觀鎖等等還有很多新特性,例如 Sequence、Key VisualizerFollower Read等等,有興趣的同學可以官網查看相關文章。

更多 TiDB 實踐案例閱讀:案例 | PingCAP

關於 TiDB 使用上的問題可以登錄可以在 TiDB 用戶論壇 Asktug.com 交流探討~

公衆號簽名圖.jpeg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章