火山引擎 veDB 是字节跳动自研的云原生分布式数据库,采用"计算-存储分离"的云原生架构,主打"一主多从、弹性扩缩、高可用、低成本",并且100% 兼容 MySQL 协议。对内承载字节跳动 90% 以上的关系型数据库流量,服务产品覆盖范围:抖音、电商、广告、番茄小说、懂车帝、飞书、豆包等核心业务线。总实例数达 10 万级,总数据量达百 PB 级。对外 veDB 以 DBaaS 形式向企业客户输出,帮助快速构建海量、高并发、低延迟的在线业务。企业客户业务的核心诉求是云服务的质量保证可靠,veDB 以极致服务保障能力定义了云原生数据库的可靠性标杆。单可用区部署月度可用性≥99.95%,三可用区金融级部署≥99.99%。
为保证线上云服务的质量标准,火山引擎严格控制服务故障的 MTTR(Mean Time To Repair)。线上问题处理采用"三步法"把时间轴拆解极致,即问题发现(MTTI)、根因定位(MTTK)、故障止损(MTTR)。本文着重介绍 veDB 在问题发现和根因定位方面所做的技术探索。
诊断流程
技术是用来解决问题的,在介绍诊断技术前需要先说明诊断过程面临的问题。
1. 问题发现
一般系统运维问题发现主要依靠的 3 种手段,分别是:告警通知、定期巡检、人工报障。
- 告警通知:
veDB 设置了四层监控指标:资源层(如:CPU/IO/网卡)、业务层(Proxy 端到端 QPS、RT、Error等)、计算层(DBEngine 内核指标)、存储层(logstore/dbstore 内核指标)。基于四层监控指标设置告警通知,紧急情况下可进行 OnCall 升级。告警机制虽然能主动发现问题,但容易告警配置不合理,告警不足则问题不能及时发现,告警太频繁又会淹没有用信息。
- 定期巡检:
巡检的检查机制与告警方式相似,可认为是告警通知的降级处理方式。首先告警是发现问题即通知,而巡检是每日推送的方式通知;其次因巡检不紧急故检查的阈值更严格,可能导致误判,其主要目的是提醒运维人员检查潜在风险。巡检的问题是实时性不足,检查逻辑简单,既可能误判也无法做风险预测功能。
- 人工报障:
人工报故障是问题发现的最后一道防线,问题故障可能已经对客户业务造成了影响,因此应该避免依靠这种方式发现问题。一切的努力的方向都是先于客户发现问题。
2. 根因定位
veDB 当前问题根因定位主要依赖 3 类诊断信息:监控指标打点、系统日志、系统状态。
- 监控指标
如前所述,veDB 设置了四层监控指标,监控项定期打点上传到监控平台,形成可视化的时间序列图表。监控项打点频率可按不同场景调整,支持秒级打点和分钟级打点。实践中使用最多的是 30s 级打点。
- 系统日志
系统日志是各模块运行的历史记录,对分析问题非常有帮助,包括:OS 系统日系、Proxy 访问日志、mysqld日志、全量 SQL 日志、存储 IO 访问等等;
- 实时状态
实时状态反映系统实时运行状态,只临时保存在内存中不做持久化保存。特点是包含的信息量巨大且最及时,所以价值非常高。比如:processlist 列表、线程池调度排队信息、锁关联视图信息、InnoDB 运行状态等等。
定位过程
veDB 采用人工诊断和智能 RCA(Root Cause Analyze)相结合的方式定位根因。因为纯依靠人工诊断整个过程耗时比较长,主要耗时节点在:
-
各种诊断信息复杂,收集信息需登陆各类系统平台,操作繁琐过程比较耗时;
-
数据库系统原理复杂,诊断难度较高且要通过分析信息间的关系来确定根因耗时耗力,非常依赖个人经验;
-
当遇到一些关键信息缺失时,只能依靠问题复现,而有些问题复现非常耗时。
因此 veDB 结合智能 RCA 的能力,将问题定位流程标准化、标准流程自动化,并引入大模型 AI Agent 能力进行根因诊断,使得问题场景诊断快速、高效、准确。
3. 故障止损
依赖问题发现和根因定位,简单问题可以立即止损操作,复杂问题若要做到精确止损往往依赖根因定位,若根因定位时长过长,则需要有问题兜底手段立即执行止损,可能无法将问题根除,或带来更大的损失。
问题场景
要系统性地解决诊断难的问题,还需要对问题进行场景分类,应针对不同场景采取不同的应对措施。结合线上问题经验积累,可大致分成三类:
- 资源瓶颈类问题
该类问题是一种资源使用率上升导致为了瓶颈。"资源"是个广义概念,任何争抢对象都可看作资源。比如,机器物理资源、各层级对象的锁、网络发送通道、CPU 调度队列等。资源瓶颈的具体表现,如 CPU /内存用量上升、锁竞争加剧、线程调度拥挤、网络发送或磁盘 IO 出现排队等等。
- 时延升高类问题
此类问题又可分为整体性时延升高和单个时延毛刺突发变高。整体性时延升高可能与资源瓶颈类问题相关,具体表现为系统所有访问响应都变慢。时延毛刺类问题表现是平均时延没有变化但 p99 时延升高很多,时延毛刺无规律性的出现,问题出现的频率很低。
- 系统异常类问题
该类问题主要表现为系统运行不符合预期,比如节点间的流量分配不均、不合预期的切主行为、业务访问连接异常中断、实例变更耗时过长等等。此类问题的原因多种多样,可能是系统内部的 bug、网络抖动异常、应用侧的异常建连访问等等。
根据线上问题的轻重缓解程度,又可进一步将问题诊断场景细分成下列三类。三种诊断场景紧迫程度、投入的资源和采集的信息密度不一样,面临的问题也不一样。
日常运维
日常运维中需要监测所有线上实例的运行状态,通过告警和巡检等手段主动发现问题。该使用场景需要覆盖所有的实例,先于客户发现问题。日常运维的特点是线上监测的实例数量多,告警发生频繁且没有固定的时间段约束限制。问题诊断虽不十分紧急但诊断的频次高,不能完全依靠人力解决而需借助智能 RCA 等手段进行辅助分析定位。
客户重保
客户刚搬迁上云或者重要大促活动期间流量会发生突增,此时最容易发生线上问题并引发故障。因此除了日常运维的告警巡检 oncall 机制外,还需要投入专门的人力进行重点看护。此时需提高诊断信息采集密度,缩短问题反馈链路。虽可以通过添加更多的告警和巡检,或者是用专人进行值守。但这样做无疑会加重运维负担,拖慢整体日常运维响应效率。
紧急情况
日常运维和重保期间,一旦发现故障风险会立即启动紧急情况应对。所有核心技术会召集在一起进行分析诊断并应尽快止损。此时面临如何分工协作、信息共享等问题。应快速提升多人协作效率,多路径进行根因定位并且要定期对外同步问题解决进展情况。
诊断技术
为了应对解决上述不同场景下的多类问题,我们采用了多种诊断技术。分别介绍如下:
全量 SQL 洞察:
全量 SQL 洞察的应用范围比较广泛,对于定位系统资源瓶颈类问题非常有帮助。比较典型的问题场景是:CPU 使用量高、内存使用量高、系统整体时延上升等,因为全量 SQL 日志中记录了所有访问 SQL 的详情,因此通过全量 SQL 洞察可以快速精准的定位到业务的应用 SQL 类问题,比如:访问流量异常、SQL 扫描行数过多、表上缺少索引等等问题。全量 SQL 洞察中记录了每一条 SQL 的耗时情况以及各种资源的开销,并且按照 SQL 模版和时间维度做了聚合。如下:

全量 SQL 洞察实现过程中面临 1 个难点问题:如何在不对系统整体性能造成大的影响前提下记录全部的 SQL 详情。veDB 是基于官方开源 MySQL 的产品,我们知道官方开源版本有 general log 功能可以记录下全部的访问 SQL 到外部文件,但代价是性能可能下降 30%+,故而不能一直打开。而 veDB 全量 SQL 日志功能能将整体性能开销控制在 5% 以内,因此可以常态化开启。这主要得益于以下几个技术优化手段:
-
使用系统共享内存代替外部文件记录 SQL 日志,这样就避免了磁盘 IO 的时间开销;
-
使用内存预取的方式分配内存,使得各线程写 SQL 日志时互相不影响;
-
使用特定的数据编码方式,减少日志写入的长度从而加快写入速度;
-
使用异步化方式,将一部分日志内容放到后台线程写入,减少前台线程的等待时间。
此外,veDB 还在 SQL 日志写入成功率和性能损耗间做了平衡处理,当系统整体负载非常高的情况下可能会主动丢弃部分 SQL 日志以保障系统平稳运行。全量 SQL 日志写入到外部共享内存,由第三方 Agent 消费并上传到 TLS 日志存储系统,然后交给 DBW(火山引擎数据库管理平台)进行管理。DBW 通过离线任务对 SQL 日志内容按照 SQL 模版和时间维度聚合操作。历史全量 SQL 日志最长保存时间为 3 年,单实例的全量 SQL 日志最大保存容量可达 T 级别。
全链路时延分析
全链路 SQL 时延分析功能解决的是单条 SQL 访问时延过高的分析难题,应用的场景包括:1)整个系统访问中偶发性的 SQL 时延毛刺;2)单条 SQL 执行慢的内部根因分析。
由于 veDB 是一个分布式的系统,包含了Proxy(代理)、DBEngine(SQL引擎)、logstore(日志存储)、pagestore(页面存储)等多个组件。单条 SQL 执行慢的原因可能在任何一个组件上。当一条 SQL 端到端时延变慢时需要定位到具体的组件模块,SQL 全链路时延分析功能可以定位到每个模块内部整条执行路径上的具体耗时情况。每一条访问 SQL 以全局唯一的 trace id 做标识,SQL 在每个组件上执行的耗时信息日志都带上唯一 trace id。故而用户可以通过 trace id 追踪 SQL 在每个组件上的耗时情况。

在单个组件内部,使用 SQL span(SQL 时延分析打点)功能追踪 SQL 的执行链路上的耗时情况。整条 trace 路径由许多 span 点组成,每个 span 点是耗时统计的基本单元,可以是一个函数也可以是一个算子。以 DBEgine 的 SQL trace span 功能为例,追踪一条 SQL 执行耗时情况如下:
mySQL> select * from (select avg(A.id), B.a from t1 A join t1 B on A.id = B.id+1 group by (B.a)) T where T.a > "a1";
+-----------+------+
| avg(A.id) | a |
+-----------+------+
| 3.0000 | a2 |
| 4.0000 | a3 |
| 5.0000 | a4 |
+-----------+------+
3 rows in set (0.00 sec)
mySQL> show execute trace\G
*************************** 1.row ***************************
Trace Context: ->mySQL_execute_command (2.562192..1)
->SQL_cmd_dml::execute (2.388568..1)
->SQL_cmd_dml::prepare (0.696748..1)
->MaterializeIterator::Init (0.922564..1)
->TemptableAggregateIterator::Init (0.776973..2)
->Hash inner join (A.id = (B.id + 1)) Init() (0.444853..2)
->Filter (B.a > 'a1') Init() (0.024934..2)
->Table Scan on B Init() (0.013996..1)
->Filter (B.a > 'a1') Read() (0.302327..4)
->Table Scan on B Read() (0.287474..5)
->Hash inner join (A.id = (B.id + 1)) Read() (0.228659..3)
->Table Scan on A Read() (0.209698..5)
->TemptableAggregateIterator::Read (0.008778..3)
->Table Scan on <temporary> Read() (0.003867..3)
->MaterializeIterator::Read (0.008924..3)
->Table Scan on T Read() (0.003049..3)
->trans_commit_stmt (0.030673..1)
同时 SQL trace span 信息可记录到外部日志文件,方便事后追踪单条 SQL 的执行耗时情况,支持通过支持 trace id 去查找指定 SQL 的耗时信息,如下:
mySQL> SHOW SQL_SPAN EVENTS in "SQL_span_20241016150333" for 45\G
*************************** 1. row ***************************
Trace_Id:45
Start_UTC:2024-12-18 11:35:37.516054
Context:
->mySQL_execute_command(0.224688..1)
->SQL_cmd_dml::execute(0.120011..1)
->SQL_cmd_dml::prepare(0.036168..1)
->Rows fetched before execution Init()(0.000231..1)
->Rows fetched before execution Read()(0.000340..2)
->trans_commit_stmt(0.007625..1)
告警智能诊断
日常运维过程中告警发生的频率比较高,告警发生就表明系统运行可能出现了问题,需要运维人员立即投入分析。我们在告警根因定位过程中遇到了几个难点,1)告警分析定位过程没有标准,完全依赖个人经验;2)定位过程依靠人工分析,耗时耗力。
针对问题1,我们的解法是对每一种问题场景梳理沉淀一个专家定位经验的标准 SOP 指南文档,并且通过反复的故障演练来验收 SOP 指南的效果,做到每一位运维人员拿来就能用。
诊断问题2,我们的解法是基于问题 SOP 指南来构建智能 RCA 能力,基于内部的 SpaceX 诊断平台来构建自动化诊断能力。SpaceX 智能诊断平台支持构建工作流和 AI 大模型调用。我们要做的是根据 SOP 指南的固定步骤流程在 SpaceX 上构建诊断工作流,工作流上的工作节点包括:获取诊断信息、指标间的比较运算、调用大模型进行推理分析。以下通过 CPU 高的诊断例子展示,如何将 SOP 转变成诊断工作流。
以下是诊断 CPU 高的整个 SOP 逻辑流程:

按照一般的方式可以基于编程逻辑判断的方式通过一堆的"if else"判断来得到最终的诊断结果,但这种方式工作流配置复杂(复杂度完全取决于 SOP 逻辑),并且最终只能得到一个结果而忽略完整的逻辑判断过程。
有了 AI 大模型后,我们可以将 SOP 的逻辑模版投喂给大模型,并且将实时的诊断信息也投喂给大模型,让大模型根据诊断信息和 SOP 模版自己去推理出结果。整个工作流的配置如下:

最终大模型输出的结果不但能展示根因,还能给出推理的整个过程,让人一目了然。下面是一个诊断结果的例子:

除了配置智能诊断 RCA 外,还需要将其与特定的告警关联起来,这样告警发生时就能自动触发智能诊断 RCA 得出诊断根因。该过程还是在 SpaceX 诊断平台上配置,基本原理是:告警发生时联动相关智能诊断项,将告警 context 信息传递给智能诊断 RCA 对象并触发其执行,最终将诊断结果发给飞书告警卡片。整个过程如下:

-
argos 是火山内部使用的告警管理平台,可通过规则为具体的业务场景配置告警;
-
SpaceX 诊断平台可将 argos 告警和智能诊断 RCA 关联起来,同时用飞书机器人来打通消息链路;
-
运维群中配置飞书机器人来接收 SpaceX 的告警信息,告警通过卡片发生展示告警内容和根因分析。
智能重保观测
新客户刚搬迁上云,或者客户重要业务活动期间,一般都是故障风险发生概率最高的时期。通常我们会为每个重保客户配置专门的告警和巡检,以便问题发生时能够及时处理。此外需要持续关注实例运行的健康状况,观测关键核心指标状态,及时识别出潜在风险。比如:资源使用增长趋势、指标的骤升或骤降、指标违反周期性规律的异常变动等等。因为此类现象不一定代表问题,故而不适合放在告警中。且情况判断逻辑相对复杂,也不适合放在定期巡检中去做。当遇到非常重要的重保场景时,我们一般会安排专人进行值守盯盘。
而为了进一步提升效率,及更加全面的覆盖客户重保场景的盯盘需求,引入了自动化 AI 观测能力。定时去获取核心关键指标进行判断,包括实时状态检查和未来趋势判断。实时状态检查逻辑借鉴告警判断逻辑,且判断的阈值会更低。未来趋势判断借助 AI 大模型能力做综合分析,大模型会根据过去一段时间的数据变化规律分析未来趋势,以识别潜在的风险。

秒级指标监控
基于性能和资源空间的考量,一般监控指标的打点频率是分钟级别,使用最多的打点频率是 30 秒。但是对于一些极端场景,整体系统性能会迅速劣化,分钟级别的监控粒度完全满足不了诊断定位需求。为此需要实现秒级别的监控打点能力。监控打点频率可设置为 1s、5s,但同时带来的是对系统性能影响以及监控打点资源的空间开销增加。
为此需要对监控指标的打点频率进行了分级管理,在保留全量指标分钟级打点基础上,增加核心指标的秒级打点监控。并逐步用秒级监控去替换分钟级监控。同时为了缓解秒级监控打点资源空间占用问题,也对使用场景进行了分级,优先对客户重保场景开启秒级监控。结合 Fatal 应急处理信息收集能力,可以减低秒级打点历史数据的保留周期时长。
总结
本文讨论了火山引擎 veDB 诊断技术实践,涵盖 veDB 的特点、应用场景、诊断流程、问题场景分类及相应诊断技术等内容。关键要点包括:
-
诊断流程:问题发现依靠告警通知、定期巡检、人工报障;根因定位依赖监控指标打点、系统日志、系统状态,采用人工诊断和智能 RCA 结合;故障止损依赖前两者,复杂问题需兜底手段。
-
问题场景分类:按问题类型分为资源瓶颈类、时延升高类、系统异常类;按紧迫程度分为日常运维、客户重保、紧急情况。
-
全量 SQL 洞察:对定位系统资源瓶颈类问题有帮助,能将整体性能开销控制在 5% 以内,可常态化开启,历史日志最长保存 3 年,单实例最大保存容量达 T 级别。
-
全链路时延分析:解决单条 SQL 访问时延过高问题,可定位到每个组件内部整条执行路径上的具体耗时情况。
-
告警智能诊断:梳理 SOP 指南,基于其构建智能 RCA 和自动化诊断能力,与告警关联,自动触发诊断。
-
智能重保观测:针对客户搬迁上云或重要活动等重保场景,通过定时获取核心指标开展实时状态检查(阈值更低)和 AI 大模型驱动的未来趋势判断,辅助或替代专人值守盯盘,提升重保期间风险观测效率与覆盖度。
-
秒级指标监控:为应对系统快速劣化的极端场景,在保留全量指标分钟级打点基础上,实现 1s/5s 级秒级打点能力;通过分级管理平衡监控粒度与系统性能、空间开销,满足极端场景下的精准诊断定位需求。
欢迎点击【阅读原文】提交工单参与试用,体验 veDB 智能诊断创新。