摘要:2017 年,在騰訊雲服務了百萬客戶之後,由開源數據庫適配業務和具體場景,騰訊雲自主研發了數據庫 CynosDB,它將傳統數據庫與雲計算的優勢相結合,解決了傳統數據庫雲上的難題,其設計思路可以概括爲以下幾點:。與此同時,騰訊雲數據庫產品總監王義成還向記者透露,CynosDB 的技術能力以及存儲層早已具備按使用量計費的能力,計算層也正在進行相應的適配,待 CynosDB 商業化後將逐步推上日程。

早在上個世紀 50、60 年代,“數據”二字就已不再是簡單的數字信息而已。隨着信息技術的不斷發展,在計算機應用領域,計算機存儲和處理的對象逐漸廣泛,表示這些對象的數據也隨之變得越來越複雜,數據庫這一門新興學科的應用也越來越廣泛。縱觀國內幾大雲服務商過去幾年在雲數據庫領域的發展,騰訊雲基於自身的業務場景以及技術研發能力,在雲數據庫市場上也經歷了蟄伏、發展與突破。

2012 年,伴隨着騰訊宣佈歷史上第二次組織架構調整,騰訊雲數據庫 MySQL 高性能版、CKV 兼容 Memcached 版本的推出,也正式開啓騰訊數據庫新時代。
2016 年,馬化騰首次公佈過去 18 年騰訊存儲總數據量超過 1000 個 PB,面對如此龐大的數據量,騰訊金融分佈式數據庫 TDSQL 商業化進程就此展開。
2018-2019 年,當“上雲”已成常態,在特定場景下重磅升級後的騰訊雲數據庫(TencentDB)也應運而生。

在 2019 年 5 月 21 日舉辦的騰訊全球數字生態大會上,InfoQ 記者也有幸與騰訊雲數據庫產品總監王義成做了一次深度對話,詳細回顧了騰訊雲數據庫七年變遷之路。

騰訊雲數據庫演進史

跟很多互聯網公司不同的是,騰訊初始的業務發展並未對數據庫有過強依賴。

與最初需使用 Oracle,SQL Server 等商業數據庫的 IOE 廠商相比,騰訊雲數據庫的起步是從 KV 與存儲分析的類型開始。直到當財付通和微信紅包這類的業務產生後,這才逐步促使着關係型數據庫的使用,因此騰訊內部是沒有一個去 IOE 的過程。那麼騰訊是以何種路線逐步進階數據庫的?

這還得先從騰訊雲數據庫的發展歷程說起,其發展歷程總體來說可以分爲兩條線:

  1. 迎接開源——開源定製參與回饋開源——爲雲而生定製——適配客戶需求;

一開始,騰訊雲數據庫建設主要引入了當時業界較爲主流的開源數據庫,如 MySQL,Redis,PostgreSQL 等。隨後針對雲上客戶定製需求,騰訊雲在數據庫中衍生研發瞭如數據庫並行複製、審計日誌、在線加字段等核心功能,並將以上功能回饋給了 MariaDB 和 MySQL 社區。

  1. 內部自研——業務倒逼技術發展——雲化支撐——走進互聯網及傳統行業。

之後,騰訊雲開啓了數據庫自研的道路,其自研數據庫典型代表是 TDSQL、CKV 以及 CynosDB 等產品。隨着財付通、微信紅包等業務的爆發性增長,對數據庫穩定性、安全性和數據一致性的需求也倒逼着自研數據庫技術的不斷發展和成熟。接下來,騰訊雲在服務越來越多的雲上用戶,並向企業級用戶進發後,也逐步開始對外輸出到金融、政府等傳統行業,因此對數據庫的要求也越來越高。

王義成在受訪時回憶說,在這段發展歷程中,騰訊·財付通剛成立的時候是對內部數據庫依賴最強的時候。2003 年,騰訊的數據庫從開源數據庫 MySQL,到適配業務而自研 MySQL,當財付通業務真正發展起來後,業務需求就開始持續倒逼騰訊雲數據庫產品的演進。

因此,騰訊數據庫的發展更多是在初始就已選擇用開源數據庫來承接。而此後,由於騰訊海量用戶的存儲需求與業務爆發性的增長,倒逼騰訊更加理解開源,進而在開源的基礎上,適配業務進行數據庫的自研迭代。

從開源到適配

作爲一個產品驅動型的企業,當產品的大方向確定之後,騰訊會驅動技術做相應選型,比如財付通的研發,就需要一款交易類型的關係型數據庫來支撐。但在任何一款數據庫產品研發之前,騰訊都需要預測數據未來可能到達的量級。值得注意的是,無論是成本的壓力也好,或者說業務的壓力也罷,都並不足以驅使當時的騰訊選配 Oracle 等商業數據庫。

因此,騰訊必須選擇一條成本與基礎能力均可控的方式——在開源的基礎上,慢慢地演變自身業務,把單節點變成雙節點,再把雙節點進行橫向擴展。然而。在提前預測相對合理的業務發展路徑並做出選擇之後,產品的開發過程仍會出現很多的問題,比如交易場景下的查證能力拓展等。

2007 年的財付通,其查證能力在一組多讀的情況下還是存在數據延遲,這對於用戶來說是完全無法接受的。但也是由於這些業務需求,促使了 TDSQL 這款數據庫產品的誕生,其適配了異步多線程的強同步複製方案,這在當時也是領先其他雲計算友商的解決方案。

從適配到自研

而對於騰訊雲自研的數據庫,主要分爲兩類,一類是 爲騰訊內部業務適配而生的自研數據庫 ,比如騰訊金融級數據庫架構 TDSQL;另一類 是基於服務海量客戶後的 經驗 ,騰訊雲在新的場景下,由開源數據庫適配業務自主研發的數據庫 ,比如企業級雲原生數據庫 CynosDB。

第一類是騰訊業務上的突破自研。從某一個歷史結點上來看,那時的開源或商業數據庫的場景是無法滿足業務發展的,因此騰訊雲自研了許多相應的數據庫適配業務的迭代,典型的代表就是 KV 類型的數據庫——CKV,它是由海量存儲衍生的 KV 類型數據庫,以及在線分析數據庫 TBase。

另一類自研數據庫,是在真正服務了很多雲上的客戶後,騰訊雲發現開源數據庫並不能完全滿足用戶的需求,或者說用戶需求即便被滿足,也並未激發出使用雲數據庫的最大價值。用戶數據規模較小的時候,使用騰訊雲的數據庫服務比自建 IDC 節省很多成本,但隨着用戶使用數據庫的規模逐漸擴大,騰訊雲數據庫團隊思考要提供超出用戶想象的產品和服務,節省運維以及人力成本是雲數據庫 1.0 時代的特徵,到了 2.0 時代,雲數據庫要在根本上具備自建數據庫無法比擬的優勢,才能成爲支持用戶業務運轉不可撼動的基石。

這時,分佈式數據庫成爲了用戶自建與雲廠商服務有所區分的關鍵。分佈式數據庫也同樣分兩類,一類是像 MPP 並行計算的數據庫,以及把數據拆分爲多個節點的分佈式數據庫;另一類是當下比較流行的存儲分離數據庫。從工程實踐以及成熟性的角度來看,存儲與計算分離的架構確實是更適合在分佈式數據庫上取得成功的工程實踐,這也成爲騰訊雲佈局自研數據庫的初衷。說到騰訊雲自研數據庫,就不得不提到兩款十分具有代表意義的數據庫——騰訊分佈式數據庫 TDSQL & 企業級雲原生數據庫 CynosDB。

騰訊業務倒逼自研——TDSQL 技術全解析

2002 年,由於當時騰訊的計費產品還處於起步階段,技術團隊選擇完全基於開源 MySQL 構建數據庫體系。爲了解決計費等公司級敏感業務高可用、核心數據的零流失、核心交易的零錯賬等問題,騰訊從 07 年開始自研了一款數據庫產品,這也是 TDSQL 的前身,這款數據庫在當時很好的支撐了 09 年的開放平臺浪潮。

隨着騰訊開放合作的發展擴大,行業場景越來越多,這款數據庫無法很好的爲合作伙伴提供服務,因此從 2012 年開始,由騰訊內部業務適配而衍生的自研數據庫 TDSQL 誕生。那麼,TDSQL 是如何實現自主可控和技術迭代的呢?

TDSQL 架構解析

從架構上講,TDSQL 是 Shared-Nothing 架構的分佈式數據庫;從部署方式來講,TDSQL 是一款支持多租戶的雲數據庫。整體來說,TDSQL 是由決策調度集羣 /GTM,SQLEngine、數據存儲層等核心組件組成的,其每個模塊都基於分佈式架構設計,可以實現快速擴展,無縫切換,實時故障恢復等,通過這一架構,TDSQL 的 Noshard、Shard、TDSpark 實例可以混合部署在同一集羣中。並且使用簡單的 x86 服務器,可以搭建出類似於小型機、共享存儲等一樣穩定可靠的數據庫。

在架構上,TDSQL 的核心思想有兩個:數據的複製(replica)和分片(sharding),其它都是由此衍生出來的。其中,

  • replica 配合故障的檢測和切換,解決可用性問題;

  • sharding 配合集羣資源調度、訪問路由管理等,解決容量伸縮問題。

同時,因 replica 引入了數據多副本間的一致性問題和整體吞吐量下降的問題,而 sharding 的引入也會帶來一定的功能約束。在最終實現上,TDSQL 由 Scheduler、Gateway、Agent 三個核心組件加上 MySQL 組成,其中:

  • Scheduler 是管理調度器,內部又分爲 zookeeper 和 scheduler server;

  • Gateway 爲接入網關,多個網關組成一個接入層;

  • Agent 是執行代理,與 MySQL 實例一起,構成數據節點。多個數據節點構成服務單元 SET。

TDSQL 面向數據一致性考驗

在金融行業,銀行、風控、渠道等第三方通常通過讀寫分離方式來查詢數據,而在互聯網行業,由於 x86 相對較高的故障率,導致數據可能經常性的出現錯亂、丟失場景。爲了解決這個問題,就必須要求主從數據保持強一致和良好的讀寫分離策略。而其中的關鍵在於如何實現強同步複製技術。

由於 MySQL 的半同步和 Galera 模式不僅對性能的損耗是非常大的,而且數據同步有大量毛刺,這給金融業務同城雙中心或兩地三中心架構容災架構帶來了極大的挑戰。爲什麼會這樣呢?

從 1996 年的 MySQL3.1.1.1 版本開始,業務數據庫通常跑在內網,網絡環境基本較好,因此 MySQL 採用的是每個連接一個線程的模型,這套模型最大的好處就是開發特別簡單,線程內部都是同步調用,只要不訪問外部接口,支撐每秒幾百上千的請求量也基本夠用,因爲大部分情況下 IO 是瓶頸。

但隨着當前硬件的發展,尤其是 ssd 等硬件出現,IO 基本上不再是瓶頸,如再採用這套模型,並採用阻塞的方式調用延遲較大的外部接口,則 CPU 都會阻塞在網絡應答上了,性能自然上不去。

爲了解決這些問題,TDSQL 引入了線程池,將數據庫線程池模型 (執行 SQL 的邏輯) 針對不同網絡環境進行優化,並支持組提交方案。例如,在 binlog 複製方案上將複製線程分解:

  1. 任務執行到寫 binlog 爲止,然後將會話保存到 session 中,接着執行下一輪循環去處理其它請求了,這樣就避免讓線程阻塞等待應答

  2. MySQL 自身負責主備同步的 dump 線程會將 binlog 立即發送出去,備機的 io 線程收到 binlog 並寫入到 relaylog 之後,再通過 udp 給主機一個應答

  3. 在主機上,開一組線程來處理應答,收到應答之後找到對應的會話,執行下半部分的 commit,send 應答,綁定到 epoll 等操作。綁定到 epoll 之後這個連接又可以被其它線程檢測到並執行。

改造後, TDSQL 基本可以應對複雜的網絡模型。

但上述方案還有小缺陷:當主機故障,binlog 沒有來得及發送到遠端,雖然此時不會返回給業務成功,備機上不存在這筆數據,然而在主機故障自愈後,主機會多出來這筆事務的數據。解決方法是對新增的事務根據 row 格式的 binlog 做閃回,這樣就有效解決了數據強一致的問題。

基於規則和基於代價的查詢引擎

當前大多數分佈式數據庫都設計的是基於規則的查詢引擎 (RBO),這意味着,它有着一套嚴格的使用規則,只要你按照它去寫 SQL 語句,無論數據表中的內容怎樣,也不會影響到你的“執行計劃”,但這意味着該規則複雜的數據計算需求不“敏感”。雖然金融業務都有自己的數據倉庫,然而也會經常需要在 OLTP 類業務中執行事務、Join 甚至批處理。

TDSQL 在 SQLENGINE 實現了基於代價的查詢引擎 (CBO),SQL 經過 SQLENGINE 的詞法、語法解析、語義分析和 SQL 優化之後,會生成分佈式的查詢計劃,並根據數據路由策略(基於代價的查詢引擎)進行下推計算,最後對彙總的數據返回給前端。

而作爲分佈式的計算引擎,在存儲與計算引擎相分離的情況下,非常重要的一環就是如何將計算儘量下推的下面的數據存儲層。因此 TDSQL 的 SQLENGINE 在經過大量業務打磨後,實現了基於 shard key 下推、索引條件下推、驅動表結果下推、null 下推、子查詢下推、left join 轉化成 inner join 等多達 18 種下推優化手段,儘量降低數據在多個節點傳輸帶來的壓力,以提供更好的分佈式查詢的能力,支撐金融交易的關聯操作。

開源數據庫適配自研——CynosDB 技術全解析

伴隨着雲計算時代的到來,雲數據庫服務常被大家理解爲,雲廠商直接把傳統數據庫搬到雲上,讓客戶以租用的方式獲得服務。但由於傳統數據庫在雲上的資源利用率低、擴展能力不足、資源規劃難,以及備份難等缺點,使得傳統數據庫無法完全釋放雲上得天獨厚的擴展性、可靠性和規模化等優勢。

2017 年,在騰訊雲服務了百萬客戶之後,由開源數據庫適配業務和具體場景,騰訊雲自主研發了數據庫 CynosDB,它將傳統數據庫與雲計算的優勢相結合,解決了傳統數據庫雲上的難題,其設計思路可以概括爲以下幾點:

  1. 首先是計算存儲分離,比如把運算 CPU 或者內存放在一起統一分配,可以獲得彈性調度能力。

  2. 第二個是日誌下沉及異步回放,同時我們移除了數據頁面的刷髒邏輯,這樣降低了計算存儲分離的架構下的網絡開銷。

  3. 第三個就是分佈式存儲,這也是我們騰訊雲自研的分佈存儲系統,共享的分佈式存儲可以橫向擴展。

  4. 第四個是後臺的持續日誌備份,傳統數據庫我們的備份是在數據庫主機上去拷日誌完成備份,而 CynosDB 的持續備份是在存儲上進行,不干擾數據庫實例,減輕由於備份的工作任務對數據庫的衝擊,並且用戶可以不必關心備份策略和備份存儲資源規劃。

計算存儲分離架構的實現和優化

傳統數據庫的優化演進歷史,基本上是和 IO 做鬥爭的歷史,因爲數據庫是有狀態、重 IO 的服務,傳統 MySQL 架構有多個 IO 類型,存儲相同的文件,所以主機和備機的磁盤會有很多相同的 IO 和冗餘的文件。即便數據庫被搬上雲,爲了在雲上做彈性的擴容,開發者依然面臨傳統數據庫所面臨的問題。

基於以上痛點,CynosDB 引入計算存儲分離的架構,存儲層使用共享的分佈式塊存儲雲服務,計算層則將不必要的 IO 全部卸載,實現計算與存儲基於日誌傳輸的新架構。

CynosDB 架構有如下幾個特點:

  1. 日誌即數據庫。架構中只有日誌流,因而只有日誌能表達數據庫;

  2. IO 卸載。除了日誌,其他所有類型 IO 全部卸載,如數據文件、源數據文件、biglog 文件等;

  3. 無狀態。本地文件將不復存在,包括日誌文件,所以計算層是無狀態的。

在新架構中,日誌處理無可厚非具有非常重要的作用。其中連續的日誌在存儲層被打散成了很多的小的分片,分別存儲在不同的 cell 裏。而日誌處理的邏輯是將存儲引擎將日誌發給存儲節點,存儲節點將日誌放到一個日誌隊列裏面,並將其持久化,之後立即返回給存儲引擎,當存儲引擎獲得日誌的反饋後就可以將一部分事務提交。其中,存儲節點會異步的進行一些操作,這些操作和事務的提交過程無關,不影響事務的提交響應速度。

而在數據庫裏面,如果 buffer 足夠的話,數據庫的寫性能是和日誌的落盤時間相關的,傳統數據庫組提交機制可能存在幾個問題,一是如果有大量的連接進來,MySQL 將會爲每一個連接創建一個線程,如果用戶的業務沒有連接管理,那麼將會存在頻繁的線程創建與銷燬,浪費很多資源,同時,大量併發線程的鎖衝突以及切換代價也會非常大。

針對以上問題,CynosDB 引入了線程池,直接解決了資源管理和線程切換的問題,但線程池只適合處理短任務。爲此,CynosDB 同時引入了異步組提交的機制,基於線程池實現,再增加獨立的日誌寫線程 log writer,每一個工作線程提交事務的時候,並不是去做寫和刷的操作,而是將自己的請求提交到一個提交隊列裏去,然後立即返回給 Server 層,以便釋放自己的線程資源。如果某一段日誌持久化成功之後,log writer 會喚醒提交隊列裏面等待的請求,將其重新調度到線程池的高優先級隊列,重新獲得工作線程執行事務提交後的工作。如此一來就能高效的利用線程池的資源,同時做到資源的控制,避免上下文頻繁切換帶來的性能問題。

日誌下沉、異步回放的關鍵設計

日誌下沉是什麼意思?比如開發者在一個頁面做插入操作,生成的日誌會放到日誌管理子系統的日誌 buffer 裏,日誌 buffer 的重用、刷新、併發管理等都是由數據庫來做。CynosDB 會把日誌管理做成獨立模塊,並在 CynosStore Client 中實現。任何數據庫如果想接入這個系統的話,都不用去關心日誌管理,直接調相關接口完成日誌記錄即可。這裏的日誌和普通日誌存在區別,比如 PG 的日誌更偏向邏輯的概念,而 CynosDB 的日誌,記錄的是物理修改(對某頁面的什麼位置做了什麼內容的修改)。另外,日誌向日志 buffer 的插入過程是並行的,若有 5 個用戶同時生成日誌,往日誌 buffer copy 都是並行進行的而非串行。

總結來說,日誌下沉是指 DB 層產生的日誌都會放到 CynosStore Client 的 buffer 中,然後異步發送到分佈式存儲中,而不是存到本地。而在分佈式存儲中有一塊固定的存儲空間來專門存儲日誌,由於空間大小固定,因此在 CynosStore 中會有特定的線程,定時地把日誌異步地合併到數據頁面上,通過這種日誌回收機制可以有效的利用日誌空間,保證寫的連續性。

CynosDB 應用場景及未來規劃

近日,騰訊雲數據庫 CynosDB 正式亮相 MariaDB 用戶者大會,並受到了 MariaDB 基金會以及衆多參會者的認可。

據瞭解,今年 Q3,CynosDB 將會徹底完成商業化。與此同時,騰訊雲數據庫產品總監王義成還向記者透露,CynosDB 的技術能力以及存儲層早已具備按使用量計費的能力,計算層也正在進行相應的適配,待 CynosDB 商業化後將逐步推上日程。

由於 CynosDB 對主流開源數據庫的兼容,以及快速彈性升級、海量數據存儲等優勢,王義成稱,CynosDB 未來將持續落地應用於包括互聯網及遊戲等廣闊的行業,幫助用戶更好地應對業務高峯,加速業務創新。

後記

從 2012 年到 2019 年,這七年,騰訊雲數據庫無不見證、參與數據庫技術發展史上的一次次突破與迭代。回望這段從開源到適配,從適配到自研的歷程,騰訊雲可以說將每一次經由業務適配考驗後的思考、經驗都化作數據庫服務的“活水”,灌溉自身業務的同時也灌溉了開發者社區。

但值得注意的是,在長達幾十年的時間裏,由於國內數據庫市場啓動較晚,國外巨頭始終佔據數據庫絕對領先優勢,使得國產數據庫的發展十分艱難。未來,由雲原生技術帶來的一系列新技術與市場機遇,不僅僅是對數據庫管理員的挑戰,也是對數據庫產品內核與工具的考驗,接下來騰訊雲數據庫“風”往何處吹?且看“行雲”。

相關文章