摘要:作為一個開源的分布式數(shù)據(jù)庫產(chǎn)品,具有多副本強一致性的同時能夠根據(jù)業(yè)務需求非常方便的進行彈性伸縮,并且擴縮容期間對上層業(yè)務無感知。另外本身維護了數(shù)據(jù)多副本,這點和分布式文件系統(tǒng)的多副本是有重復的。
作者:鄧栓
來源:細說云計算
TiDB 的架構作為一款定位在 Cloud-native 的數(shù)據(jù)庫,現(xiàn)如今 TiDB 在云整合上已取得了階段性的進展。日前 Cloud TiDB 產(chǎn)品在 UCloud 平臺正式開啟公測,TiDB 彈性伸縮的特性在 Cloud 提供的基礎設施支持下發(fā)揮的淋漓盡致。在感受云數(shù)據(jù)庫魅力的同時,讓我們來一探究竟,看一下 TiDB 與 Cloud 背后的技術秘密。
首先還是要先從 TiDB 的架構說起,TiDB 和傳統(tǒng)的單機關系型數(shù)據(jù)庫有什么不同?相信長期以來一直關注 TiDB 的同學都比較了解了,但這里還是科普一下。TiDB 作為一個開源的分布式數(shù)據(jù)庫產(chǎn)品,具有多副本強一致性的同時能夠根據(jù)業(yè)務需求非常方便的進行彈性伸縮,并且擴縮容期間對上層業(yè)務無感知。TiDB 的主體架構包含三個模塊,對應 GitHub 上面 PingCAP 組織下的三個開源項目,TiDB / TiKV / PD:
TiDB 主要是負責 SQL 的解析器和優(yōu)化器,它相當于計算執(zhí)行層,同時也負責客戶端接入和交互;
TiKV 是一套分布式的 Key-Value 存儲引擎,它承擔整個數(shù)據(jù)庫的存儲層,數(shù)據(jù)的水平擴展和多副本高可用特性都是在這一層實現(xiàn);
PD 相當于分布式數(shù)據(jù)庫的大腦,一方面負責收集和維護數(shù)據(jù)在各個 TiKV 節(jié)點的分布情況,另一方面 PD 承擔調度器的角色,根據(jù)數(shù)據(jù)分布狀況以及各個存儲節(jié)點的負載來采取合適的調度策略,維持整個系統(tǒng)的平衡與穩(wěn)定。
上面的這三個模塊,每個角色都是一個多節(jié)點組成的集群,所以最終 TiDB 的架構看起來是這樣的。
由此可見,分布式系統(tǒng)本身的復雜性導致手工部署和運維的成本是比較高的,并且容易出錯。傳統(tǒng)的自動化部署運維工具如 Puppet / Chef / SaltStack / Ansible 等,由于缺乏狀態(tài)管理,在節(jié)點出現(xiàn)問題時不能及時自動完成故障轉移,需要運維人員人工干預。有些則需要寫大量的 DSL 甚至與 Shell 腳本一起混合使用,可移植性較差,維護成本比較高。
TiDB 與 Kubernetes 的整合歷程在云時代,容器成為應用分發(fā)部署的基本單位,而谷歌基于內部使用數(shù)十年的容器編排系統(tǒng) Borg 經(jīng)驗推出的開源容器編排系統(tǒng) Kubernetes 成為當前容器編排技術的主流。作為 Cloud Native Database,TiDB 選擇擁抱容器技術,并與 Kubernetes 進行深度整合,使其可以非常方便地基于 Kubernetes 完成數(shù)據(jù)庫的自動化管理。
Kubernetes 項目可以說是為 Cloud 而生,利用云平臺的 IaaS 層提供的 API 可以很方便的和云進行整合。這樣我們要做的事情就很明確了,只要讓 TiDB 與 Kubernetes 結合的更好,進而就實現(xiàn)了和各個云平臺的整合, 使得 TiDB 在云上的快速部署和高效運維成為現(xiàn)實。
Kubernetes 最早是作為一個純粹的容器編排系統(tǒng)而誕生的,用戶部署好 Kubernetes 集群之后,直接使用其內置的各種功能部署應用服務。由于這個 PaaS 平臺使用起來非常便利,吸引了很多用戶,不同用戶也提出了各種不同的需求,有些特性需求 Kubernetes 直接在其核心代碼里面實現(xiàn)了,但是有些特性并不適合合并到主干分支,為滿足這類需求,Kubernetes 開放出一些 API 供用戶自己擴展,實現(xiàn)自己的需求。當前 Kubernetes 已經(jīng)發(fā)展到 v1.8,其內部的 API 變得越來越開放,使其更像是一個跑在云上的操作系統(tǒng)。用戶可以把它當作一套云的 SDK 或 Framework 來使用,而且可以很方便地開發(fā)組件來擴展?jié)M足自己的業(yè)務需求。對有狀態(tài)服務的支持就是一個很有代表性的例子。
Kubernetes 項目最早期只支持無狀態(tài)服務 (Stateless Service) 來管理的,無狀態(tài)服務通過 ReplicationController 定義多個副本,由 Kubernetes 調度器來決定在不同節(jié)點上啟動多個 Pod,實現(xiàn)負載均衡和故障轉移。對于無狀態(tài)服務,多個副本對應的 Pod 是等價的,所以在節(jié)點出現(xiàn)故障時,在新節(jié)點上啟動一個 Pod 與失效的 Pod 是等價的,不會涉及狀態(tài)遷移問題,因而管理非常簡單。但是對于有狀態(tài)服務 (Stateful Service),由于需要將數(shù)據(jù)持久化到磁盤,使得不同 Pod 之間不能再認為成等價,也就不能再像無狀態(tài)服務那樣隨意進行調度遷移。Kubernetes v1.3 版本提出 PetSet 的概念用來管理有狀態(tài)服務并于 v1.5 將其更名為 StatefulSet。StatefulSet 明確定義一組 Pod 中每個的身份,啟動和升級都按特定順序來操作。另外使用持久化卷存儲 (PersistentVolume) 來作為存儲數(shù)據(jù)的載體,當節(jié)點失效 Pod 需要遷移時,對應的 PV 也會重新掛載,而 PV 的底層依托于分布式文件系統(tǒng),所以 Pod 仍然能訪問到之前的數(shù)據(jù)。同時 Pod 在發(fā)生遷移時,其網(wǎng)絡身份例如 IP 地址是會發(fā)生變化的,很多分布式系統(tǒng)不能接受這種情況。所以 StatefulSet 在遷移 Pod 時可以通過綁定域名的方式來保證 Pod 在集群中網(wǎng)絡身份不發(fā)生變化。
然而現(xiàn)實中一些分布式系統(tǒng)更為復雜,StatefulSet 也顯得捉襟見肘。舉例來說,某些分布式系統(tǒng)的節(jié)點在加入集群或下線時還需要做些額外的注冊和清理操作,或者滾動升級要考量版本兼容性等。基于這個原因 CoreOS 公司提出了 Operator 概念,并實現(xiàn)了 etcd-operator 和 prometheus-operator 來管理 Etcd 和 Prometheus 這樣的復雜分布式系統(tǒng)。用戶可以開發(fā)自己的 Operator,在 Kubernetes 之上實現(xiàn)自定義的 Controller,將有狀態(tài)服務的領域特定的運維知識編碼進去,從而實現(xiàn)對特定分布式系統(tǒng)的管理。同時 Operator 本身也是跑在 Kubernetes 中的一組 Pod(deployment),對 Kubernetes 系統(tǒng)并無侵入性。
TiDB 系列組件及其作用針對 TiDB 這種復雜的分布式服務,我們開發(fā)了 tidb-operator 等一系列組件,來管理 TiDB 集群實例在 Kubernetes 平臺上的創(chuàng)建、銷毀、擴縮容、滾動升級和故障轉移等運維操作。同時在上層封裝一個 tidb-cloud-manager 組件,提供 RESTful 接口,實現(xiàn)與云平臺的控制臺打通。這樣也就實現(xiàn)了一個 DBaaS (數(shù)據(jù)庫即服務)架構的基本形態(tài)。
由于 TiDB 對磁盤 I/O 有比較高的要求,通過 PV 掛載網(wǎng)絡盤性能上會有明顯的性能損耗。另外 TiKV 本身維護了數(shù)據(jù)多副本,這點和分布式文件系統(tǒng)的多副本是有重復的。所以我們要給 Pod 上掛載本地磁盤,并且在 Kubernetes 上面把 Local PV 管理起來,作為一種特定的資源來維護。Kubernetes 長期以來官方一直沒有提供 Local PV 支持,本地存儲只支持 hostPath 和 emptyDir 兩種方式。其中 hostPath 的生命周期是脫離 Kubernetes 管理的,使用 hostPath 的 Pod 銷毀后,里面的數(shù)據(jù)是不會被自動清理,下次再掛載 Pod 就會造成臟數(shù)據(jù)。而 emptyDir 更像一個臨時磁盤,在 Pod 重建時會被清理重置,不能成為持久化 PV 來使用。為此我們開發(fā)了一個 tidb-volume-manager 組件,用于管理 Kubernetes 集群中每臺物理主機上的本地磁盤,并且將其暴露成一種特殊的 PV 資源。結合 Operator 在部署 TiDB 節(jié)點時會參考 Local PV 資源的情況來選擇特定的節(jié)點來部署,分配一個空的 Local PV 和 Pod 綁定。而當 Pod 銷毀時候會根據(jù)具體情況來決定是否結束 Local PV 的生命周期,釋放掉的 Local PV 再經(jīng)歷一個 gc 周期后,被 tidb-volume-manager 回收,清理其盤上數(shù)據(jù)等待再次被分配使用。
將這些組件整合起來,就形成了上圖描述了 Cloud TiDB 的總體架構,在 Kubenetes 管理的集群之上通過 tidb-operator 等組件來針對性的調配和使用集群資源,從而實現(xiàn) TiDB 集群實例的生命周期管理。通過這種方式,來實現(xiàn) TiDB 分布式數(shù)據(jù)庫和云平臺的整合。接下來,我們再針對 Cloud TiDB 的關鍵特性和實現(xiàn)細節(jié)分別進行解讀。
自動化運維數(shù)據(jù)庫產(chǎn)品上云的一個先決條件是能實現(xiàn)自動化的運維管理,否則在云上靠手工運維幾乎是不現(xiàn)實的。我們首先用 Kubernetes 將云平臺的主機資源管理起來,組成一個大的資源池。然后再通過 tidb-opeartor 及 tidb-cloud-manager 等組件來自動化完成 TiDB 實例的一鍵部署、擴容縮容、在線滾動升級、自動故障轉移等運維操作。
首先拿集群創(chuàng)建來說。前面提到過,TiDB 包含三大核心組件:TiDB / TiKV / PD,每個服務又都是一個多節(jié)點的分布式結構。服務和服務之間的啟動順序也存在依賴關系。此外,PD 節(jié)點的創(chuàng)建和加入集群方式和 etcd 類似,是需要先創(chuàng)建一個單節(jié)點的 initial 集群,后面加入的節(jié)點需要用特殊的 join 方式,啟動命令上都有差別。有一些操作完成后還需要調用 API 進行通知。Kubernetes 自身提供的 StatefulSet 是很難應付這種復雜的部署,所以需要 tidb-operator 中實現(xiàn)特定的 Controller 來完成這樣一系列的操作。并且結合 Kubernetese 強大的調度功能,合理的規(guī)劃和分配整個集群資源,盡量讓新部署的 TiDB 實例節(jié)點在集群中均勻分布,最終通過 LB 暴露給對應的租戶使用。
在線升級也是類似。由于 TiKV / PD 的 Pod 掛載的是本地存儲,并不能像云平臺提供的塊存儲或網(wǎng)絡文件系統(tǒng)那樣可以隨意掛載。如果 TiKV / PD 遷移到其它節(jié)點,相當于數(shù)據(jù)目錄也被清空,所以必須保證 TiKV / PD 的 Pod 在升級完成后仍然能夠調度在原地,這也是要由 tidb-operator 的 Controller 來保證。TiDB 的數(shù)據(jù)副本之間由 Raft 算法來保證一致性,因此當集群中某一個節(jié)點暫時斷開可以不影響整個服務的。所以在集群升級的過程中,必須嚴格按照服務的依賴關系,再依次對 Pod 進行升級。
當節(jié)點出現(xiàn)故障時,同樣是由于掛載本地數(shù)據(jù)盤的原因,也不能像 StatefulSet 那樣直接把 Pod 遷移走。當 TiDB Operator 檢測到節(jié)點失效,首先要等一定的時間確認節(jié)點不會再恢復了,開始遷移恢復的操作。首先調度選擇一個新節(jié)點啟動一個 Pod, 然后通知 TiDB 將失效的節(jié)點放棄掉,并將新啟的 Pod 加入集群。后面會由 TiDB 的 PD 模塊來完成數(shù)據(jù)副本數(shù)的恢復,以及數(shù)據(jù)往新節(jié)點上進行搬移,從而重新維持集群內數(shù)據(jù)平衡。
以上只是列舉了 TiDB 幾種典型的運維操作流程,實際生產(chǎn)上運維還有很多 case 需要考慮,這些都以程序的方式實現(xiàn)在 tidb-operator 里面。借助 Kubernetes 和 tidb-operator 來代替人工,高效的完成 TiDB 數(shù)據(jù)庫在云平臺上的復雜運維管理。
動態(tài)擴縮容彈性水平伸縮是 TiDB 數(shù)據(jù)庫最主要的特性之一。在大數(shù)據(jù)時代,人們對數(shù)據(jù)存儲的需求在快速膨脹。有時候用戶很難預估自己的業(yè)務規(guī)模的增長速度,如果采用傳統(tǒng)的存儲方案,可能很快發(fā)現(xiàn)存儲容量達到了瓶頸,然后不得不停機來做遷移和完成擴容。如果使用 Cloud TiDB 的方案,這個過程就非常簡單,只需要在 Cloud 控制臺上修改一下 TiDB 的節(jié)點數(shù)量,很快就能完成擴容操作,期間還不會影響業(yè)務的正常服務。
那么在 Cloud 后臺,同樣借助 Kubernetes 和 tidb-operator 的能力來完成 TiDB 增減節(jié)點操作。Kubernetes 本身的運作是基于一種 Reconcile 的機制。簡單來說當用戶提交一個新的請求,比如期望集群里面跑 5 個 TiKV 節(jié)點,而目前正在跑的只有 3 個,那么 Reconcile 機制就會發(fā)現(xiàn)這個差異,首先由 Kubernetes 的調度器根據(jù)集群整體資源情況,并結合 TiDB 節(jié)點分配的親和性原則和資源隔離原則來分配節(jié)點。另外很重要一點就是選擇有空閑 Local PV 的機器來創(chuàng)建 Pod 并進行掛載。最終通過 tidb-operator 將 2 個節(jié)點加入 TiDB 集群。
對于縮容的過程也是類似。假如數(shù)據(jù)庫存儲的總數(shù)據(jù)量變少,需要減少節(jié)點以節(jié)省成本。首先用戶通過云控制臺向后端提交請求,在一個 Reconciling 周期內發(fā)現(xiàn)差異,tidb-operator 的 Controller 開始通知 TiDB 集群執(zhí)行節(jié)點下線的操作。安全下線可能是個比較長的過程,因為期間需要由 PD 模塊將下線節(jié)點的數(shù)據(jù)搬移到其他節(jié)點,期間集群都可以正常服務。當下線完成,這些 TiKV 變成 tombstone 狀態(tài)。而 tidb-operator 也會通知 Kubernetes 銷毀這些 Pod,并且由 tidb-volume-manager 來回收 Local PV。
資源隔離資源隔離也是云上用戶關心的一個問題。尤其是數(shù)據(jù)庫這類應用,不同租戶的數(shù)據(jù)庫實例,甚至一個租戶的多套數(shù)據(jù)庫實例,都跑在一套大的 Kubernetes 管理的集群上,相互間會不會有資源的爭搶問題,某個實例執(zhí)行高負載的計算任務時,CPU、內存、I/O 等會不會對同臺機器上部署的其他實例產(chǎn)生影響。其實容器本身就是資源隔離的一個解決方案,容器的底層是 Linux 內核提供的 cgroups 技術,用于限制容器內的 CPU、內存以及 IO 等資源的使用,并通過 namespace 技術實現(xiàn)隔離。而 Kubernetes 作為容器編排系統(tǒng),能夠根據(jù)集群中各個節(jié)點的資源狀況,選擇最優(yōu)的策略來調度容器。同時 tidb-operator 會根據(jù) TiDB 自身的特性和約束,來綜合決策 TiDB 節(jié)點的調度分配。舉例來說,當一個 Kubernetes 集群橫跨多個可用區(qū),用戶申請創(chuàng)建一個 TiDB 集群,那么首先根據(jù)高可用性原則,將存儲節(jié)點盡量分配到不同的可用區(qū),并給 TiKV 打上 label。那么同一個可用區(qū)內也盡量不把多個 TiKV 部署到相同的物理節(jié)點上,以保證集群資源最大化利用。此外,每個 Local PV 也是一塊獨立的磁盤,每個 TiKV 的 Pod 分別掛載不同的盤,所以 I/O 上也是完全隔離的。Kubernetes 還可以配置 Pod 之間的親和性(affinity)和反親和性(anti-affinity),例如 TiKV 和 TiDB 之間我們可以通過親和性使其調度到網(wǎng)絡延時較小的節(jié)點之上,提高網(wǎng)絡傳輸效率,TiKV 之間借助反親和性,使其分散部署到不同的主機、機架和可用區(qū)上,降低因硬件或機房故障造成的丟數(shù)據(jù)的風險。
上面解釋了容器層面的隔離,可以看作是物理層面的隔離。那么數(shù)據(jù)層面的隔離,TiDB 的調度體系也是有所考慮的。比如一個大的 TiDB 集群,節(jié)點分布在很多臺主機,跨越多個機架、可用區(qū)。那么用戶可以定義 Namespace,這是一個邏輯概念,不同業(yè)務的數(shù)據(jù)庫和表放置在不同的 Namespace。再通過配置 Namespace 和 TiKV 節(jié)點以及區(qū)域的對應關系,由 PD 模塊來進行調度,從而實現(xiàn)不同業(yè)務的數(shù)據(jù)在物理上的隔離。
高可用性TiDB 作為一個分布式數(shù)據(jù)庫本身就具有高可用性,每個核心組件都可以獨立的擴縮容,任意一個模塊在部署多份副本時如果有一個掛掉,整體仍然可以正常對外提供服務,這是由 Raft 協(xié)議保證的。但是如果對數(shù)據(jù)庫節(jié)點的調度不加任何限制,包含一份數(shù)據(jù)的多個副本的節(jié)點可能會被調度到同一臺主機。這時如果主機發(fā)生故障,就會同時失去多個副本,一個 Raft 分組內在失去多數(shù)派節(jié)點就會使整個集群處于不可用的狀態(tài)。因此 tidb-operator 在調度 TiKV 節(jié)點時需要避免出現(xiàn)這種情況。
另外 TiDB 支持基于 label 的數(shù)據(jù)調度的,給不同的 TiKV 實例加上描述物理信息的 label,例如地域(Region)、可用區(qū)(AZ)、機架(Rack)、主機(Host),這樣 PD 在對數(shù)據(jù)進行調度時就會參考這些信息更加智能的制定調度策略,盡最大可能保證數(shù)據(jù)的可用性。例如 PD 會基于 label 信息盡量把相同數(shù)據(jù)的副本分散調度到不同的主機、機架、可用區(qū)、地域上,這樣在物理節(jié)點掛掉或機架掉電或機房出故障時,其它地方仍然有該數(shù)據(jù)足夠的副本數(shù)。借助 tidb-operator 中 controller-manager 組件我們可以自動給 TiKV 實例加上物理拓撲位置標簽,充分發(fā)揮 PD 對數(shù)據(jù)的智能調度能力,實現(xiàn)數(shù)據(jù)層面的高可用性。
同時我們還可以實現(xiàn)實例級別的高可用性,通過 Kubernetes 強大的調度規(guī)則和我們擴展的調度器,我們按優(yōu)先級會盡量選擇讓 TiKV 部署到不同的主機、機架和可用區(qū)上,把因主機、機架、機房出問題造成的影響降到最低,使數(shù)據(jù)具有最大的高可用性。
另外運行在 Kubernetes 之上我們能實時監(jiān)測到 TiDB 各組件的運行情況,當出現(xiàn)問題時,我們也能第一時間讓 tidb-operator 對集群進行自動修復 (self-healing)。具體表現(xiàn)為 TiDB / TiKV / PD 實例出現(xiàn)故障時,執(zhí)行安全的下線操作。同時增加新的實例,來保證集群的規(guī)模和之前一致。
TiDB 作為一款 Cloud Native Database,通過 tidb-operator 的方式充分發(fā)揮 Kubernetes 平臺的強大能力,實現(xiàn)云上自動化管理,極大降低人力運維成本。用戶可以根據(jù)業(yè)務需要進行動態(tài)擴容縮容,多租戶隔離特性讓不同租戶的實例可以共享計算和存儲資源,互不干擾,同時最大程度充分使用云上資源。Raft 算法和 tidb-operator 自動修復能力以及兩層調度機制保證了 Cloud TiDB 的高可用性。UCloud 和 PingCAP 公司深度合作,推出 Cloud TiDB 產(chǎn)品現(xiàn)已開啟公測,歡迎大家來體驗云時代的新一代數(shù)據(jù)庫。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/25200.html
摘要:所以很多對不太了解的小伙伴看完我們的招聘頁面,可能會覺得那些五沒花聽八說門過的研發(fā)類職位是特別神秘的存在吧招聘頁面上一小部分神秘部隊那么這些神秘團隊到底是做什么的下面就簡單的介紹一下這些研發(fā)團隊是做什么的吧。 過去一年在 PingCAP 全力奔跑的同時,越來越多的小伙伴開始關注我們、了解我們,我們的團隊也愈加龐大,我們也期待更多對我們感興趣的小伙伴加入我們,跟我們一起做點有意義的事情。...
摘要:申礫老師的演講實錄正在整理中,后續(xù)會分享給大家同時在里面,我們還做了大量的改進。 1 月 19 日 TiDB DevCon 2019 在北京圓滿落幕,超過 750 位熱情的社區(qū)伙伴參加了此次大會。會上我們首次全面展示了全新存儲引擎 Titan、新生態(tài)工具 TiFlash 以及 TiDB 在云上的進展,同時宣布 TiDB-Lightning Toolset & TiDB-DM 兩大生態(tài)工...
閱讀 1377·2021-10-08 10:04
閱讀 2680·2021-09-22 15:23
閱讀 2724·2021-09-04 16:40
閱讀 1172·2019-08-29 17:29
閱讀 1492·2019-08-29 17:28
閱讀 2987·2019-08-29 14:02
閱讀 2220·2019-08-29 13:18
閱讀 838·2019-08-23 18:35