作者简介:吴其朋,滴滴分布式存储运维负责人
滴滴出行作为涵盖网约车、出租车、顺风车、代驾等业务的一站式多元化出行平台,拥有全球客户 6.5 亿。在平台出行种类十余种且服务如此体量的用户时,滴滴出行的底层数据库主要采用 MySQL,且拥有上万套集群。其中单实例超 2TB 的集群为 400+套,最大的集群规模为几十分片,数据总量已超百 TB。还有数十套非 Innodb 引擎的 MySQL 服务如 RocksDB、TokuDB 等。
然而,底层数据库矩阵随着业务的高速增长逐渐在性能、效率,成本,一致性这四个方面显露瓶颈。
首先,某业务在访问 MySQL 百亿大表时,延迟高达上百毫秒,造成业务 SQL 超时,影响业务流程。同时,因为该表有事务依赖,所以无法通过拆表的方式提升其访问性能。
其次,由于审计和业务需求,核心归档服务中需要保留大量历史数据,导致服务存储量高达几十 T 甚至上百 T,每次业务有新增表字段等 DDL 需求时,DDL 过程都会持续数天或数周。严重影响业务上线时间,降低产品迭代效率。
再次,某些业务既需要 TP 能力,又需要 AP 能力。因此由 MySQL 提供 TP 能力,然后通过链路把数据同步到大数据平台,业务同学再进行 AP 访问。这不仅使运维成本增加,还带来了业务同学的学习和改造成本。因此,我们希望 TP 场景和 AP 类场景可以在内部闭环,降低成本,加速业务迭代效率。
最后,滴滴出行的金融服务对数据一致性有强依赖,无法接受 MySQL 主从上百毫秒级延迟,导致所有的金融服务只能依靠强制读写主库的方式。当业务流量上涨时,我们只能通过不断地拆分主库提升性能,这不仅浪费从库资源,还会造成业务成本翻倍增长。
面对上述 MySQL 痛点和业务挑战,我们把选型和调研工作投入到分布式数据库领域,没想到也是一波三折。
引入分布式数据库某 DB 无法满足业务需求
根据业务需求,我们确定引入分布式数据库必须满足三个条件。
一是能够解决当前性能差、效率低、成本高,以及数据一致性方面的问题。根据上文所述,我们希望数据库有秒级的在线 DDL 功能、更便捷的横向扩缩容能力、天然的强一致性、更低的学习与运维成本,同时,能够对下游链路提供支持。
二是要足够稳定,稳定性即我们对业务同学承诺的 SLA 标准,包含可恢复性、Lantency、限流模型、容量模型。这也是我们选型时的基础要求。
三是要符合滴滴出行的未来业务规划,其中最重要的是双活需求。
在 2021 年初,我们调研了几款发展较为成熟的分布式数据库,并在 2021 年中引入当时的选型结果——某 DB,开始搭建测试集群,学习分布式数据库的基础知识。
后续,从测试到正式上线历经四个阶段。
第一阶段:2022 年初,对某 DB 进行 Sysbench 压力测试、兼容性测试,以及验证高可用场景、周边工具可用性、DDL 和扩缩容能力。
第二阶段:2022 年 8 月,我们搭建了非核心归档库,用于积累线上运维经验,让组内同学都能在真实环境中进行实战演练,同时锻炼大家解决问题的能力。
第三阶段:2022 年 9 月,我们在某 DB 接入公司级监控,编写运维手册,期望当我们遇到故障时可以根据预案 SOP 轻松解决线上问题,并经过长期实践能更好地接入自动化平台。
第四阶段,2023 年初,我们在某 DB 接入线上归档库和在线集群。
在某 DB 上线后,解决了部分 MySQL 的使用问题。比如,除索引以外的其它 DDL 操作基本都秒级完成;再比如横向一键扩容的功能非常实用。但是,我们在日常运维以及和业务同学平时的沟通中,发现了一些线上问题。
第一个问题是在进行日常集群扩容、索引添加的整个过程中,业务延迟基本会上涨近 40%。
第二个问题在于日常的抖动,在业务流量、业务模型不变的前提下,某 DB 会出现间接性的延迟抖动,抖动范围在 40%-100%不等。因为业务对延迟数据库的响应延迟非常敏感,当出现延迟变长的情况时,整体响应超过业务阈值,造成大量 SQL 执行失败,对客户产生极大影响。
第三个问题来自于业务的下游同步需求,比如是否可以依赖当前的 Canal 链路,把数据同步到 MQ、Kafka 以供其他业务方使用,用最小的代价达到业务需求。
针对这三个问题,我们做了一些优化和调整,比如参数优化、调小并发度、增加存储节点数量等,可仍不能达到业务侧对延迟的要求。因此,我们开始再次调研是否有更适合的分布式数据库方案。
转角遇到分布式数据库 OceanBase
在调研分布式数据库的过程中,我们通过技术文章认识到 OceanBase 的能力,比如稳定、性能较高、可灵活扩展、降本表现不错等,结合对 OceanBase 社区论坛动态的观察,初步分析其可能满足我们的业务需求,于是展开了进一步的测试验证。
基于上一次分布式数据库选型失败的经验和教训,我们并没有对 OceanBase 进行常规的测试流程,而是针对线上问题进行定向压测和场景演练。我们认为,只有满足线上需求,才能进行更深的探索。
首先,测试日常抖动。低峰期业务配合 100%模拟线上流量直接发压,我们进行了 4 次压力测试,每次持续 3 小时以上。在压力测试的过程中,业务同学还会不断变化压力模型,比如 1:1 的读写、2:1 的读写、3:1 的读写等。在测试结束后,DBA 同学根据业务同学提供的 SQL 访问模型,自己编写接口模拟业务场景,再通过滴滴出行压测平台进行一周持续发压测试。经过两轮这样的压力测试,OceanBase 在延迟方面表现平稳,整体压测期间没有出现明显的延迟抖动,CPU 负载也很稳定,业务端也没有像之前线上一样因延迟问题出现大量报错的情况,完全满足我们业务方的需求。
其次,验证常规业务流量下,扩容、缩容对业务 Latency 的影响。基于 OceanBase 运维平台 OCP 便捷的 API 接口,我们通过简单调用几十分钟内就实现了之前需要长达数天的自动扩、缩容操作。不断地观察切换过程 Latency 的情况。结果显示,在切换过程中会产生 20s 左右的延迟上涨(满足业务诉求),其余时间段均平稳度过,没有产生扩容期间延迟上涨的问题。
最后,我们基于业务流量对 1T 大表进行多达几十次的加索引操作,观察延迟情况。结果显示,一直到索引添加结束,都无明显延迟上涨。
在经过上述基于业务场景的测试后,OceanBase 的性能满足业务需求。在接下来的一个月,我们开始为上线做准备。
我们验证了 OceanBase 与 MySQL 的兼容性,对 1000 个 CASE 进行回放,发现有 22 个函数变量未通过验证,但经过比对,这 22 个函数均未在滴滴出行线上业务使用。因此,OceanBase 100%兼容线上业务。
在上线任何存储方案或功能前,我们都会对故障预案进行验证,涵盖网络、磁盘、内存、CPU、节点故障等。我们此次故障预案基于 OCP 运维平台,这是一个白屏化的操作平台,即便是刚接触 OceanBase 的同学,根据预案也能达到线上及时止损的效果。顺便一提,除 OCP 外,OceanBase 的其他工具如 OMS 迁移工具、binlog_service、obdiag 巡检也都符合要求。
为避免疏漏,我们仍然对 OceanBase 进行了高可用验证、磁盘 I/O 性能测试、基准压力测试。
高可用验证:2.5W/s QPS 压力下进行单点故障测试,1T 集群 15 秒内可以完成自动切换,15 秒后集群整体运行稳定. 。
磁盘 I/O 性能测试:模拟 OceanBase 顺序写、随机读的文件访问方式对磁盘进行性能测试,以判断机型的使用极限。
基准压力测试结果如下图所示:
OceanBase 在滴滴出行的落地效果
滴滴出行在 OceanBase 上线的第一个业务是特征库,其特点是对接业务广泛,公司内很多业务依赖特征库做数据聚合与数据分析。因此,当特征库在线上出现问题时,影响范围较大。在 OceanBase 上线初期,业务同学采用双写随机读的方式验证其性能,这样能保证问题发生时可以随时回滚,还能更直观地对比上线前后的性能变化。
从下图可见,OceanBase 上线后,性能提升明显,其稳定性表现也得到了业务同学的一致认可。
OceanBase 在滴滴出行上线后,我们开始完善基于 OceanBase 的上下游生态。上文提到,我们需要解决下游数据链路支持的问题,滴滴出行的大多数业务都需要把上游的 MySQL 或 OceanBase 的数据同步到下游的 MQ 或 Kafka,以供不同业务线或业务场景进行分析。因此,一些业务强依赖于 binlog 同步链路。
OceanBase 的 Binlog Service 在 MySQL 兼容模式下,可以将 OceanBase 的日志转换成 MySQL Binlog 文件,且全面兼容 Binlog 能力,更方便接入下游生态。当前工具基本无需改造就可以直接使用,避免了重复造轮子。可问题是,Binlog Service 目前为单机模式,无法满足高可用需求。我们的解决方案是:将多个 binlog server 部署在不同的 proxy 节点上,实现共同消费模式;Canal 通过文件名+时间戳的形式,实现单个 binlog server 故障时,自主切换到另外一个 server 上,实现高可用。
OceanBase 应用经验总结与未来规划
上线 OceanBase 之后,不仅解决了此前线上的问题,还让整体延迟缩短了近 10 倍。并且在执行 DDL、扩缩容、日常流量中,延迟整体表现平稳,没有产生间接性抖动。完全满足我们业务对延迟的要求,保证了线上业务的稳定运行。
在使用 OceanBase 过程中,让我们留下了三个深刻的印象。
第一,分区表设计,是超级大表性能稳定的保障。OceanBase 分区表的设计是它的一大亮点,使我们可以根据不同的维度对表进行分区。例如,我们有一张大表,既可以根据订单进行分区,也可以根据司机进行分区,还可以根据乘客进行分区。不仅满足业务不同维度的查询需求,而且性能有保障。
第二,日志、数据分盘存储,防止资源抢占以影响性能。起初滴滴出行由于 MySQL 历史架构导致日志和数据放在一块磁盘里,带来的问题是当上游业务量特别大,在 OceanBase 进行转储时,日志和数据会相互抢占资源,进而影响性能。将日志和数据分盘存储,就能避免这个问题,达到 OceanBase 的最佳应用效果。
第三,MySQL Shard 到 OceanBase 的多表合并问题。当我们把上游 MySQL 的多表合并到下游 OceanBase 的一张表时,我们不仅要关心迁移效率和成本,还要关心链路问题。例如,我们把 MySQL20 个库的分表合并到一个 OceanBase 库时,可能这 20 个分库是由 20 个链路提供消费,但合并到下游时只能有一个 binlog server 提供链路服务。这时,我们需要评估这个 binlog server 和 Canel 能否支持这么大的流量。
未来,我们计划扩大 OceanBase 使用规模。首先替换数十套非 InnoDB 引擎;其次逐渐承接线上的核心归档服务;最后将 OceanBase 作为分布式数据库方案,并将 MySQL 超大规模核心集群逐步迁移至 OceanBase。
另外,在运维方面,核心业务场景如多活场景、强一致场景开始接入 OceanBase,同时,将 OceanBase 运维管控平台接入滴滴出行平台,加强运维人员的问题定位、故障排查等能力。
目前,OceanBase 在滴滴出行上线的表现满足预期。在使用过程中,我们积累了三个期望或建议,希望官方能够支持。
期望实现全局自适应限流。因为业务方有时候简单粗暴,会出现大量自动重试操作,基于我们的 SLA 标准,期望 OceanBase 在未来具备全局自适应限流能力,,自动对每种类型的 SQL 限制并发度,,防止重试 SQL 瞬间激增,,导致数据库 Load 激增。这样一来,当我们设置全局 SQL 执行的并发度在 10 或 20 的时候,无论历史 SQL 还是新 SQL 都会自动统一,无需运维手动操作,当出现故障时即可快速止损。目前 OCP 具备单独对 SQL 限流的能力,但不能全局限流。
期望增加核心字段校验,增快迁移速度。在 OceanBase 上线期间,OMS 的迁移只是基于全量的迁移与数据验证(OceanBase 社区响应迅速,,最新版 OMS 已支持该功能.),但在大表迁移场景下,大表中有一些备注信息、大字段等,业务同学在数据校验时更侧重于核心字段校验。我们希望 OMS 拥有校验部分核心字段的能力,分担业务同学的校验工作,提高 OMS 的迁移速度。同时希望 OMS 支持多表的旁路导入,替代目前多表合并采用的 SQL 方式。
期望更方便的多租户拆分能力。在数据使用初期,业务的规模可能都比较小。大家为了节省资源希望把多个租户或多个业务线放在一个大的集群中,但这会遗留什么问题呢?随着业务的发展,该集群将由非核心变为核心,想把业务从核心集群中迁移出去,为了保证数据一致性,采用主备库模式,且相同的 Proxy 兼容主库和备库。在主备库搭建过程中,让备库的延迟与主库完全齐平后,Proxy 进行主备库的切换,业务几乎是无感知的。备库完全迁移出来后,我们可以通过切换 Proxy,再把业务流量迁移出来。目前据 OceanBase 社区反馈,下一个 OBProxy 版本将支持透明切换,,帮助用户完成无感迁移。
评论