饿了么异地双活数据库实战

数据库 其他数据库
尽量把业务做成类聚的,让一个用户的访问落在同一个地方。不是所有的业务都有多活特性的,还可以有全局使用的业务(比方用户数据),所以需要做业务类型划分。

 我今天的分享是饿了么在数据库和多活数据库这块的实战经历,供大家参考。

主要围绕以下五点进行分享:

  • 多活当中的难点
  • 多活的架构
  • 数据库改造
  • DBA 挑战
  • 收益与展望

多活当中的难点

我们先来看一下多活的***个难点:要考虑做多活到底是同城的多活还是异地的多活。

跨地域网络延时是现阶段很难突破的点,因为饿了么面临的是异地的多活,所以我们需要基于延时这个前提来考虑方案。

从北京到上海中间有 30 毫秒的延迟,这个会带来什么问题?我们接下来会讲。

上图是同城和异地多活不同的点,复杂性和可拓展性对架构的影响方面会有很大的不同。

我们挑几个点讲一下:

  • 如果只是做同城多活的话,像 30 毫秒的延时不需要考虑,因为同城的延时通常只有几毫秒,跟同机房相差不大。
  • 如果是异地 30 毫秒的延时就需要重点考虑了,因为如果是反复调用的应用,放大的时间就不只是 30 毫秒了,可能是 300 毫秒、500 毫秒,对很多应用来说是不可接受的。

在可扩展性方面如果做的是异地多活的话,你的可扩展性理论上来说没有太多的边界。

我们做同城多活只能在上海机房里面选,如果是异地多活,可能是全国甚至是全球都可以选。

还有一个比较难的问题,就是怎么保证数据的安全?多活数据可能面临多个写入点,可能会错乱、会冲突、循环复制、数据环路等问题。

这种情况下怎么保障一致性?如果这些没有考虑好之前,你是不能上多活方案的,多点写入的风险对数据的考验是很大的。

综合考虑下来我们选择了异地多活,所以这些问题我们都需要克服,也意味着会面临很多的系统改造。

如何解决跨机房延时对业务的影响,包括各种抖动甚至是断网的问题;怎样有效区分我们访问的流量,***限度地保障用户的访问落在正确的机房,这个都是需要解决的难点。

我们采取了一些措施,如上图:

尽量把业务做成类聚的,让一个用户的访问落在同一个地方。不是所有的业务都有多活特性的,还可以有全局使用的业务(比方用户数据),所以需要做业务类型划分。

在服务划分这一层,怎么定义业务调用的边界,还有我们基于什么对流量和用户做划分的呢?

目前根据我们的业务特点使用的是地理围栏(POI),用户、商户、骑手当前所在的地理位置是我们入口流量划分的依据。

再看看路由控制这一块,除了入口流量这一层做了机房的划分,还在内部使用了虚拟的 Shardingkey,ShardingKey 会把全国流量分成多个部分,并且与 POI 标签绑定。

这样就可以把逻辑 ShardingKey 和物理位置对应起来,切换的时候访问就可以随 ShardingKey 分流到不同的机房。

APIRouter 就是为了完成这个工作的,它会根据配置的规则把 Shardingkey 对应的流量分到对应的机房。

脏写预防方面,为防止数据冲突,我们也需要业务配合做一些多活规则的改造,这些规则对业务还是有一些侵入性的。

另外 SOA-Route 就是内部跨业务调用的访问路由;还有一个 DAL,就是数据库的代理层。

业务访问在我们多层的路由控制下,理论上应该能正确路由到合适的机房,如果超越规则或者没有按规则改造的意外流量真正穿透到 DAL 这一层的时候我们是强制拒绝的。

因为底层认为这个访问是属于异常的调用,流量走错了机房,这时候就会拒绝,所以我们宁愿让他失败也不能让控制之外的数据进来,这样才能保障规则和数据的可控性。

数据一致性方面,我们有一个重要的 DRC 数据同步组件,数据库这块有一些自增的控制,DBA 还研发了一个数据一致性校验的工具。

多活的架构

粗略说了一些多活的难点和我们的应对方案后,我们现在来看一下整个多活的架构。

如上图,最上面是我们从入口流量、分流控制、数据多机房同步,包括各个重要组件的架构等。

还有里面有 globol zone 这一项,它是我们刚刚讲的需要全局依赖的业务会把它放在 globol zone 里面。

DRC 这是做多活时相当重要的组件,主要解决数据在多个机房当中的同步复制。

我们从北京机房写入的数据,会同步到上海的机房,上海的机房写入的数据也会通过 DRC 这个组件同步到北京的机房。

大家可以看到,它包含三块服务,Replicator、Applier 和 Manager。一个收集变更数据、一个将变更数据写入到另一个机房、另外一个是做管理控制。

DB 架构这块我们有两类(准确讲还有一类是多推的,比较少):

  • ***类是 Sharding Zone,不管是数据写入还是访问都是本机房提供,出问题的时候也只是流量的切换,并不涉及到底层的变动,这个是真正多活的架构。
  • 还有一种是刚刚讲的 globol zone,有些没有办法做业务分区,因为是 globol zone 的架构,写入是集中在一个机房,读取在本地机房完成。

大家可能会想到 global zone 这种架构会天然面临一些数据延迟的问题,所以这块我们的定义是一些写入量不大,访问量大,对数据延时是不那么敏感的业务就可以放到这里面来。

数据库改造

多活项目我们调研大概花的时间有半年左右,但真正做改造的时候时间是相当短的。

从启动这个项目到真正上线就用了三个月左右的时间,那时候时间是相当紧的,大家可以看一下我列举的为配合多活数据库所做的大的改造项目。

首先面临的问题,就是我们要把数据全量的从一个机房导入到另外一个机房,这个不光有测试环境还有生产环境都要全量的同步。

我们数据有几百 T 数据,几百套集群,有各种主从结构需要搭建,每个节点时间也很短。

我们刚刚讲的 DRC 会做数据的同步,但同步的时候也会面临数据冲突的问题。

为解决这个问题,我们需要在所有表上增加一个 DRC 时间戳字段,用来判断哪一边数据是***的,这样在数据发生冲突的时候,我们会选***的数据作为最终的数据。

为防止多活主键冲突,数据库做了一些自增的调整,自增步长放大后马上就会面临数据溢出的问题,所以我们需要把主键都从 int 调整为 bigint。

主键改完以后还有一些外键依赖的也会需要改造,所以整体会要做很多的 DDL(几乎是全量表),而在 MySQL 里面 DDL 其实是风险比较高的操作。

第二个大改造是因为区分了不同的业务类型(我们刚刚讲了有 golobl zone 这些),就会面临各种不同类型的业务原来在同一套实例上的情况。

现在需要拆分迁移到不同的实例上,这个我们也陆陆续续迁移 50+ 的 DB,现在还有些在迁移。

下一个改造是我们现在用 DRC 做跨机房的数据同步了,所有的数据同步都是原生的改成 DRC 的模式,也会做很多的调整。

还有一个问题,就是帐号网段也需要做调整,因为我们原来基于安全考虑会限制某些 IP 网段,现在网段范围放大了,所有帐号都要面临调整网段的问题。

如果量比较多的话,调整账号风险还是挺高的(很多历史遗漏会使得主从账号不一致,出现同名账号不同网段等问题,如果出现不一致调整的时候主从会中断)。

另外怎么保证全局参数的一致性,起码要保证同一个集群,在各个机房参数都是一致的,这个是比较脏活累活的东西,但是很容易出问题,到处是坑。

另外 HA 也面临改造,因为原来在一个机房,现在有多个机房,怎么做到 HA 的可靠性也是一个问题,这块我们也做了很多的改造。

改造完成之后,我们对比下改造前后在数据库这端的变化。实例就翻了一倍,集群数量、Proxy 配置、数据量、HA 都会翻倍。

这里特别列了一些 DDL 的变化,为什么会有变化?因为 DRC 不做 DDL 同步这个事情,这个事情都需要 DBA 分开机房来做。

机器故障每周也增加了,原来一周碰不到一台,现在可能一周面临两到三台这样的机器故障,所以必须要保证你的 HA 是足够可靠的。

但是我们人数是没怎么增加,而且我们马上要上第三个 zone,维护的工作量会增加更多。

不过我们没有加人的计划,之所以这样是因为我们在把很多的工作通过平台、自动化和项目的方式来推动解决掉。

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 是哪一个,否则后面维护的信息都会错乱。

第三点我们的切换需要让 Proxy 这一层自动感知,如果不能自动感知的话,每次切换 Proxy 都需要维护,这个可能会中断生产的访问,而且这个维护质量基本也得不到保证,所以 EMHA 也会自动完成与 Porxy 配置层信息的互通。

还有配置的保持也是比较麻烦的事情,我们在代理层的配置,如果节点变动了也需要变(调整区别于切换,切换 DAL 可以通过 EMAH 自动感知)。

有各种参数,如果说调整不一样了,也需要全局的同步的,这些东西都需要有很多自动发现的手段,包括自动处理的方式。

当然我们现在有些也还没能完成做到自动化(正在努力中),目前还有些是通过巡检脚本来发现的,起码保证能够发现它然后解决掉。

容量这块,现在是两个机房,两个机房的流量并不一定均衡,比如上海机房 70% 的流量,北京机房 30% 的流量,但流量会随时切换,所以必须保证每个机房都能够承担所有流量。

当然三个机房的话,不一定***的冗余,但也一定要知道每套集群是不是能承载切换过来的流量,否则切换过来就面临雪崩的效应。

所以对各项指标我们都要有相应的水位监控,提前发现这些问题。

还有一个很大的困难是在 DDL 这块,因为 DRC 里面不方便做 DDL 这个事情,之前我们也尝试让 DRC 同步 DDL 操作。

比如说我们做 DDL 的时候,一般是用 PT 工具来做,这个过程要拷贝整张表的数据。

如果这个表比较大,DDL 时两个机房之间的流量就会面临很大的冲击,而且延时会相当大。

比如说 100G 的表在一个机房做完要同步到另外一个机房去,这冲击业务影响是不可接受的。

所以 DDL 需要 DBA 在每个机房单独做,我们开发了一套 DDL 发布工具,因为我们有很多数据类型,有 global zone,还有 Sharding Zone,我们还有大量 Sharding 表。

对单个业务逻辑表的 DDL 来说,实际上我们一套集群里面有几百张表,这个表又分布在多套集群里面。

所以实际业务一张逻辑表的 DDL 操作,实际 DDL 需要做一千张表,同时还有各种不同的业务集群类型,我们在发布工具时必须要能自动适配和识别这些情况(这个时候元数据维护相当重要了,因为人已经识别不了啦,只能依靠工具)。

刚刚讲 DDL 的时候,大家普遍用 PT 的工具,我们用的时候也发现了很多问题,毕竟是它是同步触发器的,一旦加上去之后,如果瞬间 TPS 很高,就会把数据库打爆。

所以我们在这块也做了大量的改造,现在大部分情况下,我们已经不用 PT 了,大家看这个图上有好几种工具可以选择。

我们基于开源社区的 gh-ost 做了一个二次开发改造,改造后的工具叫 mm-ost。

它是一个跨机房的 DDL 工具,不仅解决了 DDL 的时候 threadrunning 不可控、主从延时不可控的问题,还解决了跨机房延时的问题,并且速度比 gh-ost 要快一倍。

我们是多机房,多机房和你做一个机房的 DDL 是完全不一样的,因为你的机器可能有差异或者繁忙程度不一样。

可能这个机房 DDL 做完了,另外一边要半小时之后才能做完,尤其是一个业务逻辑表的 DDL 对应的是上千张物理表的 DDL 时,差异性就更大了。

这样造成的跨机房延时业务可能没法接受,所以我们需要的不仅是能保证同机房DDL主从延时的可控,还要保证跨机房延时的可控。

mm-ost 现在就能够支持到跨机房同步完成 DDL 的时差控制在 3 到 5 秒之内。

这延时对业务来说就没什么感觉了,而且它可以支持暂停、探测到 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 个工单。

收益与展望

***看一下多活做完以后收益有哪些?做多活之前,我们也面临过很多棘手的问题:

  • 比方我们之前面临着整个机房出现问题(核心交换机出问题、网络出问题)。
  • 还有些机房因为在业务没有那么大之前你不可能预留特别多的机柜,但你现在说我业务涨的很快,现在要加一千台机器、两千台机器的时候,发现你加不了,因为你的 IDC 不能给你这个支持,他们不可能给你预留这么多机柜。

这个时候你就面临单机房没法扩容的麻烦,之前只能考虑迁移到一个更大的机房去,但也是个耗时费力成本高的事情。

我们多活做了之后,首先打破了单机房容量的瓶颈,单机房不能扩容的时候,我们现在可以在另外的机房扩容我的机器,也可以分不同的流量来满足负载,就不再受到单个机房容量的限制。

另一个,多活上线到现在我们流量切了有 20 次左右,有时候是演练,有时候是真实发生故障。

现在就不再受到单机房故障的影响,甚至是单地域的影响,假如说上海哪一天全断电了对我们影响也不大(当然只是指技术层面)。

还有故障兜底,有的问题可能是比较麻烦的问题,一下子没有办法判断或者解决,那时候可能影响很大,但只影响单个机房。

这个时候就可以把业务切到另外一个机房,等我们把问题解决了以后再把流量切回来,这样对业务就基本没有损失了,所以多活之后对我们整体可用性也有一个很大提升。

另外一块是动态调整各个机房的流量,尤其是在做一些促销活动的时候,有些地区的流量明显是不均衡的。

这时候如果能动态的调整机房之间的流量访问,这是比较好的分担压力的方式,像阿里双 11 这种活动,应该会根据流量压力来调整各机房之间的分配。

接下来在来讲下多活这块后续我们可能要做的一些事情:

一个是多个机房,我们现在正在准备第三个机房,因为两个机房的代价比较高,冗余比较多。

我们需要做第三个机房分摊这块的成本,当然一开始成本是比较高的,往后业务继续上涨的话,可能不需要做太多的扩容。

而且现有***冗余的机器资源,可以再做调配,这样成本往后来看的话是会下降的。

另外一块是数据的 Sharding,这个我们还没有做到,因为我们在各个机房都是全量的数据,这也是我们后面努力的方向。

还有一个是自动动态扩缩容,我们需要有更细的控制能力来自动的完成这些动作,尤其是在硬件资源利用率上能动态调整。

***一个点是希望能够提供多机房数据强一致性的架构方案,因为我们现在来讲都是最终一致性的,怎么对一些非常重要的数据,提供各个机房数据及时强一致性,这块也是我们接下来需要努力的方向。

[[215855]]

虢国飞,饿了么 DBA 负责人,从事数据库行业 10+ 年,专注于 MySQL、PgSQL、MSSQL 等数据库领域的管理、研究和平台的研发等工作,目前负责饿了么数据库团队的管理和数据库维护方面的工作。

责任编辑:武晓燕 来源: 高效运维
相关推荐

2017-08-01 10:55:47

DRC应用实践

2014-11-03 16:24:55

阿里云

2019-02-26 09:39:46

数据库高可用架构

2018-04-02 09:33:03

多活技术架构运维

2018-08-30 09:43:11

DBA数据库运维

2018-07-19 11:18:45

饿了么时序数据库监控系统

2019-03-18 10:32:33

容灾双活同城

2015-03-31 18:19:37

饿了么动画效果

2018-11-29 09:36:56

大数据调度系统

2022-05-31 11:17:14

单元化异地双活

2017-11-08 13:53:35

饿了么程炎岭多活

2016-08-26 22:36:18

大数据

2017-12-05 15:03:45

人工智能饿了么大数据

2010-04-09 15:35:28

Oracle数据库

2018-11-30 12:11:11

Oracle存储配置

2017-07-21 14:48:47

AI物流O2O

2020-07-13 09:16:13

潮数数据

2023-11-28 07:45:48

Rust自动化测试

2010-05-04 14:57:27

Oracle数据库

2017-10-27 15:44:24

饿了么张龙前端基础设施
点赞
收藏

51CTO技术栈公众号