在架構上,TDSQL 的核心思想有兩個:數據的復制(replica)和分片(sharding),其它都是由此衍生出來的。其中,
在金融行業(yè),銀行、風控、渠道等第三方通常通過讀寫分離方式來查詢數據,而在互聯(lián)網行業(yè),由于 x86 相對較高的故障率,導致數據可能經常性的出現(xiàn)錯亂、丟失場景。為了解決這個問題,就必須要求主從數據保持強一致和良好的讀寫分離策略。而其中的關鍵在于如何實現(xiàn)強同步復制技術。
由于 MySQL 的半同步和 Galera 模式不僅對性能的損耗是非常大的,而且數據同步有大量毛刺,這給金融業(yè)務同城雙中心或兩地三中心架構容災架構帶來了極大的挑戰(zhàn)。為什么會這樣呢?
從 1996 年的 MySQL3.1.1.1 版本開始,業(yè)務數據庫通常跑在內網,網絡環(huán)境基本較好,因此 MySQL 采用的是每個連接一個線程的模型,這套模型最大的好處就是開發(fā)特別簡單,線程內部都是同步調用,只要不訪問外部接口,支撐每秒幾百上千的請求量也基本夠用,因為大部分情況下 IO 是瓶頸。
但隨著當前硬件的發(fā)展,尤其是 ssd 等硬件出現(xiàn),IO 基本上不再是瓶頸,如再采用這套模型,并采用阻塞的方式調用延遲較大的外部接口,則 CPU 都會阻塞在網絡應答上了,性能自然上不去。
為了解決這些問題,TDSQL 引入了線程池,將數據庫線程池模型 (執(zhí)行 SQL 的邏輯) 針對不同網絡環(huán)境進行優(yōu)化,并支持組提交方案。例如,在 binlog 復制方案上將復制線程分解:
改造后, TDSQL 基本可以應對復雜的網絡模型。
但上述方案還有小缺陷:當主機故障,binlog 沒有來得及發(fā)送到遠端,雖然此時不會返回給業(yè)務成功,備機上不存在這筆數據,然而在主機故障自愈后,主機會多出來這筆事務的數據。解決方法是對新增的事務根據 row 格式的 binlog 做閃回,這樣就有效解決了數據強一致的問題。
當前大多數分布式數據庫都設計的是基于規(guī)則的查詢引擎 (RBO),這意味著,它有著一套嚴格的使用規(guī)則,只要你按照它去寫 SQL 語句,無論數據表中的內容怎樣,也不會影響到你的“執(zhí)行計劃”,但這意味著該規(guī)則復雜的數據計算需求不“敏感”。雖然金融業(yè)務都有自己的數據倉庫,然而也會經常需要在 OLTP 類業(yè)務中執(zhí)行事務、Join 甚至批處理。
TDSQL 在 SQLENGINE 實現(xiàn)了基于代價的查詢引擎 (CBO),SQL 經過 SQLENGINE 的詞法、語法解析、語義分析和 SQL 優(yōu)化之后,會生成分布式的查詢計劃,并根據數據路由策略(基于代價的查詢引擎)進行下推計算,最后對匯總的數據返回給前端。
而作為分布式的計算引擎,在存儲與計算引擎相分離的情況下,非常重要的一環(huán)就是如何將計算盡量下推的下面的數據存儲層。因此 TDSQL 的 SQLENGINE 在經過大量業(yè)務打磨后,實現(xiàn)了基于 shard key 下推、索引條件下推、驅動表結果下推、null 下推、子查詢下推、left join 轉化成 inner join 等多達 18 種下推優(yōu)化手段,盡量降低數據在多個節(jié)點傳輸帶來的壓力,以提供更好的分布式查詢的能力,支撐金融交易的關聯(lián)操作。
如果說騰訊云數據庫歷史是一部從蟄伏到發(fā)展再到突破的歷史,那么可以說接下來 CynosDB 的推出,讓騰訊云數據庫迎來了新一輪云應用場景下的突破與變遷。
2017 年,在騰訊云服務了百萬客戶之后,騰訊云數據庫迎來了突破。由開源數據庫適配業(yè)務和具體場景,騰訊云自主研發(fā)了一款真正的云原生數據庫CynosDB。作為騰訊云在數據庫領域的重要布局,CynosDB 單節(jié)點讀性能可以達到 130 萬 QPS,全面超越業(yè)內目前最高的 100 萬 QPS 水平。它將傳統(tǒng)數據庫與云計算的優(yōu)勢相結合,解決了傳統(tǒng)數據庫云上的難題,其設計思路可以概括為以下幾點:
這里需要重點說下計算和存儲分離。傳統(tǒng)數據庫的優(yōu)化演進歷史,基本上是和IO 做斗爭的歷史,因為數據庫是有狀態(tài)、重 IO 的服務,傳統(tǒng) MySQL 架構有多個 IO 類型,存儲相同的文件,所以主機和備機的磁盤會有很多相同的 IO 和冗余的文件。即便數據庫被搬上云,為了在云上做彈性的擴容,開發(fā)者依然面臨傳統(tǒng)數據庫所面臨的問題。
基于以上痛點,CynosDB 引入計算存儲分離的架構,存儲層使用共享的分布式塊存儲云服務,計算層則將不必要的 IO 全部卸載,實現(xiàn)計算與存儲基于日志傳輸的新架構。
在新架構中,日志處理無可厚非具有非常重要的作用。其中連續(xù)的日志在存儲層被打散成了很多的小的分片,分別存儲在不同的 cell 里。而日志處理的邏輯是將存儲引擎將日志發(fā)給存儲節(jié)點,存儲節(jié)點將日志放到一個日志隊列里面,并將其持久化,之后立即返回給存儲引擎,當存儲引擎獲得日志的反饋后就可以將一部分事務提交。其中,存儲節(jié)點會異步的進行一些操作,這些操作和事務的提交過程無關,不影響事務的提交響應速度。
而在數據庫里面,如果 buffer 足夠的話,數據庫的寫性能是和日志的落盤時間相關的,傳統(tǒng)數據庫組提交機制可能存在幾個問題,一是如果有大量的連接進來,MySQL 將會為每一個連接創(chuàng)建一個線程,如果用戶的業(yè)務沒有連接管理,那么將會存在頻繁的線程創(chuàng)建與銷毀,浪費很多資源,同時,大量并發(fā)線程的鎖沖突以及切換代價也會非常大。
針對以上問題,CynosDB 引入了線程池,直接解決了資源管理和線程切換的問題,但線程池只適合處理短任務。為此,CynosDB 同時引入了異步組提交的機制,基于線程池實現(xiàn),再增加獨立的日志寫線程 log writer,每一個工作線程提交事務的時候,并不是去做寫和刷的操作,而是將自己的請求提交到一個提交隊列里去,然后立即返回給 Server 層,以便釋放自己的線程資源。如果某一段日志持久化成功之后,log writer 會喚醒提交隊列里面等待的請求,將其重新調度到線程池的高優(yōu)先級隊列,重新獲得工作線程執(zhí)行事務提交后的工作。如此一來就能高效的利用線程池的資源,同時做到資源的控制,避免上下文頻繁切換帶來的性能問題。
日志下沉是什么意思?比如開發(fā)者在一個頁面做插入操作,生成的日志會放到日志管理子系統(tǒng)的日志 buffer 里,日志 buffer 的重用、刷新、并發(fā)管理等都是由數據庫來做。CynosDB 會把日志管理做成獨立模塊,并在 CynosStore Client 中實現(xiàn)。任何數據庫如果想接入這個系統(tǒng)的話,都不用去關心日志管理,直接調相關接口完成日志記錄即可。這里的日志和普通日志存在區(qū)別,比如 PG 的日志更偏向邏輯的概念,而 CynosDB 的日志,記錄的是物理修改(對某頁面的什么位置做了什么內容的修改)。另外,日志向日志 buffer 的插入過程是并行的,若有 5 個用戶同時生成日志,往日志 buffer copy 都是并行進行的而非串行。
總結來說,日志下沉是指 DB 層產生的日志都會放到 CynosStore Client 的 buffer 中,然后異步發(fā)送到分布式存儲中,而不是存到本地。而在分布式存儲中有一塊固定的存儲空間來專門存儲日志,由于空間大小固定,因此在 CynosStore 中會有特定的線程,定時地把日志異步地合并到數據頁面上,通過這種日志回收機制可以有效的利用日志空間,保證寫的連續(xù)性。
近日,騰訊云數據庫 CynosDB 正式亮相 MariaDB 用戶者大會,并受到了 MariaDB 基金會以及眾多參會者的認可。
與此同時,騰訊云數據庫產品總監(jiān)王義成還向記者透露,今年 Q3,CynosDB 將會徹底完成商業(yè)化。CynosDB 的技術能力以及存儲層早已具備按使用量計費的能力,計算層也正在進行相應的適配,待 CynosDB 商業(yè)化后將逐步推上日程。
由于 CynosDB 對主流開源數據庫的兼容,以及快速彈性升級、海量數據存儲等優(yōu)勢,王義成稱,CynosDB 未來將持續(xù)落地應用于包括互聯(lián)網及游戲等廣闊的行業(yè),幫助用戶更好地應對業(yè)務高峰,加速業(yè)務創(chuàng)新。
從 2012 年到 2019 年,這七年,騰訊云數據庫無不見證、參與數據庫技術發(fā)展史上的一次次突破與迭代?;赝@段從開源到適配,從適配到自研的歷程,騰訊云可以說將每一次經由業(yè)務適配考驗后的思考、經驗都化作數據庫服務的“活水”,灌溉自身業(yè)務的同時也灌溉了開發(fā)者社區(qū)。
但值得注意的是,在長達幾十年的時間里,由于國內數據庫市場啟動較晚,國外巨頭始終占據數據庫絕對領先優(yōu)勢,使得國產數據庫的發(fā)展十分艱難。未來,由云原生技術帶來的一系列新技術與市場機遇,不僅僅是對數據庫管理員的挑戰(zhàn),也是對數據庫產品內核與工具的考驗,接下來騰訊云數據庫“風”往何處吹?且看“行云”。