你聽過多少款無伺服器架構(Serverless)資料庫?
什麼是Serverless呢?簡單理解,Serverless 分為 FaaS 和 BaaS 兩個部分,其中 FaaS 指的是函數即服務,BaaS 是後端即服務。
舉個例子,使用者瀏覽網頁,可能涉及CDN資源。如果是靜態內容,從物件儲存下載照片、視訊;如果是動態內容,則觸發一個函數計算,雲函數將從雲資料庫獲取相應的資源,生成使用者所需的動態內容。其中,雲函數為 FaaS,物件儲存和雲資料庫則為 BaaS。
傳統的雲資料庫會提供多種記憶體/CPU規格給使用者購買。即使無法時刻用滿負載,使用者也需要為選中的規格付費。大多數客戶在購買資料庫服務時,只能根據歷史經驗來推測需求規格,無法準確判斷業務未來的發展趨勢。也是,咱們沒有天眼,誰知道什麼時候能被時代選中呢?
不過,咱還是要默默的問自己一聲。萬一爆紅,你的資料庫做好準備迎接業務存取量暴漲、計算或儲存的需求量激增了嗎?
不打算爆紅的企業不是好企業,抱著一顆要爆紅的心,大多數的企業會選擇比真實需求稍微偏大一些規格的資料庫服務。在沒爆紅前,這就是儲存、計算資源的浪費,也是嘩嘩的銀子在流淌。當然也有很多務實的企業,計算的近乎精準,可還是避免不了資源的靈活規劃問題,如某一時刻突然業務存取量暴漲,對計算或儲存的需求量激增,也容易出現範例資源不夠、規格太小,需要緊急擴容。
那,使用者當然要問了,到底我要選擇多大規格的呢?在 TDSQL-C 這兒,完全不用糾結。
Serverless 服務是騰訊雲資料庫自研的新一代雲原生關係型資料庫 TDSQL-C MySQL版的無伺服器、全 Serverless 架構版。TDSQL-C 推出的 Serverless 服務基於計算與儲存分離的理念,滿足了客戶在公有云端計算環境下根據業務發展彈性擴充套件叢集的剛性需求,讓使用者不再糾結範例資源問題,讓使用者像使用自來水一樣使用資料庫。總結其特性,可分為以下三點:
要想完美的實現 Serverless 的特性,必然不能放過任何一個細節。資料庫範例的啟停過程帶來的時間成本、安全挑戰就是其中重要的一點,接下來將會圍繞這個細節為大家闡述騰訊雲資料庫TDSQL-C的解法。
在一些極限的測試場景下,範例會頻繁的自動啟停,這時候如何保證範例停止後快速恢復呢?如何保證在恢復範例時無需使用者重複連結,直到恢復存取?
站在使用者的角度考慮,誰都不希望資料庫每次啟停都耗費大量的時間,更不希望在這個過程中對業務有任何的影響。因此,極致壓縮冷啟動時間,做到連結不斷轉發請求的能力相當關鍵。
為了實現這一能力,我們做了眾多探索,最後選定了通過在接入層增加一個恢復感知器來實現秒級冷啟動這一方案。同比於通過 proxy 來實現連結的保持和轉發能力的方案,我們採用的方案更加貼合 Serverless 服務為使用者提供低成本的理念。這是因為採用 proxy 模式需要支付額外的成本,整體設計會更加複雜,並且還需要設計多租戶的能力。
接下來,我們將詳細解讀 TDSQL-C Serverless 服務是如何實現通過接入層來實現恢復感知服務這一方案的。
這一方案的核心要點是在 TDSQL-C 的接入層增加了一個恢復感知器(下文簡稱:perceptron),通過 perceptron 模組來實現請求轉發,perceptron 在和使用者端握手之後,不斷開與使用者連線,恢復範例後,與 TDSQL-C 握手,後續轉發四層報文。以下為 perceptron 與 TDSQL-C 建連的具體過程:
在範例暫停的狀態下,如果有連線發起時,MySQL 使用者端首先會同 preceptron 進行 TCP 握手(P0)。
完成 TCP 握手之後,preceptron 會向用戶端傳送 「亂數 A」 進行挑戰(P1),MySQL 使用者端用自己的賬號密碼和 「亂數 A」 來計算並回復自己的 「登入解答 A」(P2)。
由於 preceptron 並沒有儲存使用者的賬號密碼,所以無法校驗 「登入解答 A」 是否正確,但 preceptron 能區分使用者端是 MySQL 使用者端,還是其他型別的使用者端(preceptron 在機器學習界是分類器,區分不同型別的使用者端,這也是我們以它命名的原因之一)。
校驗 「登入解答 A」 將由 TDSQL-C 計算層(下文簡稱:TDSQL-C)來完成,preceptron 通過管控喚醒 TDSQL-C 後(P3),開始下一步的登入校驗流程。
在和 preceptron TCP 握手之後(P4),對於 TDSQL-C 來說,preceptron 也是一個普通的 MySQL 使用者端,所以也傳送一個 「亂數 B」 挑戰(P5)給 preceptron。
preceptron 的回覆是一個我們實現的特殊的 MySQL 報文(P6),首先它用 「亂數 B」 和 preceptron 自身的鑑權機制計算得到 「登入解答 B」 並放入報文中,其次它也將 「亂數 A」 和 「登入解答 A」 捎帶在此報文中。
TDSQL-C 收到特殊的解答報文後會做兩次校驗,第一次是 「亂數 B」 和 「登入解答 B」 的正確性以及 preceptron 的身份,通過後再進行第二次的 「亂數 A」 和 「登入解答 A」 的正確性,通過即以使用者身份進行登入,並回復 preceptron 登入成功(P7)。
preceptron 進而回複用戶登入成功(P8)。
經歷過這樣的流程後,我們在使用者端發起一次登陸請求後,範例就可以完全無感地進行範例恢復,恢復登入後,後續的請求和封包通過 preceptron 進行相互的轉發。
比較巧妙的點在於整體流程設計採用了兩個挑戰亂數進行鑑權,這樣做的優勢在於:
由於後續的 SQL 請求都是通過 preceptron 進行轉發,此功能對於 preceptron 的安全性、穩定性、低資源消耗以及低延遲響應能力都有要求。所以 TDSQL-C 團隊採用了 Rust 語言進行研發,相比使用垃圾回收機制管理記憶體的語言,Rust 具有更穩定的響應時間。同時基於 Rust 記憶體管理特點,使得 preceptron 更安全,佔用的記憶體資源更少,最大化降低成本。
至此,讀者一定會疑問,基於 serverless 形態下如果所有請求都通過 preceptron 進行轉發,這樣成本和開銷無疑會變大,有悖於資料庫在 serverless 下的低成本特性吧?
其實,選擇 serverless 的使用者更在意低成本,而不是讀寫分離和連結保持能力。因此我們在設計 preceptron 模組時,只會把觸發恢復的請求連結接路由到 preceptron 上,當範例恢復後,新增的請求會直接發給 TDSQL-C。
這一流程是通過 VIP 權重來實現路由的定向轉發。當範例處於暫停狀態時,僅保留 preceptron 的路由;當範例恢復後時,同時保留 preceptron 的路由和 TDSQL-C 的路由,並設定 preceptron 的路由權重為 0,以實現新增連線直連到 TDSQL-C,同時存量與 preceptron 已經建連的連結依然能夠通訊。
那麼下面我們來模擬一下使用者恢復範例的連結不斷機制。首先我們選好一個暫停狀態的 serverlss 範例,如果其在執行中我們也可以通過手動暫停來停止範例的執行。
通過監控資料和控制檯,我們可以看到上面的範例已經處於完全暫停狀態了,接下來我們通過遠端連線工具,直接對資料庫發起連線請求。
如下圖所示,我們在發起資料庫連線請求時,可以做到秒級資料庫恢復,並且在整個連線的過程中使用者側對範例恢復和重連毫無感知,極大程度地提高了 Serverlss 產品的易用性。
經過多輪測試,我們累加核心側、管控側、perceptron 側的總體冷啟動時間,整體重連時間約在 2000ms 左右。淺放一張今天下午測試的結果,歡迎大家來體驗秒級的快樂!
TDSQL-C Serverless 功能還在持續優化中,今天我們更貼近了雲函數的啟動時間,在保證範例暫停的狀態下快速拉起服務並對業務無感。未來,我們還會繼續提升冷啟動的時間。
同時,我們為了進一步降低使用者的儲存成本,我們在持續探索新型的儲存能力,在範例暫停狀態下將資料轉存到物件儲存COS,並保證範例在恢復時不影響資料的讀取,更大程度幫助使用者降低成本。