今天分享的是饿了么在数据库和多活数据库方面的实战经验,供大家参考。分享主要围绕以下五点展开:多活架构数据库转型难点DBA挑战收益与前景同城就业多,异地就业多。跨地域网络延迟是现阶段难以突破的一个点,因为饿了么面临异地多活,所以需要以延迟为前提来考虑解决方案。北京和上海之间有30毫秒的延迟。这会造成什么问题?我们接下来会谈到那个。上图展示了同城和异地的多个activity的区别,复杂度和可扩展性对架构的影响会有很大的不同。挑几个点说一下:如果只是多做同城生活,30毫秒的延迟是不需要考虑的,因为同城的延迟一般只有几毫秒,这不是和同一个机房??里的大不相同。如果是异地延迟30毫秒,就需要考虑了,因为如果是重复调用的应用,放大时间不只是30毫秒,有可能是300毫秒,也可能是500毫秒,这对许多应用程序来说是不可接受的。在可扩展性方面,如果你在异地做多活,你的可扩展性理论上是没有太多边界的。我们只能选择住在上海的机房同城。如果是异地居住,可能全国乃至全球都有。另一个难题是如何保证数据安全?多活数据可能面临多个写入点,这可能会导致混乱、冲突、循环复制和数据循环。在这种情况下如何确保一致性?如果您之前没有考虑过这些,则无法使用多活动计划。多点写入的风险对数据是一个很大的考验。综合考虑后,我们选择了更多的异地居住,所以我们需要克服这些问题,这也意味着我们将面临大量的制度改造。如何解决跨机房延迟对业务的影响,包括各种抖动甚至断网问题;如何有效区分我们的访问流量,最大程度保证用户访问落在正确的机房,都是需要解决的难点。我们采取了一些措施,如上图所示:尽量把业务做集群化,让一个用户的访问落在同一个地方。并不是所有的服务都具有多活的特性,也可能存在全局使用的服务(比如用户数据),所以需要划分业务类型。在服务划分层面,我们如何定义业务调用的边界,根据什么来划分流量和用户?目前,根据我们的业务特点,使用地理围栏(POI)。用户、商家、骑手目前的地理位置是我们入口流量划分的依据。再来看看路由控制部分。除了入口流量层面的机房划分外,内部还使用了一个虚拟的ShardingKey。ShardingKey将全国流量分成多个部分,绑定到POI标签上。这样就可以将逻辑上的ShardingKey与物理位置关联起来,在切换时可以随着ShardingKey分配到不同的机房。APIRouter就是完成这个工作的。它将Shardingkey对应的流量按照配置的规则分配到对应的机房。在防止脏写方面,为了防止数据冲突,我们还需要业务配合修改一些活跃的规则。这些规则对业务还是有些侵入性的。另外SOA-Route是内部跨服务调用的访问路由;还有一个DAL,就是数据库的代理层。在我们的多层路由控制下,理论上业务访问应该正确路由到合适的机房。如果超出规则或未按规则修改的意外流量真的渗透到DAL层,我们将强制拒绝。因为底层认为这次访问是异常调用,如果流量走错机房,这时候就会拒绝,所以我们宁愿让它失败,也不愿让控制外的数据进来,这样确保规则和数据的可控性。在数据一致性方面,我们有一个重要的DRC数据同步组件。数据库有一些自增控制,DBA也开发了数据一致性校验的工具。多活架构大致说了一些难点和我们的解决方案之后,我们来看看整个多活架构。如上图所示,最上面是我们的入口流量,分布控制,多个机房之间的数据同步,包括各个重要组件的架构。还有globolzone项,就是我们刚才说的需要全局依赖的业务放在globolzone里面。DRC是做多活时很重要的一个组件,主要解决多机房数据的同步复制。我们从北京机房写的数据会同步到上海机房,在上海机房写的数据也会通过DRC组件同步到北京机房。可以看到,它包含三个服务,Replicator、Applier和Manager。一个收集变更数据,一个将变更数据写入另一个机房,一个用于管理控制。我们有两种DB架构(准确的说还有一种比较推荐,比较少):***型是ShardingZone,无论是数据写入还是访问,都是由机房提供的,当有是个问题,只是流量切换,不涉及底层的变化。这是一个真正的多活动架构。另一个是刚刚提到的全局区域。由于全局区域的结构,某些业务无法分区。写作集中在一间机房,阅读在本地机房完成。大家可能会觉得globalzone架构自然会面临一些数据延迟问题,所以我们对这个区域的定义是一些写量不大,访问量不大,对数据延迟不是那么敏感的业务可以放在这儿。多活库改造项目我们考察了大约半年时间,但实际改造时间很短。从这个项目开始到真正上线,用了大约三个月的时间。当时,时间相当紧迫。大家可以看一下我列举的配合多活数据库的主要改造项目。我们面临的第一个问题是需要将一个机房的数据全量导入到另一个机房。不仅是测试环境,生产环境也要完全同步。我们的数据有几百TB的数据,几百套集群,需要搭建各种主从结构,每个节点的时间也很短。我们刚才讲的DRC会做数据同步,但是在同步的时候也会面临数据冲突的问题。为了解决这个问题,我们需要在所有的表中加入一个DRC时间戳字段来判断哪一边的数据是最准确的,这样当数据发生冲突的时候,我们会选择最近的数据作为最终的数据。为了防止多主键冲突,数据库做了一些自增调整。自增步长放大后,马上就会面临数据溢出的问题,所以我们需要将主键从int调整为bigint。主键改变后,一些外键依赖也需要修改,所以会整体做很多DDL(几乎全表),而DDL在MySQL中其实是一个风险比较高的操作。第二个大改造是因为区分了不同的业务类型(刚才讲了goloblzone),我们会面临各种类型的业务本来就在同一个实例集合上的情况。现在我们需要拆分并迁移到不同的实例。我们也陆续迁移了50+个DB,还有一些还在迁移中。接下来的改造就是我们现在使用DRC跨机房同步数据。所有数据同步都是原生的,改成DRC模式,会做很多调整。还有一个问题就是账户的网段也需要调整,因为我们原本出于安全考虑限制了某些IP网段,现在网段范围扩大了,所有账户都要面临调整的问题网段。如果金额较大,调整账户的风险还是挺大的(很多历史遗漏会导致主从账户不一致,会出现账户同名不同网段等问题。如果有一个不一致的调整,主从就会中断)。另外,如何保证全局参数的一致性,至少要保证同一个集群,各个机房的参数是一致的,这是一件比较脏很累的事情,但是很容易出错,还有陷阱无处不在。另外HA也面临转型,因为以前是在一个机房,现在是多个机房。如何保证HA的可靠性也是一个问题。我们在这方面也做了很多改造。改造完成后,我们对比改造前后数据库端的变化。实例翻倍,集群数量、代理配置、数据量、HA都会翻倍。此处专门列出了一些DDL更改。为什么会有变化?因为DRC不做DDL同步,所以这个需要DBA在单独的机房做。机器故障的数量也每周都在增加。以前一周不会出现一台机器故障,现在一周可能会遇到两三台这样的机器故障,所以一定要保证你的HA足够可靠。但是我们的人数并没有增加多少,很快就要进入第三区了,维护的工作量会增加更多。但是,我们没有计划增加人员。之所以会这样,是因为我们在通过平台、自动化、项目来推进和解决很多工作。DBA的挑战对于DBA来说,除了多活动时期的业务转型和架构支持,我觉得最重要的还是DBA,这对DBA提出了很大的挑战。前面提到,在集群数量众多的情况下,如何有效保证数据的一致性、HA、配置、容量和DDL等问题。我们可以看看刚才提到的数据。我们要保证它不能错,不能乱,不能说因为一些数据冲突,我们整个数据流就停止了。这是不合理的,否则再活下去也没有意义。向上。还有一个,即使之前的流量都按规矩走,你也不能保证每个组件都没有bug。比如当DRC同步出现BUG时,我们需要进行彻底的检测,及时发现有问题的数据,甚至进行修复。所以我们的DBA开发了一个DCP平台。DCP是为了数据一致性。它会把我们每个机房的数据进行全量比对,当出现数据不一致的问题时,告诉DBA,大概的个数,什么类型,如何修复。需要合适的维修工具。对于DCP设计,因为我们的集群多套,变化多,如果说一旦变化就需要人为调整,维护量也很大,很难保证其准确性.因此,它必须是自适应的,需要随时支持全量、增量、延迟控制验证和手动验证。延迟验证意味着我们有时在穿越机房时会自然而然地面临延迟。这时候如果数据有延迟,肯定是有区别的。DCP需要知道数据不一致是因为延迟还是真的不一致。还有黑白名单机制,自定义规则,白名单中的一些表我们可以跳过不验证。自定义规则可以设置一些对应的过滤条件进行比较,过滤掉一些不需要比较的数据。DCP不仅支持数据一致性的校验,如果表结构不一致也需要校验,甚至多维数据也可以提供校验支持。例如,可以根据用户和商户拆分订单。这两个数据是否一致需要验证。还有就是我们需要去控制和比较的是它的延迟,并发,还有验证时长等等,因为你的验证一直在跑,消耗太大了,跑的时间长了肯定会影响生产。***我们需要提供灵活的修复工具和配套脚本。这样可以快速恢复比对数据。否则,虽然知道数据有问题,但要查出数据有多不一致,如何修复,再根据情况编写脚本,需要花很长时间。您的维修可能会对业务产生比较大的影响。DCP平台上线后,每天需要验证400多套集群,日均验证数据超过60亿条,验证频率为分钟级。实际发现的数据一致性问题至少有50+例。不一致的原因可能是业务写错了,DRC有bug,也可能是各个环节(包括DB)的配置问题。如果没有相应的数据校验工具,很难知道数据是否一致。加班的时候一定要能够把握好这种情况,否则就会手足无措。刚才讲的是数据校验DCP平台,也有HA的保证。集群的数量增加了一倍。这时候需要保证任意一个节点都能尽快切换。同时,如果你的节点发生调整或者下线,你需要保证HA的配置可以相应的改变,否则HA的成功率就得不到保证,不可能靠人肉来保证超过800组集群。所以我们做了一个EMHA,它有什么作用?首先,可以自动感知集群中任何节点的变化。当然,我们的底层依赖于MHA。如果你用过MHA配置,你就知道它需要和SSH通信。任何调整都需要在配置文件中增加或删除,否则切换时会出现问题,因此EMHA增加了自动感知配置保留的功能来自动解决这些问题。第二个重要的功能是变化信息的扩散通知机制,因为我们是通过DRC来同步数据的。如果一个master出现问题,切换了,此时必须通知DRC连接到新的master,需要提供相应的位置信息,需要通知各种监控。master挂掉后需要知道哪个master是新的master,否则后面维护的信息会混乱。第三点,我们的切换需要让Proxy层自动感知。如果不能自动感知,则每次切换Proxy时,都需要维护。这可能会中断生产访问,而这种维护的质量基本得不到保证,所以EMHA也会自动完成与Porxy配置层信息的互通。保留配置也是一件麻烦的事情。如果节点发生变化,我们在代理层的配置也需要改变(调整不同于切换,切换DAL可以被EMAH自动感知)。有各种参数。如果调整不同,还需要全局同步。这些东西需要很多自动发现的方法,包括自动处理的方法。当然,有些还没有自动化(我们正在努力),有些是通过检查脚本发现的。至少我们可以保证我们能够找到并解决它们。从容量上来说,现在有两个机房,两个机房的流量不一定平衡。比如上海机房70%的流量,北京机房30%的流量,但是流量会随时切换,所以要保证每个机房都能承担所有的流量。当然,如果是三个机房,不一定绝对冗余,但也要知道每组集群能否承载切换后的流量,否则切换会面临雪崩效应。因此,我们必须对各项指标进行相应的水位监测,提前发现这些问题。DDL还有一个很大的难点,就是在DRC里面做DDL不方便。我们之前也尝试过让DRC同步DDL操作。比如我们在做DDL的时候,一般都是使用PT工具来做。这个过程需要复制整个表的数据。如果表比较大,DDL时两个机房之间的流量会面临很大的冲击,延时会比较大。比如一个100G的表在一个机房完成,必须同步到另一个机房。这种对业务的影响是不可接受的。所以DDL需要DBA在各个机房单独做。我们开发了一套DDL发布工具,因为我们有很多数据类型,包括globalzone和shardingzone,还有大量的shardingtables。对于单个业务逻辑表的DDL,我们实际上一个集群有几百张表,而这张表分布在多个集群中。所以在实际业务中对一个逻辑表的DDL操作,实际的DDL需要做千张表,并且有各种类型的业务集群。我们在发布工具时必须能够自动适应和识别这些情况(这个时候元数据的维护很重要,因为人已经识别不出来了,只能依赖工具)。刚才讲DDL的时候,大家一般都是用PT工具。我们在使用的时候也发现了很多问题。毕竟是同步触发。一旦加进去,如果瞬间TPS很高,数据库就炸了。所以我们在这方面也做了很多改造。现在在大多数情况下,我们不再使用PT。您可以看到这张图片中有几个工具可供选择。我们基于开源社区的gh-ost做了一次二次开发改造,改造后的工具叫做mm-ost。是一款跨机房DDL工具,不仅解决了DDL时线程运行不可控、主从延迟不可控的问题,还解决了跨机房延迟问题,速度是gh-的两倍原声带我们有多个机房,多机房跟你在一个机房的DDL是完全不一样的,因为你的机器可能不一样或者很忙。可能这个机房的DDL写完了,另一边要半个小时才能写完,尤其是一个业务逻辑表的DDL对应上千个物理表的DDL时,差距就更大了。由此造成的跨机房延时业务可??能是无法接受的,所以我们需要的不仅是保证同机房DDL主从延时的可控性,还要保证跨机房的可控性延迟。mm-ost现在可以支持3~5秒内跨机房同步完成DDL的时差。这个延迟对业务没有意义,可以支持暂停,在检测到DDL数据延迟时减慢速度,根据机器负载动态调整DDL的速度,所以现在DDL基本都是给业务用的。说没感觉。另外大家可以看到我们的发布平台很复杂。它的底层调用了mm-ost,我们在发布平台上也做了很多控制。比如DDL空间是否满,每台主机是否满足DDL的条件,主从我们需要控制延时在30秒以内,有锁的时候需要放慢速度,定时执行是也支持。因为我们有些业务的低峰是在晚上4点,DBA不可能每次都在4点这样。这时候就需要定时功能的支持了。此外,系统还可以通过识别业务高峰和低谷来推荐何时进行DDL。还有一些风险识别控制。我们还需要估计DDL的持续时间。如果开发问一个500G表的DDL,要多久才能完成?你需要粗略地告诉它,并给它一个期望。总之,发布这块是我们面临的最大挑战,我们在这上面做了大量的工作。我们有相当多的DDL。可以说,多活转型过程中,DBA发布的最多。多活改造的时候,我们的DDL基本上每周都有四位数的工单,而四位数的工单数量,在底层可能会产生一千个逻辑表的DDL,至少是5位数DDL物理表的数量。如果完全靠DBA来执行,很难支撑,所以我们增加了自动发布功能,系统自动执行低风险的工单。粗略的比例在8:2左右,大部分都是自动释放的。向上。我们只需要人来处理风险比较高的工单。半年时间,我们统计了大概15000个工单。收益与前景***多活完成后有什么收益?在做更多的工作之前,我们也面临着很多棘手的问题:比如我们面临着整个机房的问题(核心交换机问题、网络问题)。还有一些机房,因为以前业务没那么大,你不能预留很多机柜,现在你说我的业务增长很快,现在我要加1000台机器或者2000台机器的时候,我发现你不能添加它们,因为你的IDC给不了你这个支持,他们不可能给你预留那么多机柜。这时候你就会面临单机房无法扩容的烦恼。以前,只能考虑迁移到更大的机房,但这也是一件费时费力、成本高昂的事情。我们做了很多工作之后,首先打破了单体机房的容量瓶颈。当单个机房扩容不了的时候,我们现在可以在另一个机房扩容我的机器,也可以分流不同的流量来满足负载。房间容量限制。还有一个就是多货上线后,我们的流量砍了大概20倍。有时是演练,有时是真正的失败。现在我们不再受单个机房故障,甚至单个区域故障的影响。如果有一天上海彻底断电,对我们影响不大(当然只是指技术层面)。也有故障的细分。有些问题可能比较麻烦,没办法一下子判断或解决。到时候影响可能很大,但只影响单个机房。这时候可以把业务切换到另外一个机房,等我们解决问题后再把流量切回来。这样对业务来说基本不会有什么损失,所以工作多了之后,我们整体的易用性也会有很大的提升。另外一个就是动态调整各个机房的流量,尤其是在做一些促销活动的时候,有些区域的流量明显不平衡。这时候,如果能动态调整机房之间的流量访问,这是一个更好的分担压力的方式。像阿里双11这样的活动,要根据流量压力来调整机房之间的分配。接下来说一下多中心区后续可能做的一些事情:一个是多个机房,现在正在筹备第三个机房,因为两个机房的成本比较高,有更多的冗余。我们需要建第三个机房来分摊费用。当然,一开始的成本是比较高的。如果未来业务继续上升,我们可能不需要做太多的扩张。而且,可以重新部署现有的冗余机器资源,从而降低未来的成本。还有一个就是数据分片,这个我们还没有做,因为我们每个机房的数据都是全量的,这也是我们以后努力的方向。另一种是自动动态伸缩。我们需要更细粒度的控制能力来自动完成这些动作,尤其是硬件资源利用率的动态调整。***有一点是我们希望提供一个多机房数据强一致性的架构方案,因为我们现在讲的是最终一致性。对于一些非常重要的数据,如何在各个机房提供及时且强的数据一致性?这也是我们未来需要努力的方向。郭国飞,饿了么DBA负责人,从事数据库行业10余年,专注于MySQL、PgSQL、MSSQL等数据库领域的管理、研究和平台开发。目前在饿了么维护工作负责数据库团队的管理和数据库管理工作。
