万实例规模下数据库故障自愈探索实践每天需要处理200多条告警。随着运维规模的增大,线上故障会越来越多,DBA处理每一个故障的及时性会降低。如果没有强大的工具来提高排查和修复故障的效率,那么在线稳定性就会受到影响。不保证。所以,我们的想法是,虽然我们要继续提供更丰富的工具,但是再丰富的工具,还是要被人们主动去使用。因此,改变以人为主体、工具为辅的运维模式,引入自动化分析更为重要。以及自愈手段,提高运维效率。2.实现思路2.1短期和长期目标目标确定后,下一步就是确定目标实现思路。在调研了业界的一些解决方案后,我们发现能力的发展可以概括为以下三个阶段:平台化:可以提供一些数据和统计信息,运维人员可以根据这些信息进行运维;智能化:已经可以提供分析和建议,但是否采纳需要运维人员判断;自动化:部分场景可以实现自动恢复,无需人工参与。通常平台的开发流程就是上面说的,但是也需要根据我们自己的情况来决定,因为我们投入的人力少,没有团队合作,所以不可能按照这样的开发策略。因此,基于人力投入的情况,我们的目标是短期内做投入产出比最高的工作,以求立竿见影,但从长远来看,图中系统的基本能力仍然需要建造。.2.2寻找切入点要想在短期内取得立竿见影的效果,就需要寻找切入点。如果我们观察故障的生命周期,我们可以看到故障的生命周期分为故障前、故障和故障后:“故障前”包括故障预防;“故障前”包括故障预防。“故障”包括故障发现、故障定位和故障恢复;“失败后”包括失败后的恢复。从整个故障生命周期来看,根据我们的经验,DBA的大部分时间都花在了故障定位和故障恢复上,而且由于每一类故障都有相似的定位路径,更容易定义定位规则,沉淀专家经验。因此,我们的思路是围绕故障定位和故障恢复两个阶段来提高DBA的运维效率,优先考虑一些投入产出比高的场景,实现故障自愈。2.3结合实际情况的发展思路结合上述的近期和远期目标,我们确定了这样的发展思路。首先,我们将重点关注各种故障场景的自动分析和自愈。这些自动分析和自我修复行为是由故障消息驱动的。进行故障定位等操作。然后在这个过程中需要某种基本能力的时候,着重培养这种能力。这样,我们的短期和长期目标就可以兼顾。2.4实施过程中如何保证数据库的可用性在实施方案之前,我们需要思考一个问题,即实施过程中如何保证数据库的可用性?之所以单独提出数据库可用性,是因为故障自愈是自动触发执行的,过程中通常需要接触数据库,比如查询数据库的状态或者进行操作,那么这个自动操作本身因此,更需要考虑的是如何避免在实施过程中对数据库的可用性造成影响。那么如何避免可用性影响呢?我们的答案是将每个故障自愈方案的上线流程标准化。3.具体实现3.1故障自愈方案上线流程下图是在可用性是首要考虑的前提下确定的故障自愈方案的上线流程。①确定方案:当有新的故障自愈场景需要实施时,首先需要确定自愈方案,即确定在本次故障中需要做什么,怎么做设想。这里有两种方法可以确定计划。可以和DBA咨询沟通确定方案,也可以通过分析网上案例确定方案。②开发与测试:方案确定后,进行程序的开发与测试。这里无需赘述。③在线灰度:开发测试完成后,需要在线灰度。这里我们支持特定对象的灰度。比如某个集群经常出现此类故障,可以为该集群指定灰度。如果没有特定的对象,也可以设置百分比随机灰度。当然,如果某些故障场景出现的频率非常低,我们也会在开始时进行在线演练,通过在线模拟故障的方式进行验证。每个故障自愈方案上线后都不是最终形态,我们需要结合用户反馈和后续案例,不断迭代优化上述过程的“定解”和“演化方案”五个步骤是重点,所以下面展开介绍。3.1.1确定解决方案在实践中,我们通过咨询DBA和分析在线案例来确定故障自愈方案。咨询交流下面介绍磁盘告警时自动清理MySQLBinlog的解决方案。我们通过与DBA的协商沟通确定了解决方案。具体求解过程如下图所示。其实整个解决方案集中在两个问题上:第一个问题,如何判断哪些Binlog不能清理?答案是未备份的Binlog无法清理,因为会影响增量备份;备库未同步的Binlog不能清理,会影响复制同步。第二个问题,删除时如何保证系统可用性?这里我们批量删除,每次sleep一秒,来平滑删除带来的IO压力。案例分析有时并不是所有的解决方案都可以通过协商和沟通来确定。对于根因分析场景,由于每个运维人员的运维经验不同,如果要枚举所有可能的情况,那么会导致计划很长,所以更好的方法是确定通过分析线上真实案例来制定方案,从而输出最适合线上情况的方案,未来也可以不断结合案例进行迭代优化。下面介绍一下我们如何确定SQL告警根因的SQL分析方案。为了确定这个解决方案,我们分析了50个在线案例:首先找出哪些案例可以清楚地看到根因SQL,然后细化根因SQL的类别,最后得出根因SQL判断步骤。3.1.2演化解决方案针对某一故障场景的解决方案通常不具备一步到位自动恢复故障的能力,而是在实践中不断演化。我们将解决方案的演进过程分为三个阶段,如下图所示:那么为什么要分阶段演进解决方案呢?从效率的角度来看,先行快速上线的相对简单的方案,可以快速提升运维效率;从可用性的角度来看,前一阶段是下一阶段的基础,只有前一阶段的验证成熟了才能继续进化,才是比较稳妥的做法。以SQL失败场景为例,展示解决方案的演进过程。一开始,我们的SQL故障场景预案只是提供了数据和统计,然后进一步分析案例,试图根据规则找出导致告警的根因SQL。目前正在实现针对根因SQL的自动优化建议。最终目标是有能力自动优化和限制问题SQL。3.2故障自愈过程基于以上思路,我们实现了一个故障消息驱动、基于规则的故障自愈过程。首先,我们听取了故障信息。当自愈系统收到故障消息后,会根据消息类型在规则库中查找对应的自愈流程,然后通过流程编排引擎运行。过程中会调用相关的基础能力,最终生成处理结果通知发送到我们的工作通讯软件。同时,这个过程的运行信息也会保存在分析中心。用户可以在分析中心看到详细的现场快照和分析结果,也可以对本次分析发表评论。下面介绍该过程中的关键组件。3.2.1故障信息首先是故障信息。在设计之初,我们希望能够支持接入各种故障信息,比如告警事件、巡检事件等,但在实践中,我们还是优先考虑TOP告警场景。开发,因为大多数故障信息都是警告。而且根据我们的统计,TOP5的告警几乎占了所有告警的一半,优先处理TOP告警可以在短期内取得不错的效果。3.2.2规则库规则库保存了故障消息类型与自愈过程的绑定关系。自愈系统收到故障消息后,会根据消息类型在规则库中查找对应的自愈流程。这里我们实现了一个简单的流程编排功能。我们的想法是先实现一些原子操作,然后把这些操作组合成一个流程,这样可以让操作的复用性更好,也更容易实现新的流程。比如CPU告警,我们把TOP分析和SQL根因分析分离成两个原子操作,这样这两个操作也可以在其他流程中复用。3.2.3分析中心在分析中心,用户可以看到监控告警详情、现场快照和分析结果。还可以给我们反馈告警的原因,如何排查等信息,帮助我们迭代优化。这样自愈过程就不是黑盒了,也方便运维人员协同。3.3数据采集与计算3.3.1数据采集故障自愈需要大量的数据支持,我们将数据分为三类。监控数据:我们这边的数据库种类很多,每个数据库都有自己的监控和采集方式;日志数据:在采集过程中,Agent会先查询Manager需要采集哪些日志,然后逐行逐行采集,然后上报给Manager,最后由Manager解析根据配置的正则表达式转化为结构化数据写入Kafka。这些日志包括慢日志、运行日志、满日志等;事件数据:我们开发了一个事件系统SDK,每个服务通过这个SDK将自己的服务事件上报给事件系统。3.3.2数据计算数据采集完成后,还需要对一些数据进行计算和处理。我们现在实时计算数据的场景比较少。下图是近期完整的SQL需求。首先,Agent收集SQLLOG文件并批量上报。为了减轻Kafka的带宽压力,在上报的时候需要进行压缩。上报的时候指定实例地址作为Kafka分区键,可以保证同一个实例的数据可以写入同一个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。五、未来展望展望未来,还有很多东西需要逐步建立和完善:建立可观察、可追踪的效果衡量机制。目前唯一可观察的指标是告警覆盖率,还无法衡量每项分析的有效性和准确性,需要建立一套效果衡量机制;还有很多基础能力需要逐步建立和完善,比如SQL优化建议、SQL限流等功能;基于规则的故障自愈方案容易出现投入产出比较低、系统容量瓶颈等问题。因此,需要借鉴行业解决方案,逐步使用AI技术,在各种功能场景中进行尝试。笔者介绍林凤英,vivo互联网高级数据库研发工程师。
