万级实例规模下的数据库故障自愈探索实践

精选
数据库 其他数据库
随着运维规模越大,线上故障也就越多,DBA 对于每个故障的处理时效将会下降,如果没有强有力的工具能提高故障的排查和修复效率,那么线上的稳定性就得不到保障。因此我们的想法是,我们固然要不断提供更加丰富的工具,但无论工具再丰富,都需要人去主动使用,因此更重要的是改变以人为主、工具为辅的运维模式,引入自动化分析和自愈的手段来提升运维效率。

1.背景

近几年 vivo 数据库运维规模快速增长,从数量上看增长了几倍,达到了万级别的规模,与此同时 DBA 每日需要处理200多条告警。

随着运维规模越大,线上故障也就越多,DBA 对于每个故障的处理时效将会下降,如果没有强有力的工具能提高故障的排查和修复效率,那么线上的稳定性就得不到保障。因此我们的想法是,我们固然要不断提供更加丰富的工具,但无论工具再丰富,都需要人去主动使用,因此更重要的是改变以人为主、工具为辅的运维模式,引入自动化分析和自愈的手段来提升运维效率。

2.实现思路

2.1 短期和长期目标

目标确定后,接下来需要确定目标的实现思路。我们调研了业界的一些解决方案后,发现能力的发展可以总结为以下三个阶段:

图片

  • 平台化:能够提供一些数据和统计信息,运维人员再基于这些信息来进行运维;
  • 智能化:已经能够提供分析和建议,但是否采纳需要运维人员自行判断;
  • 自动化:已经有部分场景可以实现自动恢复,无需人工参与了。

通常平台的发展过程如上所述,但是也需要结合我们自身的情况来决定,因为我们投入的人力较少,不是成团队地投入这个工作,因此不太可能遵循这么一个发展策略。因此基于人力投入的情况,我们定下的目标是,短期内我们要做投入产出比最高的工作,以求达到立竿见影的效果,但长期来看,图中成体系的基础能力还是需要建设起来。

2.2 寻找切入点

为了短期达到立竿见影的效果,就需要寻找一个切入点。如果我们观察一个故障的生命周期的话,可以看到故障的生命周期分为故障前、故障中和故障后:

图片

  • “故障前”包括故障预防 ;
  • “故障中”包括故障发现、故障定位和故障恢复;
  • “故障后”包括故障复盘。

那么从整个故障的生命周期来看的话,按照我们的经验,DBA 大部分时间都是消耗在故障定位和故障恢复上的,而因为每类故障具有相似的定位路径,所以比较容易去定义定位规则、沉淀专家经验。因此我们的想法是将重点放在故障定位和故障恢复这两个阶段上,去提高 DBA 的运维效率,优先找一些投入产出比高的场景去实现故障自愈。

2.3 结合实际情况后的发展思路

结合前面提到的短期目标和长期目标,我们确定下来这么一个发展思路。

图片

首先我们会重点去实现各类故障场景的自动分析和自愈,这些自动分析和自愈行为是由故障消息驱动的,这也是一个比较直观的方式,因为 DBA 通常也是收到故障消息后,才去进行故障定位等操作。然后当过程中需要某类基础能力时,就去重点发展该能力。

这样我们的短期目标和长期目标就都能兼顾到。

2.4 如何在实现过程中保证数据库可用性

在实现方案前,需要先思考一个问题,即我们如何在实现过程中保证数据库的可用性?

之所以把数据库可用性单独提出来,是因为故障自愈是自动触发、自动执行的,而且过程中通常需要去触达数据库,比如查询数据库的状态或执行操作,那么这种自动的操作本身会带来比较大风险,因此更加需要考虑实现过程中,如何避免对数据库造成的可用性影响。那么如何避免可用性影响呢?我们的答案是将每个故障自愈方案上线的流程标准化。

3.具体实现

3.1 故障自愈方案上线流程

下图是我们以可用性为第一考量的前提下,确定下来的故障自愈方案上线流程。

图片

①确定方案:当有一个新的故障自愈场景需要实现时,首先需要把自愈方案确定下来,即确定在这个故障场景中,需要“做什么、怎么去做”。这里有两种确定方案的方式,可以和 DBA 进行咨询交流确定方案,也可以通过分析线上案例来确定方案

②开发测试:方案确定后进行程序的开发测试,此处不必赘述

③线上灰度:开发测试完成后,需进行线上灰度,这里我们支持针对具体对象进行灰度,比如某个集群经常发生该类故障,那么可以指定灰度该集 群。如果没有具体对象,也可以设置百分比随机灰度。当然如果某些故障场景发生的频率很低,我们一开始也会进行线上演练,通过在线上模拟故障的方式来进行验证

④全网生效:灰度完成后,开放全网生效

⑤演进方案:每个故障自愈方案不是上线后就是最终形态,还需要我们结合用户反馈以及后续案例来不断进行迭代优化

上述流程的五个步骤中,“确定方案”和“演进方案”是重点,因此下文展开介绍。

3.1.1 确定方案

在实践中,我们通过和 DBA 咨询交流以及分析线上案例的方式来确定故障自愈的方案。

  • 咨询交流

这里介绍下发生磁盘告警时自动清理 MySQL Binlog 的方案,通过和 DBA 咨询交流的方式,我们确定了该方案。具体方案流程如下图所示,其实整个方案就重点关注了两个问题:

第一个问题,如何确定哪些 Binlog 是不可以清理的?答案是未备份的 Binlog 不能清理,因为会影响增量备份;备库未同步的 Binlog 也不能清理,因为会影响复制同步。

第二个问题,如何保证删除过程中的系统可用性?这里我们采用分批删除、每次删除睡眠一秒的方式来平滑删除带来的 IO 压力。

图片

  • 案例分析

有时不是所有方案都能够通过咨询交流的方式确定下来,对于根因分析的场景,因为每个运维人员的运维经历有所差别,如果要把所有可能的情况枚举出 来,那么会导致方案十分冗长,因此一种更好的方法是通过分析线上真实案例来确定方案,这样产出的方案是最贴合线上情况的,后续也可以不断结合案例做迭代优化。

这里介绍下我们如何确定 SQL 类告警根因 SQL 分析方案。为了确定这个方案,我们分析了50个线上案例:首先找出哪些案例是能明显看出有根因 SQL 的, 再对有根因 SQL 的类别进行细化,最后得到根因 SQL 的判断步骤。

图片

3.1.2 演进方案

针对某个故障场景的方案通常不是一步到位、直接拥有自动恢复故障的能力的,而是在实践中不断演进。我们把方案演进的过程分为下图三个阶段:

图片

那么为什么要分阶段去演进方案呢?

从效率的角度看,能够先快速上线比较简单的方案,可以快速地提高运维效率;

从可用性的角度看,前一阶段是后一阶段的基础,只有前一阶段验证成熟了,再去不断演进是比较安全的做法。

以 SQL 故障场景为例来演示方案的演进过程。我们的 SQL 故障场景方案一开始只是提供数据和统计,然后进一步地通过案例分析的方式,使其可以根据规则尝试找出导致告警的根因 SQL,目前正在实现对根因 SQL 的自动优化建议,最终目标是可以具备对问题 SQL 自动优化、自动限流的能力。

图片

3.2 故障自愈流程

基于上述的思路,我们实现了一个故障消息驱动、基于规则的故障自愈流程。

图片

首先我们监听了故障消息,当自愈系统接收到故障消息时,会根据这个消息类型去规则库中查找对应的自愈流程,再通过流程编排引擎运行起来。流程中会去调用相关基础能力,最后生成一个处理结果通知,发送到我们的工作沟通软件。同时也会将这次流程的运行信息保存到分析中心,用户后续可以在分析中心看到详细的现场快照、分析结果,还能对这次分析进行评价标注。

下面对流程中的重点组件进行介绍。

3.2.1 故障消息

首先是故障消息,在一开始设计时,我们期望是可以支持接入各种故障消息,比如告警事件、巡检事件等,但是在实践中,我们还是优先针对 TOP 告警场景进行开发,因为故障消息中,绝大部分都是告警。而且据我们统计,TOP 5 的告警差不多占了所有告警的一半,优先针对 TOP 告警短期内能取得不错的效果。

图片

3.2.2 规则库

规则库保存了故障消息类型和自愈流程的绑定关系,自愈系统收到故障消息后,会根据这个消息类型去规则库中查找对应的自愈流程。这里我们实现了一个简单的流程编排功能,我们的想法是,先实现一些原子操作,再去将这些操作组合成一个流程,这样可以让操作具有的复用性,也更容易实现新的流程。

比如针对 CPU 告警,我们将 TOP 分析和 SQL 根因分析独立成两个原子操作,这样这两个操作也能复用在其他流程中。

图片

3.2.3 分析中心

在分析中心,用户可以看到监控告警详情、现场快照、分析的结果,还可以通过这里向我们反馈这个告警的原因、如何排查等信息,帮忙我们去进行迭代优化。这样自愈流程就不是一个黑盒了,也方便运维人员之间进行协作。

图片

3.3 数据采集和计算

3.3.1 数据采集

故障自愈需要大量的数据支持,我们将数据分为三种类型。

监控数据:我们这边的数据库种类比较多,每种数据库都有自己监控采集方式;

日志数据:采集流程中 Agent 先会向 Manager 查询自己需要采集哪些日志,然后以类似 tail 的方式一行一行地采集,再上报给 Manager,最后由 Manager 根据配置的正则表达式解析成结构化数据,写入 Kafka。这些日志包括慢日志、运行日志、全量日志等;

事件数据:我们开发了一个事件系统的 SDK,由各个服务使用这个 SDK,将自己服务的事件上报到事件系统。

图片

3.3.2 数据计算

数据采集后,一些数据需要做计算处理。我们现在对数据做实时计算的场景比较少,下图是近期的全量 SQL 需求。

图片

首先由 Agent 采集 SQL LOG 文件,进行批量上报,为了降低 Kafka 的带宽压力,上报的时候需要进行压缩。上报时指定实例地址作为 Kafka 分区 Key, 以保证同一个实例的数据能写到同一个 Kafka 分区,因此也就能保证在实时计算端,同一个实例的数据会落在同一个处理线程上,这样就能在接收到数据后,做一个预聚合,降低发往下游的网络流量。然后通过逐层聚合的方式,先聚合出每分钟每个 SQL_ID 的平均执行次数、平均响应时间等指标,再根据SQL_ID 的聚合数据,聚合出每分钟每个 Table 的平均访问次数指标。最后这份数据将用以支撑 SQL 趋势、表流量统计、SQL 过载保护等功能。

4.成果和案例

4.1 成果

10+种故障场景分析和自愈能力:

图片

使用6人月覆盖线上70%以上告警:

图片

4.2 案例

这里介绍一个案例:长时间执行的 SQL 数量达到阈值后,产生了告警,根据 SQL 根因分析得出,这是因为有一条长时间运行的 SQL 阻塞了其他 SQL,并把分析结果推送到故障处理群。从分析详情可以看出,这是一个 MDL 锁等待的经典场景,因为某条 SQL 长时间运行,备份进程执行 FLUSH 时请求 MDL 被阻塞,继而引发后续 SQL 请求 MDL 阻塞。

图片

5.未来展望

展望未来,仍有许多事项需要逐步建设完善:

建立可观测、可跟踪的效果度量机制。目前可观测的指标只有告警覆盖率,而对于每次分析的有效性和正确率,现在还无法度量,因此需要建立一套效果度量机制;

仍有许多基础能力需要逐步建设完善,比如 SQL 优化建议、SQL 限流等功能;

基于规则的故障自愈方案容易碰到投入产出比降低、系统能力瓶颈等问题,因此需要借鉴业界方案,逐步使用 AI 技术,在各个功能场景进行尝试。

作者介绍

林锋英,vivo互联网高级数据库研发工程师。


责任编辑:武晓燕 来源: dbaplus社群
相关推荐

2021-03-27 22:00:37

数据库故障移动端

2022-06-30 10:56:18

字节云数据库存储

2009-12-23 15:53:36

ADO.NET访问数据

2023-01-05 07:54:49

vivo故障定位

2019-01-14 08:18:43

DBA数据库运维

2010-11-16 11:27:53

SQL Azure数据

2021-01-21 11:30:59

数据泄露漏洞信息安全

2017-06-12 18:24:25

数据库压缩技术

2024-07-10 08:00:00

数据库流式数据库

2010-08-04 13:37:43

2023-09-14 17:39:19

向量数据库火山引擎AI

2018-12-14 11:04:56

数据库运维智能

2011-03-24 17:21:42

Oracle数据库Redo故障

2009-07-16 09:48:29

数据库连接

2023-02-07 09:43:48

监控系统

2015-06-01 15:25:06

Oracle数据库灾难恢复

2013-10-08 09:54:41

数据库安全数据库管理

2011-05-26 09:36:07

Oracle数据库Redo故障

2021-04-09 08:21:25

数据库索引数据

2010-05-12 18:41:34

MySQL数据库
点赞
收藏

51CTO技术栈公众号