京东商城技术架构部-数据库技术部,负责为京东商城提供高效稳定的数据库服务以及数据库生态商品的研发,主要关注:数据库AIOps系统、数据库内核、多模型数据库系统、弹性数据库、BinLake、JTransfer以及数据知识图谱等产品的研发,部门秉承技术至上、不断创新的在数据库领域不断前进。
运维自动化来源于工作中的痛点,京东数据库团队面对的是商城成千上万的研发工程师,这种压力推动我们不断变革,然而变革不是一蹴而就,也经历过从手工到脚本化、自动化、平台化、智能化的转变,所以说是需求在驱动运维体系的建设,而运维自动化的真谛在于解放运维人员,促进人率提升,减少人为故障,要学会培养自己懒这个好习惯。
京东业务每年都在以爆发的形式在增长,数据库服务器的数量众多,产品线也多达上千条,要支持如此庞大的业务体系,需要一套完善的运维自动化管理平台。目前京东MySQL数据库管理平台简称DBS,主要涵盖以下内容:完善的资产管理系统、数据库流程管理系统、数据库系统、数据库故障管理系统、数据库报表系统、弹性数据库系统以及数据库辅助运维工具,涉及DBA运维的方方面面,实现了DBA对MySQL的自动化、自助化、可视化、智能化、服务化管理,避免DBA因手工操作失误带来的生产事故,保障京东数据库的安全、稳定、高效运行。
面对繁杂的数据库新增,扩容等运维工作,利用自动安装部署平台可以彻底解放DBA。目前京东的自动化部署系统包含申请服务器、部署数据库实例、同步数据、一致性校验、拆分及切换等操作,整个过程流程化,包含各级业务及DBA的操作审批,最终达到全面的MySQL服务的自动化和流程化部署,如下图:
系统为数据库管理提供了精准的数据依据,能够让运维人员对生产服务系统运行情况了如指掌,核心的指标包含:OS负载、MySQL核心指标、数据库日志等。通过分析获得的信息,判断被数据库的运行状态,对可能出现的问题进行预测,并给出优化方案,整个系统稳定、高效。
数据库性能智能分析,主要是对数据库数据的二次分析,排除安全隐患。在实际的生产中,有些隐患没有达到设置的报警阈值,处于一个报警的临界点,其实这种情况是最的,随时可能爆发,为解决这些隐患,我们通过对数据的环比、同比、TOP指标等方面进行分组汇总分析,提前发现隐患。
京东数据库服务器的量级较大,会导致出故障的概率相对提高,同时对系统稳定性的要求也较为苛刻。因此为确保实现数据库高可用,7*24小时的持续服务,我们团队自主研发了数据库自动切换平台,实现了自动和半自动两种切换方式,实现了按单集群级别、多集群级别、机房级别等度的场景切换。切换过程包含的修改、资产信息的修改、备份策略的修改、主从角色的修改等,一键化完成,避免人为因素带来的二次故障。
作为切换系统的核心组件,分布式检测功能主要解决系统容灾方面的问题。按照京东数据库服务器多数据中心部署的特征,的数据中心各部署了一个检测节点,并通过特殊标识的接口域名区分。当发生切换操作时,切换系统会根据传入的故障主机IP等信息,随机选取两个机房接口执行调用,探活操作如果发现有一个节点主机存活,那么认为主机存活;如果发现两个节点都探测为宕机,那么认为主机宕机。
主库实例故障,切换系统会首先通过分布式检测系统检查实例存活状态,确认宕机后将根据基础信息中的实例切换标识,选择使用自动切换或手动切换,两种切换方式原理相同:先在切换系统上创建切换任务,手动切换需要DBA执行切换按钮,切换操作会通过insert方式插入数据以验例运行状态,避免实例夯住和硬盘只读的情况。如果没有存活的从库,则放弃本次操作并以邮件和短信的方式通知DBA。新主库是按照先本地(先连接数少,后QPS负载低),后异地的原则选择,执行切换成功后将变更相应元数据信息,示例如下:
选目标实例,假如例子中的4个从都是存活的,那么根据先本地后异地原则,选出10.66.66.68:3366,10.66.66.69:3366,然后再去查连接数,在连接数都相同的情况下,则去比较QPS,选出QPS负载低的10.66.66.69:3366作为目标实例:
从库实例故障,将故障实例下的域名变更到该集群下的非故障实例上,选择目标实例方式与主库实例选择规则一致。切换成功或失败都会发邮件及短信告知相应的DBA。故障实例恢复后,DBA判断是否需要回切。示例如下:
京东数据库备份系统在设计之初,就是为了将DBA欧豪家庭背景从繁杂的备份管理工作中出来,实现自动处理,减少人为干预,并提高备份文件的可用性。关于备份文件可用性问题,以轮询恢复的策略确保每个集群在一个周期内都被恢复到。系统架构设计如下图所示:
之前公司的备份系统是需要指定特定的IP,经常因为服务器而导致备份失败,故在设计之初就将备份策略与高可用结合在一起,备份策略指定域名而不是IP。从库因为故障切换时DBS会将此从库上的域名切换到集群内的其他从库,相应的备份也跟随到了此从库,了备份服务器是可用的。
备份在每一步都要严格地验证,但是也无法绝对备份文件可用,因此引入了自动恢复检测机制,来帮助DBA对备份文件进行检测,及时发现因为各种未考虑到的情况导致备份文件不可用的情况,并且恢复检测也是审计的一个硬性要求,自动恢复检测也将DBA从繁重的恢复检测工作中彻底了出来。
整个自动化备份恢复系统主要由调度系统、备份系统、恢复系统、恢复检测系统、自动修复系统组成。其中调度系统是整个系统核心,通过调度系统来协调其他系统运行。调度系统可以部署Standby来实现高可用,执行器以集群部署来实现高可用和横向扩容。
备份系统每次备份时都会进行实例健康状态检查、备份运行状态检查等,防止对无效的数据库实例进行备份;恢复系统主要是在需要进行数据恢复、弹性扩容等等需要从备份文件恢复成运行的数据库实例时使用,能够让DBA通过简单地操作即可完成数据的恢复;恢复检测在调度系统的指挥下自动对备份文件可用性进行检测,来帮助DBA及时发现不可用的备份文件;备份失败有些是能够通败自动重试来解决,但有一部分是重试所不能解决的,需要进行相应修复,因此开发了自动修复系统来自动修复因为等问题引起的备份失败。
调度系统是最核心的一个系统,是整个备份恢复系统的大脑,当时考察了几种实现方式,例如Linux的crontab、Azkaban和python的开源框架Apscheduler,最终认为Apscheduler更加灵活小巧,调度方式也更加多样化,使用Python开发后期成本更低,因此采用Apscheduler开发了调度中心。
备份策略管理的页面包含了备份状态分布情况、存储使用情况以及每个集群的当前备份策略状态,如果已经添加了备份策略则可以在这里进行(时间、服务器、备份方式)修改、暂停(继续)、删除操作,如果没有添加备份策略,则可以进行添加。
备份详情里面展示了最近备份总数、成功数、成功率、当天备份任务运行状态、备份任务24小时分布曲线图以及备份详细记录。备份详细的记录可以根据集群名、项目名等信息进行查询,方便DBA更好地掌握备份运行状况。
在ContainerDB之前,京东的数据库服务实现了容器化,虽然数据库服务已经完全通过Docker容器实现了数据库服务的快速交付和自动故障切换等基本功能,在一定程度上提高了数据库服务的稳定性和效率,但是数据库服务的运维和使用方式与传统方式基本无异,比较典型的问题如下:
资源分配的标准有DBA根据经验决定,存在很大的主观性,不能根据业务的实际情况进行准确评估,而DBA在分配资源的时候一般都会考虑在3年以内不需要对服务进行迁移或者扩容,而一次分配比较多的资源,存在严重资源浪费。而且由于数据库资源标准固定,标准过大,导致宿主机中的碎片过大,经常出现一台宿主机只能创建一个容器,而剩下的资源满足不了任何资源标准,导致宿主机上资源使用率过低。
基于以上的问题,单纯的数据库服务容器化已经无决,我们需要让数据库服务更聪明,让数据库的资源能够动起来,提供资源分期交付的功能,于是ContainerDB应运而生。ContainerDB基于负载的弹性调度为京东的数据库资源赋予了智慧,令其资源真正地流动起来,并已成功服务于多次618和11.11大促。
ContainerDB针对每个业务应用都有逻辑库,逻辑库中定义了针对整个业务所有表的拆分键(Sharding Key)进行哈希取模运算时模的范围(KeySpace),在每个逻辑库中可以创建多张表,但是每个表中必须定义Sharding Key。通过该Sharding Key将表中的数据拆分成多个分片(Shard),每个分片都对应一个KeyRange,KeyRange表示对Sharding Key进行哈希取模运算之后得到的值(Sharding Index)的一个范围,每个Shard都由一整套MySQL主从架构提供数据库服务支撑。应用程序只跟Gate集群进行交互,由Gate根据元数据信息和SQL语句完成数据写入和查询的自动由。ContainerDB中的中心会对所有的基础服务和资源使用状况进行实时,并通过在中心注册的Hook程序自动进行动态扩容、故障自愈、分片管理等,而这一系列操作对应用程序来说是完全无的。
数据库以前的服务存在资源浪费的一个主要原因就是资源初始分配粒度太大,一开始就为业务提前预支3年甚至5年的资源。而资源池中的资源是有限的,不可能让所有业务都提前预支资源,从而导致有些业务没有资源。ContainerDB采用流式的方式进行资源的持续交付。每个业务接入初始都只会分配标准的64G硬盘,随着业务的发展和数据量的持续增加,会持续增加硬盘容量直到到达硬盘的上限256G。
递增资源是指资源的使用率不会再短时间之内出现严重的波动,而是会缓慢增加,并且支持递增,不会出现减少的情况,这种资源主要包括硬盘。ContainerDB对于不同的资源采取了不同的调度策略。针对于瞬时资源,ContainerDB为每个数据库分配三种标准:
每个容器分配的初始资源为标准的下限值,当数据库服务出现CPU负载过高或者内存不足时,会尝试申请多于下限的CPU或者内存,但绝对不会超过上限,待负载恢复后多申请的资源,直至恢复至CPU和内存的下限为止。
针对递增资源:磁盘,在业务接入之初,统一分配64G的硬盘,每当当前磁盘使用率达到80%,且没有达到256G上限的时候,则进行垂直升级;若容器当前磁盘达到了256G上限则进行在线Resharding。
垂直升级:首先会进行资源check,看宿主机是否有足够的剩余硬盘资源进行垂直升级,若check通过,则会在宿主机全局资源锁,并对硬盘进行垂直扩容再增加64G。若check不通过,则在宿主机上提供一个硬盘大小为:磁盘容量+64G大小,CPU和内存与当前容器相同的新容器,并将数据库服务迁移到新的容器上。垂直升级是瞬间完成的不会影响数据库服务。
在线Resharding:申请两个新的Shard,新Shard中的数据库Container的硬盘、CPU和内存标准与当前Shard中的完全一致,根据当前Shard中的数据库主从关系,对新Shard中的所有数据库重建MySQL主从关系,然后启动Schema信息拷贝和过滤复制,最后更新由规则并将读写流量切换到新的Shard上,将旧的Shard资源下线。
无论是垂直升级还是在线Resharding,都需要注意一个问题:在每个分片的Master在主机房的前提下,尽量不要将所有的资源都分配在一个宿主机/机架/机房,ContainerDB提供了强大的亲和/反亲和性资源分配能力。目前ContainerDB的亲和/反亲和性策略如下:
每个KeySpace都有一个主机房,属于同一个Shard中的数据库实例(目前一个shard中包含1主2从)的资源分配尽量应该满足:Master必须属于主机房,不能有任意两个实例属于同一机架,不能有任意三个实例在同一IDC,这种策略可以避免某一机柜掉电而导致主从同时出现故障,也可以避免IDC故障从而导致所有数据库实例均不可用。
由于是尽量满足,所以当资源池中的资源分布不均时,就有可能在资源分配的时候满足不了上述的反亲和性策略。因此ContainerDB有一个常驻后台进程,不停的轮询集群中的所有Shard,判断Shard中的实例分布是否满足反亲和性规则,若不满足,就会尝试进行实例重新分布。重新分布时为了不影响线上业务,会优先进行从库重分布。
在线自愈:当Shard中的某个MySQL实例出现故障,ContainerDB首先判断出现故障的实例是否为master,若是master,则选择GTID最大的slave作为新的主,并进行复制关系重建和Slave补齐;若不是master,则直接进行slave补齐。
在线接入:ContainerDB允许用户以完全自助化的方式启动数据在线迁移与接入任务,该任务会将传统MySQL数据库中的数据在线迁移到ContainerDB中,待数据迁移完毕后,自动进行域名切换,完成业务系统数据源的在线无迁移。
在传统的直连数据库的方案下,当Master出现网络不可达时,一般都会选择新的Slave变为Master,然后将原来Master上的域名漂移到新的Master上。但是这种方案在网络抖动的情况下很容易由于AppServer上的DNS缓存,而导致双Master,并且出现脏写的情况。从整体架构图可以看出,ContainerDB与用户之间通过Gate连接。Gate是一个集群化服务,多个Gate服务都映射到一个域名下,Gate通过IP地址直接访问各个MySQL服务,而且Gate对各个MySQL角色的识别完全依赖于元数据服务:Topology。当ContainerDB中某个MySQL的Master产生网络不可达时,会选出新的Master,并更新由元数据信息,最后才做Master切换,这样就避免了由于网络抖动和DNS缓存而在成双主和数据脏写,从而对数据进行了严格的。
ContainerDB通过在交叉在Window函数中分别执行部分存量数据拷贝和增量数据追加的算法,开发了在线数据迁移和接入工具JTransfer,通过JTransfer可以将传统MySQL数据库中的动态数据迁移到ContainerDB中,当ContainerDB中的数据与源MySQL中的数据的lag小于5秒时,首先会将源MySQL停写,待lag变为0时将源MySQL的域名漂移到Gate集群,整个迁移过程用户AppServer无。
ContainerDB与用户之间通过Gate集群进行连接,Gate根据用户发送的查询语句形成的语法树和查询执行计划得到查询中涉及到的所有表,并根据Topology中的元数据信息获得各个表的分片信息,最后结合语句中的Join中的关联条件和Where字句中的谓词信息,将查询或者写入由到正确的分片。整个过程都是Gate自动完成的,对用户完全透明。
ContainerDB将对数据库服务的实例化、DDL/DML执行、分片升级和扩容等功能抽象成为的接口,并借助于流程引擎提供了流程化的完全自助的用户接入服务,用户申请数据库服务成功后,ContainerDB会将数据库访问口令自动推送到用户邮箱。
More Smart:我们会基于各个数据库实例中CPU/内存/硬盘等各种不同资源的数据进行深度学习和聚类分析,分析出各个不同数据库实例的倾向资源,并智能化调高每个数据库实例倾向资源的并调低非倾向资源的。
More Quick:我们会实时分析宿主机和容器的对应关系、各个容器的参数以及各个容器的历史资源增长速率,预先对容器所在宿主机碎片进行整理,从而尽量各个容器以垂直升级的方式实现扩容,从而极大地加快扩容速度。
More Open:ContainerDB会在经过京东内部的各种场景的磨练之后会拥抱开源,并希望与业界各位同仁一起将ContainerDB不断完善。同时我们后续的多模型数据库最终也会贡献给开源社区,并期待其服务于业界。