TiDB 在摩拜單車在線數據業務的應用和實踐
作者:Mobike / 技術研發部 / 基礎平台中心 丁宬傑 胡明
背景
摩拜單車於 2015 年 1 月成立,2016 年 4 月 22 日地球日當天正式推出智能共享單車服務,截至 2017 年 11 月中旬,已先後進入國內外超過 180 個城市,運營著超過 700 萬輛摩拜單車,為全球超過 2 億用戶提供著智能出行服務,日訂單量超過 3000 萬,成為全球最大的智能共享單車運營平台和移動物聯網平台。摩拜每天產生的騎行數據超過 30TB,在全球擁有最為全面的騎行大數據,飛速增長的業務使摩拜面臨資料庫擴展與運維的巨大挑戰。
面對飛速增長的並發數與數據量,單機資料庫終將因無法支撐業務壓力而罷工。在摩拜正式上線以來,我們就在不斷思考資料庫擴展和運維的未來,近年來業內對資料庫進行擴展的常見的方案是通過中間件把資料庫表進行水平拆分,將表內數據按照規則拆分到多個物理資料庫中。使用這樣的中間件方案,在資料庫擴容時需要先停下業務,再重構代碼,之後進行數據遷移,對於摩拜這樣與時間賽跑的創業公司來講代價巨大,中間件方案對業務過強的侵入性,不支持跨分片的分散式事務,無法保證強一致性事務的特性都使我們望而卻步。
摩拜單車於 2017 年初開始使用 TiDB,從最早的 RC3、RC4、PreGA、到現在的 1.0 正式版,一步步見證了 TiDB 的成熟和穩定。目前支撐著摩拜內部的實時分析和部分線上業務,同時正在規劃遷移更多的線上業務至 TiDB。
目前,TiDB 在摩拜部署了數套集群,近百個節點,承載著數十 TB 的各類數據。
TiDB 在摩拜的角色和主要應用場景
在摩拜,TiDB 是一個核心的數據交易與存儲支撐平台,引入它的主要目的是用來解決海量數據的在線存儲、大規模實時數據分析和處理。
在我們看來,TiDB 的好處主要有:
- 彈性擴容。具有 NoSQL 類似的擴容能力,在數據量和訪問流量持續增長的情況下能夠通過水平擴容提高系統的業務支撐能力,並且響應延遲穩定;
- 簡單易用。兼容 MySQL 協議,基本上開箱即用,完全不用擔心傳統分庫分表方案帶來的心智負擔和複雜的維護成本,而且用戶界面友好,常規的技術技術人員都可以很高地進行維護和管理;
- 響應及時。因為和 PingCAP 團隊有非常深入的合作關係,所以有任何問題都可以第一時間和 PingCAP 團隊直接溝通交流,遇到問題都能很快的處理和解決。
下面介紹 TiDB 的應用場景:
場景一:開關鎖日誌成功率統計
開關鎖成功率是摩拜業務監控的重點指標之一。
在每次開、關鎖過程中,用戶和鎖信息會在關鍵業務節點產生海量日誌,通過對線上日誌的匯總分析,我們把用戶的行為規整為人和車兩個維度,通過分散式、持久化消息隊列,導入並存放到 TiDB 里。在此過程中,通過對不同的實體添加不同的標籤,我們就能方便地按照地域、應用版本、終端類型、用戶、自行車等不同的維度,分別統計各個類別的開鎖成功率。
按照我們的估計,這個業務一年的量在數百億,所以使用單機的 MySQL 庫需要頻繁的進行歸檔,特別是遇到單機資料庫瓶頸的情況下,擴容更是帶來了非常大的挑戰,這在我們有限的人力情況下,完全是個災難。所以要支撐整個 Mobike 的後端資料庫,我們必須要尋找簡單易用的方案,極大地減少在單個業務上的人力成本開銷。其次,根據我們之前使用分庫分表的經驗,對於這類需要頻繁更新表結構進行 DDL 操作的業務,一旦數據量過大,很很容易出現資料庫假死的情況,不僅影響服務的可用性,更嚴重的是很可能導致數據不一致的情況出現。最後,我們希望不管今後的業務量如何激增,業務需求如何變化,都可以保持業務邏輯可以很方便地升級支持。
在方案設計時,我們進行考察了 MySQL 分庫分表的方案和 TiDB 方案的對比。
我們先估計了可能的情況:
- 新業務上線,在線變動肯定是經常發生的;
- 儘可能存長時間的數據,以備進行統計比較;
- 數據要支持經常性的關聯查詢,支撐運營組的臨時需求;
- 要能支撐業務的快速增長或者一些特殊活動造成的臨時流量。
考慮到這些情況,MySQL 分庫分表的方案就出現了一些問題,首先頻繁變動表結構就比較麻煩,而 TiDB 可以進行在線 DDL。數據生命期比較長,可以設計之初做一個比較大的集群,但是彈性就比較差,針對這個問題,TiDB 可以根據需要,彈性的增加或者減少節點,這樣的靈活性是 MySQL 分庫分表沒有的。另外,數據要支持頻繁的複雜關聯查詢,MySQL 分庫分表方案完全沒辦法做到這一點,,而這恰恰是 TiDB 的優勢,通過以上的對比分析,我們選擇了 TiDB 作為開關鎖日誌成功率統計項目的支撐資料庫。
目前,大致可以將到端到端的延時控制在分鐘級,即,若有開鎖成功率下降,監控端可即時感知,此外,還能通過後台按用戶和車查詢單次故障騎行事件,幫助運維人員快速定位出故障的具體位置。
場景二:實時數據分析
數據分析場景中,TiDB 可以從線上所有的 MySQL 實例中實時同步各類數據,通過 TiDB 周邊工具 Syncer 導入到 TiDB 進行存儲。
這個業務的需求很簡單,我們線上有數十個 MySQL 集群,有的是分庫分表的,有的是獨立的實例。這些孤立的數據要進行歸集以便供業務方進行數據分析。我們一開始計劃把這些庫同步到 Hive 中,考察了兩種方式,一種是每日全量同步,這麼做,對線上的庫壓力以及 Hive 的資源開銷都會越來越大。另一種是增量同步,這種方式非常複雜,因為 HDFS 不支持 update,需要把每日增量的部分和之前的部分做 merge 計算,這種方法的優點是在數據量比較大的情況下,增量同步對比全量同步要更快、更節省空間,缺點是佔用相當一部分Hadoop 平台的計算資源,影響系統穩定性。
TiDB 本身有很多不錯的工具,可以和 MySQL 的生態方便的連接到一起。這裡我們主要使用了 TiDB 的 syncer 工具,這個工具可以方便的把 MySQL 實例或者 MySQL 分庫分表的集群都同步到 TiDB 集群。因為 TiDB 本身可以 update,所以不存在 Hive 里的那些問題。同時有 TiSpark 項目,數據進入 TiDB 以後,可以直接通過 Spark 進行非常複雜的 OLAP 查詢。有了這套系統,運營部門提出的一些複雜在線需求,都能夠快速簡潔的完成交付,這些在 Hadoop 平台上是無法提供這樣的實時性的。
目前,該集群擁有數十個節點,存儲容量數十 T,受益於 TiDB 天然的高可用構架,該系統運行穩定,日後集群規模日益變大也僅需簡單增加 x86 伺服器即可擴展。後台開發、運維、業務方等都可以利用 TiDB 的數據聚合能力匯總數據,進行數據的匯總和分析。
場景三:實時在線 OLTP 業務
如前所述,對比傳統的分庫分表方案,TiDB 的靈活性和可擴展性在實時在線業務上優勢更加明顯。
根據我們的測試,TiDB 在數據量超過 5 千萬時,對比 MySQL 優勢較大,同時協議層高度兼容 MySQL,幾乎不用修改業務代碼就能直接使用,所以 TiDB 集群對於數據量大的實時在線業務非常適合。
目前,摩拜主要上線了兩套在線 OLTP 業務,分別是摩豆信用分業務和摩豆商城業務。
摩豆信用分業務
摩拜單車信用分業務與用戶騎行相關,用戶掃碼開鎖時先行查詢用戶信用積分判斷是否符合騎行條件,待騎行完成後,系統會根據用戶行為進行信用分評估並進行修改。當單車無法騎行,上報故障核實有效後增加信用分、舉報違停核實有效後降低信用分;但是如果不遵守使用規範,則會扣除相應的信用分;例如用戶將自行車停在禁停區域內,系統就會扣除該用戶的部分信用分作為懲罰,並存檔該違停記錄。當用戶的信用分低於 80 分時,騎行費用將會大幅上升。
摩豆商城業務(APP 中的摩拜成就館)
魔豆商城業務即摩拜成就館,用戶的每一次騎行結束後,系統會根據騎行信息贈送數量不等的省時幣、環保幣、健康幣作為積分,通過積累這些積分可以在摩拜成就館內兌換相應積分的實物禮品。
這些業務的共同特點:
- 7*24*365 在線,需要系統非常健壯,在任何狀況下保證穩定運行;
- 數據不希望刪除,希望能一直保存全量數據;
- 平時高峰期並發就非常大,搞活動的時候並發會有幾倍的增長;
- 即便有業務變更,業務也不能暫停。
由於是典型 OLTP 場景,可選項並不多,而且數據量增長極快,這些資料庫的數據在一年內輕鬆達到數百億量級。這些場景在我們有了 TiDB 的使用經驗以後,發現 TiDB 的所有特性都非常契合這種海量高並發的 OLTP 場景。TiDB 的容量/並發可隨意擴展的特性不在贅述,支持在線 DDL 這個特性特別適合這些業務,有需要業務更改不會阻塞業務,這是我們業務快速迭代比較需要的特性。
目前,這兩個在線 OLTP 集群擁有數十個節點,百億級數據,上線以後非常穩定,PingCAP 客戶支持團隊也協助我們進行該集群的日常運維工作。
場景四:違章停車記錄/開鎖簡訊庫等日誌歸集庫
相對於傳統的針對不同的業務分別部署 MySQL 集群的方案,TiDB 在可擴展性和在線跨庫分析方面有較大優勢。
在部署 TiDB 之前,摩拜面對新增的業務需要對其進行單獨的規劃和設計,並根據業務的數據量,增速以及並發量設計 MySQL 的分庫分表方案,這些重複的預先設計工作在所難免。另一方面,不同業務之間往往是有關聯的,當運營部門需要不同業務的匯總數據時,就變得異常麻煩,需要新建一個臨時的數據匯總中心,例如新建一套 MySQL 分庫分表的集群,或者臨時向大數據組申請 Hive 的空間,這都讓數據提供的工作變得麻煩。
有了 TiDB 以後,此類業務的開發和數據提供都變得非常簡單,每次新需求下來,只需要按照新增數據量增加 TiKV 節點的數量即可,因為整個集群變得比較大,並發承載能力非常強,基本不需要考慮並發承載能力。特別的好處是,因為這些業務有相關性的業務,放在一個獨立的資料庫中,運營需要提供某幾類某段時間的數據時就變得極為方便。
基於 TiSpark 項目,Spark 集群可以直接讀取 TiDB 集群的數據,在一些運營需要實時數據提供的場景,不再需要按照原有的提供數據到大數據平台,設計 ETL 方案,運營再去大數據部門溝通運算邏輯。而是直接在 TiDB 現有數據的基礎上,直接提出複雜的分析需求,設計 Spark 程序進行在線的直接分析即可。這樣做,我們非常容易就可以實現一些實時狀態的分析需求,讓數據除了完成自己的工作,還能更好的輔助運營團隊。
使用過程中遇到的問題和優化
在說優化問題之前,先看 TiDB 的架構圖,整個系統大致分為幾個部分。
其中:
- PD 是整個集群的管理模塊,負責:元信息管理、集群調度和分配全局遞增非連續ID。
- TiDB,是客戶端接入層,負責 SQL 解析、執行計劃優化,通過 PD 定位存儲計算所需數據的 TiKV 地址。
- TiKV,是數據的存儲層,底層是基於 RocksDB 的KV引擎,並在其上分別封裝 MVCC 和 Raft 協議,保證數據的安全、一致。
- TiSpark,是 Spark 接入層,負責把 Spark 和 TiKV 連接到一起,在執行非常重的 OLAP 業務時可以利用到 Spark 集群的優勢。
在使用過程中,遇到過不少問題,但是在我方和 PingCAP 技術團隊的充分交流和協作下,都得到了比較完善的解決,下面挑選最為重要的資源隔離與優化展開。
TiKV 中數據存儲的基本單位是 Region,每個 Region 都會按順序存儲一部分信息。當一個 Region 包含多個表的數據,或一台機器上有多個 Region 同時為熱點數據時,就容易產生資源瓶頸。
PD 在設計之初考慮了這方面的問題(專門設計了 HotRegionBalance),但是,它的調度粒度是單個 Region,並且,整個調度基於這樣的假設:即每個 Region 的資源消耗對等,不同 Region 之間沒有關聯,同時盡量保持 Region 均攤在所有 Store。
但當一個集群同時承載多個庫,或一個庫中包含多個表時,發生資源瓶頸的概率會明顯提升。
針對這個問題,我們和 PingCAP 技術團隊合作,對 TiDB 做了以下優化。
優化一:基於 Table 的分裂
這個修改的目的是解決小表數據的相互影響的問題。
當有新表數據插入某一 Region 時,TiKV 會根據當前 Region 的 Key Range 計算出 tableID,如果發現插入的 Key 不在這個 KeyRange 中,會對這個 Region 提前分裂,這就保證了每個 Region 只包含一個表的數據。
優化二:表級別的資源隔離
與此同時,我們在 PD 增加了 TableID 和 Namespace 之間的映射關係以及 NameSpace 和 TiKV Store 的映射關係,通過把上述關係持久化到 eEtcd 里,保證該映射關係的安全。
當數據插入時,可以在 TiDB 層面拿到 TableID,進而從 PD 找出目標 Region 所在的 TiKV,保證新插入的數據不會放到其他 TiKV。
另外,我們還與 PingCAP 團隊共同開發實現了一個 NameSpace 調度器,把未規整的 Region 調度回它應在的 TiKV 里,進而在表級別保證數據不會相互干擾。
優化三:管理工具
最後的問題是管理 NameSpace 的問題。
好在 TiDB 在早期設計時保留了足夠的靈活性,通過 TiDB 原有介面,我們只需要調用相關 API 即能通過表名拿到 TableID。
同時我們在 PD 的命令行管理台 pc-ctl 中增加了 HTTP 介面,管理確認 Table Name 和 Table ID 之間的對應關係。
後記
部署 TiDB 近一年來,摩拜單車經歷了用戶數量近十倍,日騎行數據數十倍的增長,依靠 TiDB 在線擴容的能力,我們完成了多次資料庫擴容與伺服器更換,而且這些操作對業務是完全透明的,我們可以更專註於業務程序的開發與優化,而無須了解資料庫的分片規則,對於快速成長的初創公司,這有著很強的借鑒意義。另外深度參與 TiDB 的開發並和開源社區緊密的互動,也使我們獲得了很多有益的反饋,極大降低了代碼維護成本。
未來,我們會聯合 PingCAP 進一步豐富多集群的管理工具,進行更深入的研究和開發,持續提升 TiDB 的性能,將 TiDB 應用到更多的業務中。
推薦閱讀:
※日均數據量千萬級,MySQL、TiDB 兩種存儲方案的落地對比
※三篇文章了解 TiDB 技術內幕——說存儲
※TiDB 在 360 金融貸款實時風控場景應用
※TiDB Brings Distributed Scalability to SQL