云计算架构下 Cloud TiDB的技术奥秘「下」

avatar
产品与技术团队 @UCloud
原文链接: blog.ucloud.cn

在《云计算架构下 Cloud TiDB的技术奥秘「上」》中,分析了TiDB与传统单机关系型数据库的区别,以及与几种技术整合之后所形成的总体架构。接下来,我们将深度探讨Cloud TiDB的关键特性和实现细节。

自动化运维

数据库产品上云的一个先决条件是能实现自动化的运维管理,因为在云上靠手工运维几乎是不现实的。第一步,用Kubernetes将云平台的主机资源管理起来,组成一个大资源池;第二步,再通过tidb-opeartor及tidb-cloud-manager等组件,来自动化完成TiDB实例的一键部署、扩容缩容、在线滚动升级、自动故障转移等运维操作。

  • 来看集群创建。在上篇文章里提到过TiDB包含tidb、tikv和pd三大核心组件,每个服务又都是一个多节点的分布式结构,服务和服务之间的启动顺序也存在依赖关系。此外,pd节点的创建和加入集群方式与etcd类似,是需要先创建一个单节点的initial集群,后加入的节点需要用特殊的join方式,启动命令上也有差别。

有一些操作完成后还需要调用API进行通知。Kubernetes自身提供的StatefulSet很难应付这种复杂部署,所以需要tidb-operator中实现特定Controller来完成这一系列操作。同时,结合Kubernetese强大的调度功能,合理规划和分配整个集群资源,尽量让新部署的TiDB实例节点在集群中均匀分布,最终通过LB暴露给对应的租户使用。

  • 在线升级也类似。由于tikv/pd的Pod挂载是本地存储,并不能像云平台提供的块存储或网络文件系统那样可以随意挂载。如果tikv/pd迁移到其它节点,相当于数据目录也被清空,所以必须保证tikv/pd的Pod在升级完成后仍然能够调度在原地,这也是要由tidb-operator的Controller来保证。

TiDB的数据副本之间由Raft算法来保证一致性,当集群中某一个节点暂时断开,可以不影响整个服务,所以在集群升级过程中,必须严格按照服务的依赖关系,再依次对Pod进行升级。

  • 当节点出现故障时,同样是由于挂载本地数据盘的原因,也不能像StatefulSet那样直接把Pod迁移走。当TiDB Operator检测到节点失效,首先要等一段时间,以确认节点不会再恢复了,再开始迁移恢复的操作。

首先调度选择一个新节点启动一个Pod, 然后通知TiDB将失效节点放弃掉,并将新启的Pod加入集群。后面会由TiDB的PD模块来完成数据副本数恢复以及数据往新节点上迁移,从而重新维持集群内数据平衡。

以上仅列举了TiDB几种典型的运维操作流程,实际生产上运维还有很多case需要考虑,这些都以程序的方式在tidb-operator里实现。借助Kubernetes和tidb-operator来代替人工,高效地完成TiDB数据库在云平台上的复杂运维管理。


(图:Cloud TiDB总体架构图)

动态扩缩容

弹性水平伸缩是TiDB数据库最主要的特性之一。在大数据时代,人们对数据存储的需求快速膨胀,有时用户很难预估自己业务规模的增长速度,如果采用传统存储方案,可能很快发现存储容量达到了瓶颈,然后不得不停机来做迁移和扩容。如果使用Cloud TiDB的方案,这个过程就非常简单,只需在Cloud控制台上修改一下TiDB的节点数量,就能快速完成扩容操作,期间还不会影响业务的正常服务。

那么,在Cloud后台,同样借助Kubernetes和tidb-operator的能力来完成TiDB增减节点操作。Kubernetes本身的运作是基于一种Reconcile机制,简单来说就是当用户提交一个新请求,比如期望集群里跑5个TiKV节点,而目前正在跑的只有3个,那么 Reconcile机制就会发现这个差异,先由Kubernetes调度器根据集群整体资源情况,并结合TiDB节点分配的亲和性原则和资源隔离原则来分配节点。另外很重要一点是选择有空闲Local PV的机器来创建Pod并进行挂载,最终通过tidb-operator将2个节点加入TiDB集群。

缩容的过程也类似。假如数据库存储的总数据量变少,需要减少节点以节省成本,首先用户通过云控制台向后端提交请求,在一个Reconciling周期内发现差异,tidb-operator的Controller开始通知TiDB集群执行节点下线的操作。安全下线可能是比较长的过程,因为需要由PD模块将下线节点的数据搬移到其他节点,期间集群都可以正常服务。当下线完成,这些TiKV变成tombstone状态,而tidb-operator也会通知Kubernetes销毁这些Pod,并且由tidb-volume-manager来回收Local PV。

资源隔离

资源隔离也是云上用户关心的一个问题。尤其是数据库这类应用,不同租户的数据库实例,甚至一个租户的多套数据库实例,都跑在一套大Kubernetes管理集群上,相互间会不会有资源争抢问题?某个实例执行高负载计算任务时,CPU、内存、I/O等会不会对同台机器上部署的其他实例产生影响?

其实,容器本身就是资源隔离的一个解决方案,容器底层是Linux内核提供的cgroups 技术,用于限制容器内的CPU、内存以及IO等资源的使用,并通过namespace技术实现隔离。而Kubernetes作为容器编排系统,能根据集群中各个节点的资源状况,选择最优策略来调度容器。同时,tidb-operator会根据TiDB自身特性和约束来综合决策TiDB节点的调度分配。

举例来说,当一个Kubernetes集群横跨多个可用区,用户申请创建一个TiDB集群,那么首先根据高可用性原则,将存储节点尽量分配到不同可用区,并给TiKV打上label。那么同一个可用区内也尽量不把多个TiKV部署到相同的物理节点上,以保证集群资源最大化利用。

此外,每个Local PV也是一块独立磁盘,每个TiKV的Pod分别挂载不同的盘,所以I/O上也是完全隔离。

Kubernetes还可以配置Pod之间的亲和性(affinity)和反亲和性(anti-affinity)。例如:在TiKV和TiDB之间,可以通过亲和性使其调度到网络延时较小的节点上,提高网络传输效率。TiKV之间借助反亲和性,使其分散部署到不同主机、机架和可用区上,降低因硬件或机房故障而导致的数据丢失风险。

上面解释了容器层的隔离,也可以看作是物理层的隔离。再来看数据层的隔离,TiDB的调度体系也有所考虑,比如一个大的TiDB集群,节点分布在很多台主机,跨越多个机架、可用区,那么用户可以定义Namespace,这是一个逻辑概念,不同业务的数据库和表放置在不同的Namespace,再通过配置Namespace、TiKV节点以及区域的对应关系,由PD模块来进行调度,从而实现不同业务数据在物理上的隔离。

高可用性

TiDB作为一个分布式数据库,本身就具有高可用性,每个核心组件都可以独立地扩缩容。任意一个模块在部署多份副本时,如果有一个挂掉,整体仍然可以正常对外提供服务,这是由Raft协议保证的。但是,如果对数据库节点的调度不加任何限制,包含一份数据的多个副本的节点可能会被调度到同一台主机。这时如果主机发生故障,就会同时失去多个副本,一个Raft分组内失去多数派节点就会导致整个集群处于不可用状态,因此tidb-operator在调度TiKV节点时需要避免出现这种情况。

另外,TiDB支持基于label的数据调度,能给不同TiKV实例加上描述物理信息的label,例如地域(Region)、可用区(AZ)、机架(Rack)、主机(Host),当PD在对数据进行调度时,就会参考这些信息更加智能地制定调度策略,尽最大可能保证数据的可用性。

例如,PD会基于label信息尽量把相同数据的副本分散调度到不同的主机、机架、可用区、地域上,这样在物理节点挂掉、机架掉电或机房出故障时,其它地方仍然有该数据足够的副本数。借助tidb-operator中controller-manager组件,可以自动给TiKV 实例加上物理拓扑位置标签,充分发挥PD对数据的智能调度能力,实现数据层面的高可用性。

同时,还可以达到实例级别的高可用性,通过Kubernetes强大的调度规则和扩展的调度器,按优先级会尽量选择让TiKV部署到不同的主机、机架和可用区上,把因主机、机架、机房出问题造成的影响降到最低,使数据具有最大的高可用性。

另外,运行在Kubernetes之上,能实时监测到TiDB各组件运行情况,当出现问题时,也能第一时间让tidb-operator对集群进行自动修复 (self-healing)。具体表现为tidb/tikv/pd实例出现故障时,执行安全的下线操作,同时增加新实例来保证集群的规模和之前一致。

小结

TiDB作为一款Cloud Native Database,通过tidb-operator方式充分发挥Kubernetes平台的强大能力,实现云上自动化管理,极大降低人力运维成本。用户可以根据业务需要进行动态扩容缩容,多租户隔离特性让不同租户的实例可以共享计算和存储资源,互不干扰,同时最大程度充分使用云上资源。Raft算法和tidb-operator自动修复能力以及两层调度机制保证了Cloud TiDB的高可用性。

UCloud和PingCAP公司深度合作,推出的Cloud TiDB产品现已开启公测,欢迎大家来体验云计算架构下的新一代数据库。

想要获取更多技术和活动资讯,可扫描以下二维码,关注“UCloud技术公告牌”微信公众号。

Post Views: 10