做者:孫玄,轉轉公司首席架構師;陳東,轉轉公司資深工程師;冀浩東,轉轉公司資深 DBA。數據庫
轉轉二手交易網 —— 把家裏不用的東西賣了變成錢,一個幫你賺錢的網站。由騰訊與 58 集團共同投資。爲海量用戶提供一個有擔保、便捷的二手交易平臺。轉轉是 2015 年 11 月 12 日正式推出的 APP,遵循「用戶第一」的核心價值觀,以「讓資源從新配置,讓人與人更信任」爲企業願景,提倡真實我的交易。後端
轉轉二手交易涵蓋手機、3C 數碼、母嬰用品等三十餘個品類。在系統設計上,轉轉總體架構採用微服務架構,首先按照業務領域模型垂直拆分紅用戶、商品、交易、搜索、推薦微服務。對每個功能單元(商品等),繼續進行水平拆分,分爲商品網關層、商品業務邏輯層、商品數據訪問層、商品 DB / Cache,以下圖所示: 服務器
轉轉後端業務現階段主要使用 MySQL 數據庫存儲數據,還有少部分業務使用 MongoDB。雖然目前狀況下使用這兩種存儲基本能夠知足咱們的需求,但隨着業務的增加,公司的數據規模逐漸變大,爲了應對大數據量下業務服務訪問的性能問題,MySQL 數據庫經常使用的分庫、分表方案會隨着 MySQL Sharding(分片)的增多,業務訪問數據庫邏輯會愈來愈複雜。並且對於某些有多維度查詢需求的表,咱們總須要引入額外的存儲或犧牲性能來知足咱們的查詢需求,這樣會使業務邏輯愈來愈重,不利於產品的快速迭代。架構
從數據庫運維角度講,大數據量的狀況下,MySQL 數據庫在每次 DDL 都會對運維人員形成很大的工做量,當節點故障後,因爲數據量較大,恢復時間較長。但這種 M - S 架構只能經過主從切換而且須要額外的高可用組件來保障高可用,同時在切換過程因爲須要肯定主庫狀態、新主庫選舉、新路由下發等緣由,仍是會存在短暫的業務訪問中斷的狀況。 綜上所述,咱們面臨的主要問題可概括爲:併發
數據量大,如何快速水平擴展存儲;app
大數據量下,如何快速 DDL;運維
分庫分表形成業務邏輯很是複雜;異步
常規 MySQL 主從故障轉移會致使業務訪問短暫不可用。分佈式
針對上章提到的問題,轉轉基礎架構部和 DBA 團隊考慮轉轉業務數據增速,定位簡化業務團隊數據庫使用方案,更好的助力業務發展,決定啓動新型存儲服務(NewSQL)的選型調研工做。 函數
TiDB 數據庫,結合了關係庫與 KV 存儲的優勢,對於使用方,徹底能夠當作 MySQL 來用,並且不用考慮數據量大了後的分庫分表以及爲了支持分庫分表後的多維度查詢而創建的 Mapping 表,能夠把精力所有放在業務需求上。因此咱們把 TiDB 做爲選型的首選對象展開了測試和試用。
TiDB 支持絕大多數 MySQL 語法,業務能夠將基於 MySQL 的開發,無縫遷移至 TiDB。不過目前 TiDB 不支持部分 MySQL 特性,如:存儲過程、自定義函數、觸發器等。
經過測試工具模擬不一樣的場景的請求,對 TiDB 數據庫進行壓力測試,經過壓力測試結果的對比,能夠提供 RD 使用 TiDB 的合適業務場景以及 TiDB 的使用建議。 這次壓力測試,總共使用 6 臺物理服務器,其中 3 臺 CPU 密集型服務器,用於啓動 TiDB - Server、PD 服務;另外 3 臺爲 IO / CPU 密集型的PCIE 服務器,用於啓動 TiKV 服務。 使用 sysbench - 1.0.11 測試數據大小爲 200G 的 TiDB 集羣,在不一樣場景下 TiDB 的響應時間(95th per):
順序掃描的效率是比較高的,連續的行大機率會存儲在同一臺機器的鄰近位置,每次批量的讀取和寫入的效率會高;
控制併發運行的線程數,會減小請求響應時間,提升數據庫的處理性能。
適合線上業務混合讀寫場景;
適合順序寫的場景,好比:數據歸檔、操做日誌、攤銷流水。
將 TiDB 掛載到線上 MySQL,做爲 MySQL 從庫同步線上數據,而後業務將部分線上讀流量切換到 TiDB,能夠對 TiDB 集羣是否知足業務訪問作好預判。
咱們第一個接入 TiDB 的業務線是轉轉消息服務。消息做爲轉轉最重要的基礎服務之一,是保證平臺上買賣雙方有效溝通、促進交易達成的重要組件,其數據量和訪問量都很是大。起初咱們使用的是 MySQL 數據庫,對其全部的業務都作了庫的垂直拆分以及表的水平拆分。目前線上有幾十 TB 的數據,記錄數據達到了幾百億。雖對 MySQL 作了分庫分表,但實例已經開始又有偶發的性能問題,須要立刻對數據進行二次拆分,而二次拆分的執行成本也比較高,這也是咱們首先遷移消息數據庫的緣由之一。
消息服務有幾個核心業務表:聯繫人列表、消息表、系統消息表等等。聯繫人列表做爲整個消息系統的樞紐,承載着巨大的訪問壓力。業務場景相對其餘表最複雜的,也是這個表的實例出現了性能問題,因此咱們決定先遷移聯繫人列表。
整個遷移過程分三步:測試(判斷 TiDB 是否知足業務場景,性能是否 OK)、同步數據、切流量。
**(1)測試:**首先咱們模擬線上的數據和請求對「聯繫人列表」作了大量功能和性能的驗證,並且還將線上的數據和流量引到線下,對數據庫作了真實流量的驗證,測試結果證實 TiDB 徹底知足消息業務的需求。引流工做,咱們是經過轉轉自研的消息隊列,將線上數據庫的流量引一份到測試環境。測試環境消費消息隊列的數據,轉換成數據庫訪問請求發送到 TiDB 測試集羣。經過分析線上和測試環境兩個數據訪問模塊的日誌能夠初步判斷 TiDB 數據庫是否能夠正常處理業務請求。固然僅僅這樣是不夠的,DBA 同窗還須要校驗 TiDB 數據的正確性(是否與線上 MySQL 庫一致)。驗證思路是抽樣驗證 MySQL 庫表記錄和 TiDB 的記錄 Checksum 值是否一致。
**(2)同步數據:**DBA 同窗部署 TiDB 集羣做爲 MySQL 實例的從庫,將 MySQL 實例中的聯繫人列表(單實例分了 1024 個表)的數據同步到 TiDB 的一張大表中。
**(3)切流量:**切流量分爲三步,每兩步之間都有一週左右的觀察期。
第一步將讀流量灰度切到 TiDB 上;
第二步斷開 TiDB 與 MySQL 的主從同步,業務開雙寫(同時寫 MySQL 和 TiDB,保證兩庫數據一致)確保業務流量能夠隨時回滾到 MySQL;
第三步中止 MySQL 寫入,到此業務流量徹底切換到 TiDB 數據庫上。
遷移過程當中最重要的點就是確保兩個數據庫數據一致,這樣讀寫流量隨時能夠切回 MySQL,業務邏輯不受任何影響。數據庫雙寫的方案與上文提到的引流測試相似,使用消息隊列引一份寫入流量,TiDB 訪問模塊消費消息隊列數據,寫庫。但僅僅這樣是不能保證兩個庫數據一致的,由於這個方案沒法保證兩個寫庫操做的原子性。因此咱們須要一個更嚴謹的方案,轉轉的消息隊列還提供了事務消息的支持,能夠保證本地操做和發送消息的原子性。利用這一特性再加上異步補償策略(離線掃描日誌,若是有失敗的寫入請求,修正數據)保證每一個消息都被成功消費且兩個庫每次寫入結果都是一致的,從而保證了 MySQL 與 TiDB 兩個庫的數據一致。
按照上述的方案,咱們已經將消息全部的業務都切到 TiDB 數據庫上。遷移過程當中也不都是順風順水,也遇到了問題,過程當中也獲得了 TiDB 官方團隊的大力支持。這裏主要介紹兩個問題:
(1)TiDB 做爲分佈式存儲,其鎖機制和 MySQL 有很大不一樣。咱們有一個併發量很大,可能同時更新一條記錄的場景,咱們用了 MySQL 的惟一索引保證了某個 Key 值的惟一性,但若是業務請求使用默認值就會大量命中惟一索引,會形成 N 多請求都去更新統一同一條記錄。在 MySQL 場景下,沒有性能問題,因此業務上也沒作優化。但當咱們用這個場景測試 TiDB 時,發現 TiDB 處理不太好,因爲其使用的樂觀鎖,數據庫輸出大量的重試的日誌。業務出現幾十秒的請求延遲,形成隊列中大量請求被拋棄。PingCAP 的同窗建議調整 retry_limit 但也沒有徹底生效**(該 BUG 已經在 2.0 RC 5 已經修復)**,最後業務進行優化(過濾使用默認值的請求)後問題獲得解決。
(2)第二個問題是運維方面的,DBA 同窗按照使用 MySQL 的運維經驗,對一個上近 T 的表作了 Truncate操做,操做後,起初數據庫表現正常,但幾分鐘後,開始出現超時,TiKV 負載變高。最後請教 PingCAP 同窗分析,定位是操做觸發了頻繁回收 Region 的 BUG**(該 BUG TiDB 2.0 版本已經修復)**。
使用 TiDB 數據庫,業務模塊隊列請求數基本保持 1 個,MySQL 會有較大抖動。
使用 TiDB 數據庫,總體響應延時很是穩定,不受業務流量高峯影響,但 MySQL 波動很大。 另外在擴展性方面,咱們能夠經過無縫擴展 TiDB 和 TiKV 實例提高系統的吞吐量,這個特性 MySQL 是不具有的。
接入 TiDB 數據庫後業務邏輯層服務接口耗時穩定無抖動,且沒有發生丟棄的狀況(上圖錯誤大多由數據訪問層服務隊列堆積發生請求丟棄形成)。
目前轉轉線上已經接入消息、風控兩套 OLTP 以及一套風控 OLAP 集羣。
集羣架構以下:目前轉轉線上 TiDB 集羣的總容量幾百 TB,線上 TiDB 表現很穩定,咱們會繼續接入更多的業務(留言,評論、搜索、商品、交易等等)。
1. 後續規劃
2. TiDB 使用成果