APP下载

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

2018-09-29AP

电脑知识与技术·经验技巧 2018年5期
关键词:副本实例组件

近日,国内云计算服务商UCloud与国内开源分布式NewSOL数据库TiDB团队PingCAP正式达成合作,双方联手在UCloud全球数据中心推出了新一代TiDB的云端版本-Cloud TiDB。

作为一款定位于Cloud-native的数据库,目前TiDB在云整合上已取得了阶段性进展。Cloud TiDB产品在UCloud平台正式开启公测,TiDB弹性伸缩特性在Cloud提供的基础设施支持下得到了淋漓尽致地体现。在感受云数据库魅力的同时,让我们来探索—下TiDB与Cloud背后的技术秘密。

一、TiDB与传统单机关系型数据库的区别

首先,从TiDB的架构说起。TiDB作为一款开源的分布式数据库产品,具有多副本,能够根据业务需求非常方便地进行弹性伸缩,并且扩缩容期间对上层业务无影响。

TiDB的主体架构包含三个模块,对应Githuh上PingCAP组织下的三个开源项目(TiDB/TiKV/PD):

1) TiDB主要是负责SQL的解析器和优化器,它相当于计算执行层,同时也负责客户端接人和交互;

2) TiKV是一套分布式的Kev-Value存储引擎,它承担整个数据库的存储层,数据水平扩展和多副本高可用特性都在这一层实现;

3) PD相当于分布式数据库的大脑,一方面负责收集和维护数据在各个TiKV节点的分布情况,另一方面PD承担调度器的角色,根据数据分布状况以及各个存储节点的负载来采取合适的调度策略,维持整个系统的平衡与稳定。

上述三个模块中的每个角色都是一个多节点组成的集群,所以最终TiDB的架构如图1所示。

由此可见,分布式系统本身的复杂性不仅导致人工部署和运维成本较高,而且容易出错。传统的自动化部署运维T具(如Puppet/Chef/SaltStack/Ansihle等),由于缺乏状态管理,在节点出现问题时不能及时自动完成故障转移,需要人工干预,有些则需要写大量DSL甚至与Shell脚本一起混合使用,可移植性较差,维护成本比较高。

在云时代,容器成为应用分发部署的基本单位,谷歌基于内部使用数十年的容器编排系统Borg经验,推出的开源容器编排系统Kuhernetes就成为当前容器编排技术的主流。

二、TiDB与Kubernetes的深度整合

作为Cloud Native Datahase,TiDB选择拥抱容器技术,并与Kuhernetes进行深度整合,使其可以非常方便地基于Kuhernetes完成數据库白动化管理。甚至可以说Kuhernetes项目是为Cloud而生,利用云平台IaaS层提供的API可以很方便地与云进行整合。这样只要让TiDB与Kuhernetes结合得更好,进而就能实现其与各个云平台的整合,使TiDB在云上的快速部署和高效运维成为现实。

1.Kubernetes简介

Kuhernetes最早是作为一个纯粹的容器编排系统而诞生,用户部署好Kuhernetes集群之后,直接使用其内置的各种功能部署应用服务。由于这个PaaS平台使用起来非常便利,吸引了很多用户,不同用户也提出了各种不同需求,有些特性需求Kuhernetes可直接在其核心代码里实现,但有些特性并不适合合并到主程序中。

为了满足这类需求,Kubernetes开放出一些API供用户自己扩展,实现自身需求。当前Kuhernetes已经升级到1.8版本,内部API变得越来越开放,使其更像是一个跑在云上的操作系统。用户可以把它当作一套云的SDK或Framework来使用,而且可以很方便地开发组件来扩展满足自身业务需求,对有状态服务的支持就是一个代表性实例。

在最早期,Kuhernetes项目只支持无状态服务( Stateless Service)来管理,无状态服务通过ReplicationController定义多个副本,由Kuhernetes调度器来决定在不同节点上启动多个Pod,实现负载均衡和故障转移。对于无状态服务,多个副本对应的Pod是等价的,所以当节点出现故障时,在新节点上启动一个Pod与失效的Pod是等价的,不会涉及状态迁移问题,因而管理非常简单。

2.有状态服务Stateful Service

不过,对于有状态服务(Stateful Service),由于需要将数据持久化到磁盘,使得不同Pod之间不能再认为成等价,也就不能再像无状态服务那样随意地进行调度迁移。Kuhernetes l.3版本提出PetSet的概念,用来管理有状态服务并在1.5版本中将其更名为StatefulSet。

StatefuISet明确定义了一组Pod中的每个身份,启动和升级都按特定顺序来操作。另外,使用持久化卷存储(PersistentVolume)来作为存储数据的载体,当节点失效Pod需要迁移时,对应的PV通过umount/mount方式跟着一起迁移到新节点,或者直接使用分布式文件系统作PV底层存储,使Pod在迁移后仍然能访问到之前的数据。

同时,Pod在发生迁移时,其网络身份(例如IP地址)是会发生变化的,很多分布式系统不能接受这种情况,所以Statef'uISet在迁移Pod时可以通过绑定域名的方式来保证Pod在集群中网络身份不发生变化。

然而,现实中一些分布式系统更为复杂,StatefulSet也显得捉襟见肘。举例来说,某些分布式系统的节点在加入集群或下线时,还需要做些额外的注册和清理操作,或者在滚动升级时,要考量版本兼容性等问题。

基于上述原因,CoreOS公司提出了Operator概念,并实现了etcd-operator和prometheus-operator来管理Etcd和Prometheus这样复杂的分布式系统。用户可以开发自己的Operator,在Kuhernetes之上实现白定义的Controller,将有状态服务领域中特定的运维知识编码进去,从而实现对特定分布式系统的管理。同时,Operator本身也是跑在Kuhernetes中的一个Pod(deployment),对Kubernetes系统并无危害。

3.TiDB多组件支持

针对TiDB这种复杂的分布式服务,我们开发了tidh-operator等一系列组件,来管理TiDB集群实例在Kubernetes平台上的创建、销毁、扩容、缩容、滚动升级和故障转移等运维操作。同时,在上层封装了一个tidh-cloud-manager组件,提供RESTful接口,实现了与云平台的控制台打通功能。这就完成了一个DBaaS(数据库即服务)架构的基本形态。

由于TiDB对磁盘1/0有比较高的要求,通过PV挂载网络盘,会有明显的性能损耗。另外,TiKV本身维护了数据多副本,这点和分布式文件系统的多副本是有重复的,所以要给Pod上挂载本地磁盘,并且在Kuhernetes上把Local PV管理起来,作为一种特定资源来维护。

Kuhernetes方长期以来一直没有提供Local PV支持,本地存储只支持hostPath和emptyDir两种方式。其中,hostPath的生命周期是脱离Kuhernetes管理的,使用hostPath的Pod销毁后,里面的数据是不会被自动清理,下次再挂载Pod就会造成多余的数据。而emptyDir更像是一个临时磁盘,在Pod重建时会被清理重置,不能成为持久化PV来使用。

为此,我们开发了一个tidh-volume-manager组件,用于管理Kuhernetes集群中每台物理主机上的本地磁盘,并且将其变成一种特殊的PV资源。结合Operator在部署TiDB节点时会参考Local PV资源的情况,来选择特定节点进行部署,分配一个空的LocalPV和Pod绑定。而当Pod销毁时,会根据具体情况决定是否结束Local PV的生命周期,释放掉的Local PV在经历一个GC周期后,被tidh-volume-managerl回收,清理其盘上数据等待再次被分配使用。

将这些组件整合起来,就形成了上图描述的CloudTiDB总体架构(图2)。在Kubenete s管理的集群上,通过tidb-operator等组件针对性的调配和使用集群资源,从而实现TiDB集群实例的生命周期管理。通过这种方式实TiDB分布式数据库和云平台的整合。

三、Cloud TiDB的关键特性和实现细节

1.自动化运维

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

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

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

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

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

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

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

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

2.动态扩缩容

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

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

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

3.资源隔离

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

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

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

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

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

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

4.高可用性

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

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

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

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

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

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

猜你喜欢

副本实例组件
创建Vue组件npm包实战分析
光伏组件热斑对发电性能的影响
智能机械臂
国家知识产权局公告:专利证书改版
完形填空Ⅱ
完形填空Ⅰ
新副本“战歌之城”怨灵BOSS面面观
《口袋西游—蓝龙》新副本“幽冥界”五大萌点
嵌入式组件技术的研究及应用
走出孤独囧境