摘要:本文详细分析了GaussDB (for MySQL) 在不同层级的流控机制,包括反馈式流控在存储层和计算层的策略和流程,以及计算节点的主动平滑流控的方案。

本文分享自华为云社区《【华为云MySQL技术专栏】GaussDB (for MySQL)流控技术解读》,作者:GaussDB 数据库。

本文主要介绍GaussDB (for MySQL) 在不同服务层次上是如何实现过载保护的,具体包括反馈式和主动平滑流控两种机制。

1.背景介绍

GaussDB (for MySQL)是存储计算分离架构的云原生数据库,如图1所示:

图1 GaussDB (for MySQL)架构示意图

GaussDB (for MySQL)存算分离架构,主要分为3层:

  • SQL计算层,包括多个数据库实例,每个实例有1个主节点和多个只读节点;

  • DFV存储层,由DFV存储服务的多个节点组成,这些节点协同,为上层应用提供高效的日志读写与页面读取能力。

  • SAL层,即存储抽象层,位于SQL计算层和存储层之间。其中位于计算节点的部分,称为SAL-SQL层。

DFV存储层对数据按照slice进行分片(每个分片10G),SAL层则根据Slice粒度进行数据管理。

在计算层,不同租户的多个数据库实例会共享同一个存储服务。当其中一个或多个用户实例处于压力过载时,可能会对共享存储池产生冲击,造成存储服务的CPU、内存或者IO资源的瓶颈,进而影响服务稳定性。

GaussDB(for MySQL) 的过载保护机制分布在SQL层、SAL层以及存储层多个层级,能够基于不同维度进行分级流控。

2. 分层级的流控机制

按照流量控制方向,GaussDB(for MySQL) 的过载保护分为两种机制:第一种是由下层到上层的反馈式流控,即存储层流控后,驱动计算层流控;另一种则是计算层主动流控,精细化控制上层流量。

2.1存储层反馈式流控

存储层的反馈式流控是存储过载保护的主要机制。由于存储服务的每个Server会管理不同数据库实例的多个Slice,因此,需要在存储节点级过载保护的基础上,完成实例级、Slice级别的精确流控和分级限流。

整个流程概括为以下几个步骤:

第一步,对存储节点的关键资源和业务指标进行监控,并生成资源状态、指标统计等;

第二步,在存储层流控,基于以上状态和统计进行策略判断和决策;

第三步,将过载信息反馈计算层流控。

2.1.1 存储层流控策略

在存储节点的消息处理流程中,通过增加多处限流检查点,分别观测内部消息处理队列、任务队列、内存资源。例如,回放日志所需的Delta Cache、待处理Pending Table等,均可以作为输入监控指标。

在以上的限流检查点,可以采用多种策略进行控制:

第一种方式:通过关联较少的资源,设置单一阈值进行限流,对上下游影响较小。这里以盘级流控为例,如图2所示,每个存储节点管理多块存储磁盘,每个磁盘处理读写请求相互独立。通过监控每个磁盘的读写频率和读请求时延,来判断其是否超过阈值。如果超过,则为热点盘。

热点盘上有多个活跃Slice,如果某个Slice的写速度超过平均速度,则按照阶梯进行限速。图中Slice4的写入速度30MB/s超过平均速度20MB/s,因此,需要将Slice4进行限速。

图2 盘级流控示意图

第二种方式:对Delta cache,Pending Table等内存资源,进行使用率实时统计,识别出活跃Slice,再按照周期汇总计算出下一周期的可用配额,对当前活跃Slice进行公平分配;基于使用情况,可设置多个级别实施不同梯度的控制策略。例如,占比60%为流控触发点,进入基础限流阶段,设置80%为过载点,90%为停止服务阈值。其中,基础阶段采用线性流控,过载阶段则采用比例限速。

如图3所示,3个数据库实例共有6个Slice分配到当前存储节点,当前周期总的写入速度是30MB/s, 平均分配给每个Slice 的配额是5MB/s。

图3 Slice配额分配示意图

第三种方式,对于节点的IO资源,系统也支持根据租户设置的QoS(Quality of Service,即服务质量)阈值,来触发流控机制。例如,对某租户的Slice进行标记,在IO流控时,可以给予更大的配额。

基于上一周期的流控情况,迭代更新下一周期的流控策略,这样能够达到快速调整实时流控,并及时反馈到计算层,进而触发计算层的流控。

SQL节点的用户查询需要及时响应,可视为前台业务,而存储节点内部的数据合并等操作,通常不需要及时响应,可作为后台业务。针对前后台业务的差异性,GaussDB(for MySQL)支持优先级策略,并能够识别故障组件并进行隔离,从而避免少量业务影响整个系统运行。

此外,流控后也能够及时恢复,快速解除限流状态。

2.1.2 计算层流控策略

存储层流控时,通常设置每个Slice一个周期的可写入流量上限阈值,即WAL阈值(Window Access Limit)。例如,当前时间窗口Slice1的写入上限为2MB,SAL-SQL层查询得到该上限阈值,基于此,可以在数据流转过程中进行有效限速。

图4 计算层两个限流点示意图

如图4所示,计算层数据库实例的限速点分布在SQL层和SAL-SQL层。

第一个限速点在SAL-SQL层。SliceFlush线程将每个Slice的日志发送给存储服务,此时,系统需要进行限速判断,具体这里包括以下几点:

首先,Flush机制是积攒日志量到一定数量(例如64K)或者一定时间后才会Flush,避免频繁发送过小的请求;

其次,判断逻辑按照周期进行(目前周期为1s),根据每个周期的写入量和写入配额(即WAL,Write Access Limit)来决策,分为以下几种情况:

  • 如果待发送的数据量小于当前周期的配额,则直接发送;

  • 如果超过当前配额,且当前窗口配额没有被预消费,则超发当前数据,并且预消费接下来周期的配额;

  • 如果当前窗口已经被之前的窗口预支,则需要补偿,限流不发送数据。

另一个限流点是SQL层。在mtr(mini-transaction)提交时,检查SAL层的流控状态、内部资源情况,再结合Slice维度统计的日志积累情况,进行多级别的流控策略。其中,主关键指标是TLB(Transport Log Buffer)的使用情况。TLB是SAL层内部按照Slice把上层写入日志整理合并,并发送给一个Slice的Log buffer。详细策略包括:

  • 当内部资源处于基本限流阶段,即mtr涉及到的Slice处于流控时,则系统会根据日志积累量,换算出相应的等待时间,从而执行睡眠操作,以实现Slice的缓慢提交。

  • 当内部资源过载阶段,则禁止提交mtr,直到过载解除。

同时,按照相同顺序进行限速和解除限速,避免不公平的限速导致某些线程饿死。

2.2 计算层主动平滑流控

单个数据库实例在读写压力过载,甚至超过资源瓶颈时,也可能出现雪崩现象,导致整体业务响应出现异常。例如,某种子业务突增,引发大量的并发批量读请求,会导致同一实例的其他业务请求也受到影响,因此,对计算层进行流控也是必要的。

在计算层数据库节点上,分别针对读写请求,进行细粒度平滑流控,可以避免计算节点本身过载。

首先,在SAL-SQL层,数据库节点会统计每个周期的日志写频率和页面读取频率,作为核心指标。这些统计包括同步请求和异步请求,将其统称为页面更新频率。统计过程具体是在SAL层日志写链路和页面读取接口实现。

其次,根据数据库节点的读写能力,按照不同规格预设合适的读写阈值上限。当统计到的页面读写频率超过对应的读写阈值时,触发主动平滑流控机制。

图5 主动限流在SAL层的两个控制点示意图

主要的控制逻辑分为两种:

Strong限流,即需要当前线程sleep,直到指标降低到阈值内;

Weak限流,通过算法计算出等待时间,并sleep一定时间。

目前有3个控制点:

第一个是Redo日志加入SAL-SQL层调度线程时,如图中限流点1所示,如果日志写频率超过写阈值时,则进行Strong限流,否则按需进行Weak限流。

第二个是在每个Slice刷新线程中进行Weak限流,如图中限流点2所示。

第三个是在页面读取链路中,根据页面读取频率和阈值进行Weak限速。

概括来说,等待时间是基于放大倍数和一个基础步长来决定的。其中,放大倍数能够快速放大等待时间,达到快速流控的效果。放大倍数是根据页面频率超过阈值的比例来决定的,目前设置4个级别,分别对应1-4倍。基础步长是权衡性能消耗和流控灵敏度之后的一个预设参数值。

同时,在限速阶段,采用串行队列管理机制来处理并行提交的请求,确保按照先来的请求先得到处理。

3. 流控效果

为了演示反馈式流控,我们对多个数据库实例同时进行压力测试,包括:

  • 2个8U,2个16U,13个32U规格实例,按照某真实业务读写比例1:4的业务模型进行sysbench读写压测,每个实例64张表,单表1000万行;

  • 5条数据迁移链路,其中5个32U规格实例作为目标端,插入数据。实验过程中,通过人工降低存储层流控触值,模拟触发流控场景。

可以观察到压力上涨触发存储层流控后,较大写入压力的计算节点实例的QPS下降,系统处于限流状态。恢复阈值后,限流状态解除,业务QPS恢复,如图6 QPS所示。同时,较小写入压力的计算节点实例,对QPS无影响,如图7 QPS所示。

图示数据对比说明,反馈式流控可以精准的控制大压力数据库实例。

图6 反馈式流控大压力实例QPS图

图7 反馈式流控小压力实例QPS图

接下来演示计算层主动平滑流控。

首先,对一个4U16G实例进行sysbench读写混合模式压测,观察其读写的页面频率指标。其日志写频率为6093次/秒,页面读频率为3195次/秒。

其次,通过运维平台设置较小的读写阈值。

本实验设置日志写阈值为4500次/秒,页面读阈值为3000次/秒,随后可以观察到很快触发平滑限流,业务QPS快速下降,且较为平稳的维持在一个限流后的水位,并该状态一直持续到测试结束,整体效果图8所示。

图8 主动平滑流控实例QPS图

4. 小结

本文详细分析了GaussDB (for MySQL) 在不同层级的流控机制,包括反馈式流控在存储层和计算层的策略和流程,以及计算节点的主动平滑流控的方案。作为过载保护的主要手段,流控一方面可以避免流量过大造成服务资源耗尽产生雪崩效应,另一方面也力求高效快速,尽可能地充分利用服务资源,产生更大价值。

点击关注,第一时间了解华为云新鲜技术~

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐