作者 | 潘娟
伴隨著互聯網應用場景逐漸深入到生活的各個角落,為了確保前端用戶的使用體驗,對互聯網產品的后端架構性能提出了更高的需求。如今,開發以及運維人員正在將工作重心和優化重點放在了后端基礎設施的可用性、一致性、擴展性、彈性以及全面自動化管理等能夠提升效率的技術能力層面。
1 背景:Kube.NETes 環境中的微服務與數據庫
應用部署的變化
一方面,在處處充斥著大數據以及高并發場景的今天,后臺技術人員往往會花費更多精力在解決『大規模業務數據的存儲與應用』等問題上,以確保數據庫等基礎設施能夠實時提供最佳服務;另一方面,在云原生『大行其道』的今天,技術人員也需要根據業務發展,構思并設計能夠滿足未來業務訴求的云上服務架構。
而這種顛覆性的云原生技術,正是我們今天談論的主要對象,它改變了從開發、交付、部署到維護的全部技術流程。如今,市場上的應用與業務已經普遍接受由各家云廠商所提出的『XaaS』概念。與之伴隨而來的,則是交付模式與架構形態的新變化。
架構形態的變化
在部署形態發生轉變的同時,架構模式也從單一的整體式架構逐步向微服務架構演進。隨著企業業務的持續擴張,前端的業務線也在持續發生著變化,這就要求后端系統能夠快速響應前臺每一條業務的單獨訴求,而這在過去傳統的架構模式中幾乎是不可能實現的。
微服務通過將一項單體式服務切分為多個更小的單元,圍繞業務領域組件來創建應用,使這些應用可獨立地進行開發、管理和迭代。與此同時,在分散的組件中使用云架構和平臺式部署、管理及服務功能,使產品交付變得更加簡單。而隨著 Service Mesh 的興起,服務間的解耦以及 API 調用等操作也被更加簡化,以適應業務微服務的部署、交付以及業務訴求。
而這些之所以能夠興起,正是 Kubernetes 在架構模式演進的過程中所提供的抽象平臺與機制,這也是 Kubernetes 在全球流行的重要原因之一。
借用 Kubernetes 官方文檔 中的一段話,更能夠體現 Kubernetes 的價值:
“Kubernetes 為你提供了一個可彈性運行分布式系統的框架。Kubernetes 會滿足你對于擴展、故障轉移、部署模式等多方面的要求。例如,Kubernetes 可以輕松管理系統的 Canary 部署。” (摘自“為什么需要 Kubernetes,它能做什么?”部分)
Kubernetes 是管理微服務生命周期的理想化平臺,那么作為有狀態的服務,數據庫在這種大環境下應具備哪些新特性呢?
數據庫層面的變化
針對上述問題,應用層采用了微服務架構來作為解決方案。但數據庫的情況卻有些不同。在數據庫層面,面對『蜂擁而至』數據體量,常見的解決方案是對數據庫層進行數據分片,將數據庫改造為分布式架構。
當前,不論是 MongoDB、Cassandra、Hbase、DynamoDB 等非關系型數據庫還是 Cockroach、google Spanner、Aurora 等新型數據庫,分布式架構無處不在。分布式數據庫需要將單體數據庫分片為更小的單元,從而實現高性能和彈性伸縮。這也就是為什么 CockroachDB 兼容 PostgreSQL 協議;Vitess 為 MySQL 提供了分片特性;AWS 開發了 Aurora-MySQL 和 Aurora-PostgreSQL。
而對于企業用戶數據庫選型來講,新型的數據庫解決方案,不僅要解決分布式、單元化的問題,更要考慮『如何讓客戶從現有的 Oracle、MySQL、PostgreSQL、SQLServer 等數據庫遷移至新數據庫產品中』的問題,其原因在于:傳統關系型數據庫仍然占據著龐大的市場份額,數據庫替換的痛點是企業用戶不得不面臨的重要課題。
2 需求:在 Kubernetes 上實現數據庫的云中立
云的興起意味著數據庫面臨著新的挑戰。云平臺遵循“隨機應變”、“一切皆服務”、“開箱即用”的原則,正逐步改變用戶對于傳統研發、交付、部署、維護等技術流程。
以應用程序開發人員為例,在云原生環境下,開發人員通常會在云上或 Kubernetes 上交付應用。這是否意味著數據庫也應該在云端或 Kubernetes 上部署?大多數用戶應該都會這樣認為,這也是為什么數據庫即服務(DBaaS)的概念越來越受歡迎。
然而,如果你是一家準備上云的企業,首先要確認的一定是哪家云廠商能夠為業務提供長期的技術支持。但事實上,任何人都心知肚明這是很難實現的。因此為了將風險分攤開,在企業視角中,多云就成為了市面上最廣泛的選擇,而將應用及數據庫部署在 Kubernetes 上完成與云廠商的解耦和依賴,正是解決這類問題的可選項之一。
這是因為 Kubernetes 本質上是容器編排的抽象層,具有高度的可配置性和可延展性,用戶甚至可以在特定場景下自定義編碼。例如,Kubernetes 上的掛載服務是由眾多云供應商實現和提供。如果服務部署在 Kubernetes 上,應用就能夠與 Kubernetes 實現交互,無需與不同類型的特定云服務或基礎設施產生額外的交互。實踐證明這種理念在無狀態應用程序或微服務的領域非常適用。正是由于這些成功案例,人們開始思考如何將數據庫部署在 Kubernetes 上,進而實現云中立。
不過這一方案的缺點在于,Kubernetes 天生適用于無狀態應用,而非數據庫及其它有狀態應用,因此管理 Kubernetes 上的數據庫或有狀態的應用比管理無狀態的應用層的難度更大。為了解決這一問題,可以基于 Kubernetes 的基礎機制,使用 StatefulSet 和 Persistent Volume 等方法來實現橋接和適配。MongoDB、cockachdb、PostgreSQL 等數據庫的 operator 就是采用了這種方法。
3 命題一:如何將單體數據庫轉換為更接近云原生的分布式數據庫?
上述方案已經很常見,那還有其他的方案嗎?答案是肯定的。本節將會演示另一種方法,將完成從『MySQL、Oracle、PostgreSQL』等單體數據庫到分布式數據庫系統的升級改造,并且以一種更加接近云原生的管理方式,來實現 Kubernetes 上的分布式數據庫系統的部署、管理及使用。
顧名思義,這個方案主要分為兩個步驟:首先將單體數據庫轉換為分布式數據庫,其次將該分布式成功部署在 Kubernetes 環境中并實現有效管理。
其核心理念在于利用數據庫最本真的兩大基礎能力,即計算能力和存儲能力,如上圖所示。任何一款數據庫必然具備這樣的核心組件、核心能力;傳統的 MySQL、PostgreSQL 和其它單節點數據庫只是剛好將兩個組件部署在一臺服務器或容器上而已,而所謂的分布式數據庫架構,即是采用存算分離的分布式架構,將存儲節點、計算節點進行分布式化,部署在不同服務器節點上,進行內部組件的通訊,完成對上層業務的響應。
首先,使用數據分片能力打造分布式數據庫
作為一款分布式的數據庫生態系統,ShardingSphere 提供兩個客戶端:ShardingSphere-Proxy 和 ShardingSphere-JDBC。用戶可選擇使用 ShardingSphere-Proxy 充當 “分布式” MySQL 或 PostgreSQL 的服務器端;或者使用 ShardingSphere-JDBC 作為 JAVA 應用的 Driver 端來完成同樣的功能實現。無論采用哪種方式,用戶都無需變更原來訪問數據庫的方式,這極大地降低了用戶的學習曲線和遷移成本。
如果將單體數據庫看做分片節點(即存儲節點),將 ShardingSphere-Proxy 或 ShardingSphere-JDBC 看做全局的 Server 入口或代理端(即計算節點),他們的組合就是一種分布式數據庫系統。如下圖所示:
此外,ShardingSphere 內置有 DistSQL (分布式 SQL),用于管理分片數據庫、動態控制分布式數據庫系統的工作負載,如 SQL 審計、讀寫分離、權限等。
例如,你可以使用 CREATE TABLE t_order () SQL 在 MySQL 中創建一個新表。在 ShardingSphere-Proxy 中使用 CREATE SHARDING TABLE RULE t-order () 就可以在新升級的分布式數據庫系統中創建一個全局分片表。
其次,在 Kubernetes 層面部署分布式數據庫
目前為止,我們已經解決了數據分布式問題,但我們如何將其部署在 Kubernetes 上呢?Shardingsphere-on-cloud 提供了 ShardingSphere-Operator-Chart 和 ShardingSphere-Chart,幫助用戶在 Kubernetes 上部署 ShardingSphere-Proxy 和『云上 DBA』ShardingSphere-Operator 集群。
『ShardingSphere-Chart』這個 Charts 能夠幫助用戶使用 helm 命令在 Kubernetes 環境中部署 ShardingSphere-Proxy 集群,包括 Proxy 計算節點本身、治理中心、數據庫連接驅動程序和 ShardingSphere-Operator。
作為『云上 DBA』,ShardingSphere-Operator 通過利用預定義的 CustomResourceDefinition,可以聲明 ShardingSphere-Proxy 在 Kubernetes 上的部署結構,并持續監控運行狀態,還可以基于 CPU 指標進行 Kubernetes 上的 HPA (橫向自動擴容),并能夠確保 ShardingSphere-Proxy 的高可用性,以維持所需計算服務節點的副本數量,提升整個分布式數據庫系統的高可用性。
4 命題二:如何讓分布式數據庫系統變得無狀態,真正實現分布式 + 云原生?
如上所述,數據庫系統一般由計算節點和存儲節點組成。當用戶使用現有的生產環境的數據庫作為新分布式數據庫系統的存儲節點時,ShardingSphere 則可以作為全局的計算節點,提供分布式數據庫計算服務,即經典的計算存儲分離的架構。這種架構在 Cloud native 場景下, 特別是 Kubernates 上有了重新的解讀和應用。將計算節點作為無狀態的應用部署在 Kubernates 上,并利用 Kubernetes 天然的平臺能力來解決傳統單點數據庫分布式改造的課題。而存儲節點可以部署在任意位置,可以是 Kubernetes 集群內、云的 RDS、私有環境等,真正實現分布式數據庫存算架構的解耦和云化問題。
用戶可以使用 ShardingSphere-Chart 以及 ShardingSphere-Operator-Chart 這兩款工具輕松地部署和管理 ShardingSphere 集群,并在 Kubernetes 上創建自己的分布式數據庫系統,無需關注單體數據庫的位置,利用 Kubernetes 管理無狀態計算節點,用戶所創建的數據庫可在任何公有云或私有云上,通過讓 Kubernetes 上的 ShardingSphere (全局計算節點) 訪問任意位置的單機數據庫,從而對最終用戶提供透明化的、完整的分布式數據庫的解決方案,大幅降低升級改造成本,并提升整體的性能和存儲能力。
在這類體系中 ShardingSphere-Proxy 將作為全局計算節點處理用戶請求,從分片存儲節點中獲取本地結果集并進行計算。這意味著無需對生產環境的現有數據庫集群進行危險操作,只需要將 ShardingSphere 導入到現有的數據庫基礎設施層,就可以將單機數據庫存儲節點與 ShardingSphere 全局計算服務器連接起來,形成一套完整的分布式數據庫系統解決方案。
另一方面,為了提升該集群的可用性和自動擴縮容等特性,用戶可使用 ShardingSphere-Operator 按業務需求量對 ShardingSphere-Proxy(計算節點)和數據庫(存儲節點)進行分別的擴縮容,真正實現按需分配、一鍵彈性。例如,有些用戶只需要增強計算能力,ShardingSphere-Operator 將在幾秒鐘內自動擴容 ShardingSphere-Proxy,而不會對存儲能力做任何改變,無危險操作、無付費成本。也有一些用戶只關注存儲容量,而對計算能力無過多期望,這時他們只需要快速啟動更多的空數據庫實例并執行 DistSQL 命令,ShardingSphere-Proxy 將對新舊數據庫重新進行數據分片,以提高容量和性能。
采用 ShardingSphere 對現有數據庫集群進行平滑分片,并以更為云原生的方式將其部署于 Kubernetes 上。與其關注如何從根本上打破當前的數據庫基礎設施,忙于重新尋找一個可以在 Kubernetes 上作為有狀態應用進行有效管理的分布式數據庫,我們不如從另一個角度思考這個問題:
『如何讓分布式數據庫系統變得“無狀態”、充分利用現有的數據庫集群、真正實現分布式 + 云原生?』
下面將展示兩個真實場景案例:
Kubernetes 上的數據庫
首先使用 Helm charts 等方法將數據庫(如 MySQL 和 PostgreSQL)部署到 Kubernetes 環境中,然后使用 ShardingSphere charts 成功部署了 ShardingSphere-Proxy 和 ShardingSphere-Operator 集群。完成部署后,用戶可以使用原生的驅動訪問方式連接 ShardingSphere-Proxy,使用 DistSQL 讓 ShardingSphere-Proxy 感知到單機數據庫,即分布式計算節點連接到存儲節點,形成最終的分布式數據庫解決方案。
云端或本地數據庫
下圖為云端、本地的數據庫兩種形態的部署架構。下圖右半部分體現云上計算 + 云下存儲的分布式數據庫架構,即計算節點 ShardingSphere-Proxy 及 “云上 DBA” ShardingSphere-Operator 在 Kubernetes 上運行,但是數據庫(存儲節點)位于 Kubernetes 之外。
方案的優勢與不足
當然,這個世界上并不存在能夠滿足任何需求的技術銀彈,每一款產品或解決方案,都會有其所擅長以及相對不足的領域。
優勢
-
利用現有數據庫能力
在不破壞生產環境遺留數據庫架構的前提下,用戶可以平滑安全地構建分布式數據庫系統。
-
高效平穩遷移
ShardingSphere 幾乎沒有停機時間幫助用戶完成歷史數據遷移及分布式改造。
-
DistSQL
ShardingSphere 提供 DistSQL 支持以原生數據庫的方式(即 SQL)使用分布式數據庫系統的分片、數據加密、流量治理等特性。
-
對計算存儲能力單獨進行靈活擴縮容
基于計算存儲分離架構,用戶可以真正實現『按需』單獨分別對 ShardingSphere-Proxy (計算能力) 和 Databases (存儲能力) 進行靈活擴縮容。
-
云原生運行和治理方式增強
由于 ShardingSphere-Proxy 本質上是一種無狀態全局計算服務節點,同時充當全局數據庫訪問入口,因此更容易在 Kubernetes 上進行云原生的管理和部署。
-
多云或跨云
數據庫作為有狀態存儲節點可以部署于 Kubernetes 或任意云端,避免單個云平臺鎖定。僅使用 ShardingSphere 連接節點就可構建分布式數據庫系統。
-
數據庫的其他特性
ShardingSphere 是一個圍繞數據庫的生態系統,除了數據分片,還提供數據加密、權限、讀寫分離、SQL 審計等特性等待為用戶場景全面賦能。
-
用戶可選擇多個客戶端或混合部署
ShardingSphere 根據用戶需求提供兩種客戶端:ShardingSphereProxy 和 ShardingSphere-JDBC。通常,ShardingSphere-JDBC 性能更高,而 ShardingSphere-Proxy 支持所有的開發語言,提供分布式數據庫集群的管理能力。ShardingSphere-JDBC 和 ShardingSphere-Proxy 混合部署可以進行優勢互補。
-
開源支持
Apache ShardingSphere 是 Apache 基金會的一個頂級項目,開源至今已有五年以上。作為一個成熟的社區,Apache ShardingSphere 具備豐富的用戶案例、文檔和強大的社區支持。
劣勢
-
分布式事務
事務對于分布式數據庫系統也至關重要。但是由于這種技術架構不是從存儲層開發的,目前它依賴 XA 協議來協調數據源的事務處理,所以說并不算一個完美的分布式事務方案。
-
SQL 兼容性
部分 SQL 查詢在存儲節點(數據庫)中表現良好,但在全新的分布式系統中會出現問題。我們開源社區仍在努力攻克這一難點。
-
全局一致性備份
雖然 ShardingSphere 定義為分布式數據庫計算引擎,但多數用戶傾向于將其視為分布式數據庫。因此,用戶需要考慮該分布式數據庫系統全局備份一致性。ShardingSphere 正在針對這一特性進行研發,目前暫不支持(5.2.1),用戶需要對數據庫進行手動或用 RDS 備份。
-
成本增加
ShardingSphere 會接收所有請求,計算并發送至存儲節點。每次查詢都必然會增加成本,所有分布式數據庫都會遇到這種情況。
5 實操指南
本節將演示如何使用 ShardingSphere 和 PostgreSQL RDS 創建分布式 PostgreSQL 數據庫,以及用戶如何對兩個 PostgreSQL 實例進行數據分片。
以下演示過程中,ShardingSphere-Proxy 運行于 Kubernetes;PostgreSQL RDS 運行于 AWS。部署架構如下圖所示。
演示主要包含以下內容:
-
部署 ShardingSphere-Proxy 集群和 ShardingSphere-Operator。
-
使用 DistSQL 構建分布式數據庫表。
-
測試 ShardingSphere-Proxy 集群(計算節點)的彈性伸縮能力和高可用。
1. 準備數據庫 RDS
在 AWS 或任意云上創建兩個 PostgreSQL RDS 實例作為存儲節點。
2. 部署 ShardingSphere-Operator
下載 repo,在 Kubernetes 上創建一個名為 sharding-test 的命名空間。
Bash
git clone https://github.com/apache/shardingsphere-on-cloud
kubectl create ns sharding-test
cd charts/shardingsphere-operator
helm dependency build
cd ../
helm install shardingsphere-operator shardingsphere-operator -n sharding-test
cd shardingsphere-operator-cluster
vim values.yaml
helm dependency build
cd ..
helm install shardingsphere-cluster shardingsphere-operator-cluster -n sharding-test
修改并部署 shardingsphere-operator-cluster 的 values.yaml 中的 automaticScaling: true 和 proxy-frontend-database-protocol-type: PostgreSQL。
以上操作會創建一個 ShardingSphere-Proxy 集群,其中包含 1 個 Proxy 實例、2 個 Operator 實例和 1 個 Proxy 治理實例,如下所示:
3.使用 DistSQL 創建分片表
(1) 登錄 ShardingSphere-Proxy 并添加 PostgreSQL 實例。
??????Bash
kubectl port-forward --namespace sharding-test svc/shardingsphere-cluster-shardingsphere-operator-cluster 3307:3307
psql --host 127.0.0.1 -U root -p 3307 -d postgres
(2) 執行 DistSQL,用 MOD(user_id, 4)創建一個分片表 t_user,顯示這個邏輯表 t_user 的實際表。
(3) 插入測試行,在 ShardingSphere-Proxy 上執行查詢,得出最終合并結果。
(4) 登錄到兩個 PostgreSQL 實例以獲取它們的本地結果。
以上測試有助于理解 ShardingSphere 管理和分片數據庫的功能, 用戶無需關注不同分片中的單個數據。
4.測試 ShardingSphere-Proxy 集群(計算節點)的伸縮和高可用
如果用戶認為新系統的 TPS 或 QPS 太高,可以考慮升級整個分布式數據庫系統的計算能力。相較于其它分布式數據庫系統,ShardingSphere-Proxy 增加計算節點的方式最為簡單。ShardingSphere-Operator 能夠基于 CPU 指標確保 ShardingSphere-Proxy 的可用性和彈性伸縮。此外,還可通過修改參數進行擴容或縮容,如下圖所示:
升級完成后用戶將會獲取兩個 ShardingSphere-Proxy 實例,表明計算能力得到了增強。
如上,若用戶需要更多的存儲容量,可以采取以下步驟:
-
在云端或本地部署啟動額外的 PostgreSQL 實例;
-
將新的存儲節點添加到 ShardingSphere-Proxy 中;
-
運行 DistSQL,使用 ShardingSphere 進行重新分片。
6 小結
本文聚焦 Kubernetes 上的一種全新分片數據庫架構,利用分布式數據庫存算分離的架構,借助現有單體數據庫幫運維團隊高效流暢地將數據庫基礎設施轉化為現代數據庫的分布式系統。通過在 Kubernetes 重新解讀和應用分布式數據庫計算存儲分離這種傳統架構,解決了有狀態數據庫在 Kubernetes 上的部署、治理、使用等問題。
如今,分布式數據庫、云計算、開源、大數據、數字化轉型都是熱門概念。這些熱詞傳遞了新概念、新想法和新方案,對解決生產問題、滿足生產需求大有裨益。但畢竟世界上沒有完美的方案,我們要善于接受新的思想、通過權衡優劣、依據用戶獨特的場景需要選出最適合自己的方案才是技術選型的王道。
關于作者
潘娟,SphereEx 聯合創始人 &CTO、Apache Member & Incubator Mentor、Apache ShardingSphere PMC、AWS Data Hero、騰訊云 TVP、中國木蘭開源社區導師。曾負責京東數科數據庫智能平臺的設計與研發,現專注于分布式數據庫 & 中間件生態及開源領域。
參考資料:
[1]https://www.verifiedmarketresearch.com/product/database-as-a-service-providers-market/
[2] https://kubernetes.io/docs/concepts/extend-kubernetes/
[3] https://shardingsphere.apache.org/document/current/en/overview/
[4] https://github.com/apache/shardingsphere-on-cloud
[5]https://shardingsphere.apache.org/document/5.2.0/en/user-manual/shardingsphere-proxy/migration/build/