伴魚數據庫選型的思考,爲何咱們 all in TiDB

做者:伴魚技術團隊程序員

技術選型是由技術方向和業務場景 trade-off 決定的,脫離業務場景來講技術選型是沒有任何意義的,因此本文只是闡述了伴魚技術團隊數據庫選型的過程,這並非 MySQL、MongoDB 和 TiDB 之間直接的比較,只能說明 TiDB 更適合伴魚的業務場景和技術規劃,另外因爲 TiDB 是很是新的數據庫技術,因此這也能體現出伴魚技術團隊對新技術的態度、技術後發優點的理解、成本與效率的衡權和技術生態與紅利的思考。數據庫

爲何放棄 MongoDB?

伴魚是 2015 年成立的,那個時候 NoSQL 還如日中天,關係型數據庫爲了應付海量的數據只能業務侵入式的分庫分表,雖然 Google 在 2012 年發佈了 NewSQL 數據庫 Spanner 的論文,可是工業界尚未一款可使用的 NewSQL 數據庫,綜合當時的各類狀況,伴魚選擇的是 MongoDB。後端

不過,在 2015 年到 2017 年之間,對於伴魚來講 MongoDB 確實是一個上佳之選,主要有如下幾個方面的緣由:緩存

  • 開發更高效:公司初期處於探索期,產品迭代很是快,MongoDB 是 NoSQL 數據庫,不須要作建庫建表等 DDL 操做,特別在產品快速迭代,須要頻繁增減字段的時候就更高效,固然這個也是有代價的,從本質上來講,MongoDB 是讀模式,它幾乎不檢查寫入的內容是否合法,對數據 Schema 的解釋是在應用程序的代碼中,致使寫入數據的約束性是沒有保證的。
  • 運維更高效:當時公司研發很是少,這段時間整個後端只有兩個工程師,沒有專職的運維和 DBA ,可是 MongoDB 的單機性能比 MySQL 要高很多,不但對數據庫的運維成本要低很多,而且當時除了幾個熱點庫外,其餘的庫 MongoDB 能夠直接扛住流量壓力,省去了中間的 Cache 層,讓開發和運維都更高效。
  • 有事務需求的場景很少:當時使用的是 MongoDB 2.x 和 3.x,只提供了數據一致性的選擇(強一致性、單調一致性和最終一致性)和原子操做,在少數的幾個場景,好比交易相關的場景,經過選擇強一致性和原子操做,再在應用層實現 MVCC 的機制,能夠知足簡單的事務需求。

整體來講,在伴魚產品的探索期,爲了效率犧牲一點數據約束性和事務能力是值得的,可是 2017 年末伴魚產品方向比較明確後,業務場景從探索期轉變到快速發展期,對數據庫的需求從效率優先轉變爲效率、事務能力與生態並重:安全

  • 有事務需求的場景急增:事務場景從最初與錢相關的交易擴展到一些虛擬貨幣,而且因爲併發量的增長,以前沒有事務保障的場景出現競爭的狀況愈來愈多,還在應用層經過 MVCC 機制實現簡單的事務是很是低效的,而且在應用層實現事務的正確性也是很難保證的。(一個有趣的故事:Jeff Dean 曾經說過本身對 Bigtable 最後悔的事情是沒有提供跨行事務支持,致使業務就會在上層企圖本身搞事務,而且業務實現的分佈式事務大部分都是錯的,因此在後來的 Spanner 數據庫中 Jeff Dean 直接提供了官方分佈式事務支持。)
  • 對大數據生態的需求急增:在產品探索期的時候,也有很強的數據分析需求,不過當時數據總量小,在 MongoDB 的隱藏從庫中直接分析就足夠了,可是產品快速發展期,數據量急劇增長,在 OLTP 數據庫中進行 OLAP 操做已經力不從心了。可是經過大數據生態來進行數據分析,對於 MongoDB 來講有一個很是殘酷的現實,基本全部的大數據生態都是圍繞 MySQL 生態打造的,若是想接入 MongoDB 的數據,意味着須要從新大量造輪子。
  • 對數據約束性的要求更高:因爲業務快速的發展,服務可能會出現多人維護和移交的狀況,若是存儲的數據沒有約束,意味着存儲的數據 Schema 是不可控的,這很容易讓後面參與的工程師崩潰和掉進坑裏,這個時候數據的約束性變成是一個更高優秀級的需求,關係數據庫的寫模式變成更好的選擇。

到產品快速發展期,因爲業務場景對數據庫的需求已經發生了很大的改變,因此在這個時候,伴魚技術團隊開始謹慎思考數據庫從新選型的問題,咱們理想型的數據庫是這樣的:微信

  • 高可用;
  • 高吞吐;
  • 支持 ACID 事務;
  • 大數據生態友好;
  • 有水平擴張能力,而且儘可能作到不侵入業務;

基於上面這些需求,咱們開始了數據庫的從新選型之路。架構

初識 TiDB

早在 2015 年的時候我就很是關注分佈式數據庫,當時已經經歷太高併發高 QPS 的場景,利用分佈式架構解決無狀態高併發高 QPS 場景是不復雜的,可是分佈式存儲因爲涉及到一致性問題是很是有挑戰的,若是還想支持 ACID 事務那就更難了,因此當時就對分佈式數據庫技術特別感興趣,開始關注 OceanBase 而且收集和研究相關的理論和架構文檔。併發

後來同事推薦說有個叫 TiDB 的數據庫,目前有些公司也在用了,反饋也不錯,因此咱們決定調研一下。TiDB 官網的文檔作的很是友好,不管是理論仍是架構的文章都很是齊全,幾乎一口氣就把全部的文章都看了一遍(當時文章比如今要少),完備的理論支持、優雅的架構設計、與 Google Spanner 一脈相承的設計思路讓咱們對 TiDB 的前景很是看好,而且功能上徹底知足咱們的要求,因此當時就決定長期關注 TiDB,而且準備進行初步驗證。運維

初步驗證

經過調研咱們發現,TiDB 是經過 raft 協議來保證多副本數據的一致性( ACID 中的 C ),經過 2PC 協議來保證事務的原子性( ACID 的 A ),經過樂觀鎖加 MVCC 來實現可重複讀的事務隔離級別( ACID 中 I ),這意味着 TiDB 每一次事務的成本是比 MySQL 要高不少的,特別是有事務衝突的時候(樂觀鎖的緣由),因此性能是須要驗證的關鍵點。異步

當時伴魚全部的業務都部署在阿里雲上(如今有自建機房),就直接在阿里雲上面按 TiDB 的配置要求購買了機器,當時安裝的是 TiDB 1.x 的版本。由於 TiDB 官網已經有 Sysbench 的壓力測試數據,這個性能數據是符合咱們需求的,因此決定對咱們的業務場景進行一次徹底模擬的長期測試:伴魚 IM 的併發比較高,而且採用寫擴散的設計,對數據庫的要求會比較高,因此適合進行驗證。經過對 IM 業務的 inbox 表進行雙寫,業務同步寫 MongoDB 和異步寫 TiDB,業務讀只讀 MongoDB,這樣若是 TiDB 有問題也不會影響線上業務。

在低峯期對 IM 業務開啓雙寫後,TiDB 監控的 999 線和 99 線還知足要求,可是全部 TiKV 節點的 io 使用率一直在 90% 附近波動,這個若是到高峯期是絕對會有問題的,經過重讀 TiKV 的配置,在修改配置項 sync-log = false 後,TiKV 的 io 使用率維持在 5% 如下,當天的高峯期也一切正常,沒有出現問題。

在這以後,咱們對 IM 的雙寫觀察 2-3 個月的時間,在確認一切正常後,再將同步讀寫都修改成 TiDB 而且異步寫 MongoDB,一切正常而且持續觀察。

sync-log 配置是控制 TiKV 數據多副本進行 raft 協議同步的時候,若是 sync-log=false,則內存中處理完成就返回 ack,對於 3 副原本說,單節點故障是不會丟失數據的,同一個 raft 集的 2 個副本同時故障可能會出現丟數據的狀況,這個問題除了金融等對數據安全性要求很是高的場景外,其餘的業務場景是能夠接受的,而且 MySQL 等其餘數據庫的集羣方案在 master 節點故障的時候問題更大。

深度交流

在前面初步驗證 TiDB 的過程當中,一個看似很嚴重的問題可是調整一個配置就能夠解決,這讓咱們發現了咱們對 TiDB 的理解和控制力還不夠,在對每個配置都進行理解研究外,還有一些咱們很是關心的問題但沒有官方答案。若是對這些問題沒有官方答案,那麼咱們直接使用 TiDB 就是有很大風險的,因此咱們決定和 TiDB 團隊進行一次深度的交流。

咱們當時很是關心的問題列表爲:

  • T- iKV 的線性擴展能力怎麼樣?
  • 兩地三中心架構,TiDB 能夠容忍數據中心之間的延遲是多少?
  • 目前業界 TiDB 最大的一個集羣的 TiKV 和 TiDB 的節點數、數據量、QPS 最高是多少?
  • TiDB 哪一些配置是須要特別關注和調整的?

收集了大概 20 多個問題,得益於伴魚和 TiDB 都在北京,離得還很是近,在線上聯繫上而且約好時間後,和 TiDB 進行了第一次深度的交流。

大概是 2018 年上半年的一天,我和 TiDB 的 3-4 個同事聊了一整個上午,基本都是我將收集到的問題一個個拋出來,你們一塊兒討論。整個交流過程解答了不少咱們關心的問題,也瞭解到當前業界對 TiDB 的使用狀況,大大加強了咱們對 TiDB 的信心,對於數據庫的選型來講,這是很是關鍵的事情。

爲何不選擇 MySQL?

通過對 TiDB 的調研、試用和深刻交流後,在傳統的關係型數據庫 MySQL 和 NewSQL 數據庫 TiDB 之間,咱們須要作出本身的選擇了,這不只僅是兩個數據庫之間的選擇,這其實也體現了伴魚對新技術的態度、技術後發優點的理解、成本與效率的衡權和技術生態與紅利的思考。

對新技術的態度

伴魚對新技術的態度是很是積極的,若是業務場景須要的新技術咱們都會去了解它、研究它和掌握它,咱們相信咱們對新技術趨勢的判斷能力和掌控能力,因此在 TiDB 和 MySQL 的選型的過程當中,MySQL 確實是很是穩的選擇,而且對咱們的需求目前都有現成的解決方案,好比高可用,好比水平擴展能力,只不過不是很是優雅的解決方案,可是 TiDB 不管是理論層面和架構層面都比 MySQL 高出一個時代(MySQL 是面向單機數據庫設計的,是這個領域很是優秀的數據庫,只是如今伴魚想要解決的是單機沒法存儲的海量數據場景,在這個維度上比較確實 TiDB 更好一些,可是這並非 MySQL 的問題,是由於它們的設計目標不一樣而已),可是穩定性和成熟度會比 MySQL 要差一些,這個時候,咱們選擇相信咱們對 NewSQL 技術方向的判斷力和掌控力,相信 TiDB 的進化能力,相信時間站在咱們這邊,讓子彈再飛一會。

技術後發優點的理解

伴魚在以前用的數據庫是 MongoDB,MySQL 和 TiDB 都沒有用過,若是咱們判斷 TiDB 更面向將來的數據庫,那麼咱們是先從 MySQL 開始,走一遍 MySQL 的道路,在後面可預見的將來再遷移到 TiDB 上來;仍是直接深刻研究和掌握 TiDB,直接 All in TiDB?

初創公司在技術沉澱和積累上是遠遠不及一些成熟公司的,這些沉澱和積累就是成熟公司在技術上的先發優點,當技術沒有出現變革的時候咱們沒有選擇,可是當技術正出現重大變革的時候,若是咱們還作一樣的技術選型,那麼也須要花一樣的時間和成本才能達到成熟公司的水平,而後等你們都開始遷移到新的技術上的時候,這些技術沉澱和積累就可能會變成技術債務。

因此初創公司應該去預判技術趨勢,選擇面向將來的技術,在技術上彎道超車,避免本身的技術債務,這個是伴魚技術團隊對技術後發優點的理解。

成本與效率的衡權

成本和效率是技術選型繞不過的關鍵點,對於數據庫來講更是如此,由於數據庫須要的機器等資源成本會佔總資源成本的很大一部分,因此伴魚技術團隊在 TiDB 和 MySQL 作選擇的時候,對成本與效率進行了深度的評估。

Unix 哲學是通過時間和實踐的錘鍊設計原則,不少時候也是伴魚技術團隊的實踐原則,好比 Rule of Economy :「寧花機器一分,不花程序員一秒」。在技術選型上,咱們是老是指望基礎軟件作更多的事情,業務研發作更少的事情,若是業務研發須要在業務層去作本來基礎軟件應該作好的事情,那其實就是基礎軟件的抽象泄漏了。若是基礎軟件抽象泄漏,必然會致使業務層重複去解決這個問題,這個實際上是很是大的隱性成本。

MySQL 相比較 TiDB 而言,集羣的高可用和大表須要分庫分表其實就是 MySQL 在對面當前需求的抽象泄漏,MySQL 的集羣高可用須要 DBA 和基礎架構團隊花成本去解決,MySQL 的大表分庫分表方案須要 DBA、基礎架構團隊和業務研發團隊花成本去解決,只不過這些都是隱性成本,不像在搭建數據庫集羣的時候,TiDB 比 MySQL 可能須要更多的機器來的簡單直接,因此很容易被忽略了。

因此,對於成本與效率的衡權,伴魚技術團隊更關注工程師的效率,更關注工程師的心情(在業務上層重複解決一些底層軟件抽象泄漏的問題是很影響心情的),更關注隱性成本,而不只僅是帳面明顯能夠比較的資源數字,特別是在機器愈來愈便宜,人才愈來愈值錢的趨勢下。

技術生態與紅利的思考

選擇一個技術,其實也是選擇了這個技術的生態,若是技術生態完善,作事情每每會事半功倍,極大地提升研發效率。TiDB 在這個方面作的很是好,全面兼容 MySQL 協議,讓 TiDB 的用戶享受到 NewSQL 的能力的同時也享受到 MySQL 的生態,這個是很是正確的決定,MySQL 生態是幾十年的積累,不是一朝一夕能夠作到的。

另外一方面,在選擇面向將來、優雅高效的解決方案,仍是選擇成熟的但不夠優雅和高效的解決方案,若是選擇成熟的解決方案,對技術的掌控會比較高,可是會在效率方面持續的進行付出;若是選擇面向將來的解決方案,須要花時間和精力來掌握新技術,可是新技術會優雅和高效的解決問題,咱們認爲這個就是技術的紅利。好比對於大表的解決方案,MySQL 提供的解決方案是分庫分表,業務研發和 DBA 一塊兒配合很是低效地解決這個問題,可是對於 NewSQL 的 TiDB,單表幾乎能夠理解爲無限大的(業界已經存在 100 億以上的表),從根本上解決了這個問題。如今伴魚的大表都從 MongoDB 遷移到 TiDB 上面,業務研發和 DBA 再也不爲數據的增長而不停地進行分庫分表,這個就是巨大的技術紅利。

因此,基於上面的一些討論與思考,伴魚決定 All in TiDB,MongoDB 再也不增長新的庫和表,正在使用 MongoDB 的業務繼續使用,而且對 MongoDB 上的大表進行有計劃的遷移,避免進行分庫分表操做。

踩過的坑

在徹底掌握一項新技術前,享受新技術的紅利是有代價的,特別是伴魚在 TiDB 比較早期的時候就決定 All in,這很考驗技術團隊的學習和進化能力、新技術的社區和官方提供的技術支持的能力。在 TiDB 這件事情上,伴魚技術團隊和 TiDB 的技術支持團隊都作的很是優秀了,可是咱們從 TiDB 1.x 到目前的 3.x 的過程當中依然仍是踩了一些坑。

優化器選擇索引問題

單表數據 30W+,查詢請求併發約 10+,某次業務上線,新增一個索引後,致使原有的查詢索引選擇錯誤,TiKV 實例所在機器 cpu 迅速被打滿,引起故障。

線上某張大表,請求量比較大,偶爾出現個別條件走不到索引,致使全表掃描,從而引起接口響應時間的抖動,影響業務。

線上某張 14 億的大表,查詢條件區分度很高,某天出現特定條件忽然走不到索引,致使全表掃描,引起故障。後面通過 TiDB 同窗排查,系 bug 致使。

優化器選擇索引問題,TiDB 從 1.x 到 3.x 的過程當中,優化器表現愈來愈好,同時伴魚 DBA 團隊經過性能監控和慢日誌監控提早快速地發現問題,而且對大表採用強制索引的方式避免隱患,目前這個問題已經比較完全的解決了。

大數據同步問題

爲了進行數據分析,咱們把上游各 TiDB 集羣的數據經過 Pump / Drainer 匯聚到一個 TiDB 集羣供大數據分析使用,在使用過程當中,遇到數據不一致、數據同步慢和編碼不一致致使同步失敗等問題。

隨着伴魚的 DBA 團隊深度研究 TiDB 而且和 TiDB 的同窗進行持續的深刻溝通,目前對 TiDB 的掌控力愈來愈強,大數據同步問題目前已經獲得解決。

如今的狀況

如今伴魚有 10 套 TiDB 數據庫,110+ 數據庫實例,6 個 TPS 過萬核心集羣,999 線基本維持在 16ms 左右,響應時間和穩定性都達到預期。從目前的狀況來看,伴魚選擇 TiDB 是一次很是正確的選擇,咱們在數據庫技術方面彎道超車,避免了對 MySQL 技術的重複建設與積累,享受了 NewSQL 數據庫 TiDB 在高可用和水平擴展等方面的技術紅利,大大提升了業務研發和 DBA 的工做效率。 固然,這是伴魚技術團隊(特別是 DBA)和 TiDB 技術團隊共同努力的結果。

這裏還要特別提一點,TiDB 每一次版本升級都會帶來驚喜,這是一個能夠持續享受的技術紅利。

寫在後面的話

目前,在摩爾定律失效、業務的高可用要求和成本優化等綜合的大環境下,分佈式架構是技術潮流的大勢所趨,流量路由策略加多副本部署(微服務是其中的一種架構形式)解決了無狀態服務的分佈式架構問題,Redis Cluster 和 Codis 等方案解決了緩存的分佈式架構問題,Kubernetes 完成了操做系統的分佈式進化,數據庫領域天然也不會例外,它的分佈式架構趨勢必定是不可阻擋的。要特別說明一下,這裏所說的解決問題是指系統性的解決問題,MySQL 業務侵入式的分庫分表確實是一個能夠解決問題的分佈式架構方案,可是須要業務研發配合一個業務場景一個業務場景的去解決,這就不能稱之爲系統性的解決方案,由於在解決這個問題方式上,業務侵入式的分庫分表方案將本應由數據庫處理好的大表抽象泄漏給業務層了,在這個問題上,咱們認爲 NewSQL 是一個系統性的解決方案,而 TiDB 就是當下很是不錯的一個選擇。

另外還須要說明一點的是,這是一篇數據庫選型的文章,因此只記錄了與之相關的內容,好比詳細描述了伴魚技術團隊在將數據庫遷移到 TiDB 後踩的坑,由於這是咱們數據庫選型 TiDB 付出的代價,因此必定要詳細記錄;沒有記錄在使用其餘數據庫踩的坑,這並不表明咱們沒有踩到,好比在使用 MongoDB 的過程當中也踩過一些坑,可是由於這並非咱們決定從新作數據庫選型的緣由(決定從新選型的緣由見文章「爲何放棄 MongoDB」部分),因此就沒有在文章中記錄。

本文轉載自 InfoQ 微信公衆號,點擊查看原版文章 《咱們爲何放棄 MongoDB 和 MySQL,選擇 TiDB》
相關文章
相關標籤/搜索