文/网易 田维繁
我主要和大家分享网易游戏在规模化 TiDB SaaS 服务运维以及处理高并发业务方面的实践经验。我的介绍将围绕三个核心方面展开:
- 首先是对网易游戏 DB SaaS 服务的概览。
- 其次是我们在实施 TiDB SaaS 服务过程中的具体做法。
- 最后是针对高并发请求业务的优化措施和问题解决方案。
一、数据库现状
我们为网易游戏及其周边服务提供一站式数据库管控服务
- 平台服务层, DMS 负责数据维护和治理,DTS 负责数据库之间的数据迁移,比如 MySQL 到 TiDB 之间的迁移以及到kafka迁移等。DaaS,主要负责服务管理,包括调度和备份。
- 在数据库服务层面,提供了包括 MongoDB、Redis、MySQL、TiDB等在内的多种 数据库SaaS 服务。根据最新的统计数据,TiDB 集群的数量已超过 100 套,TiDB 的数据总规模超过了 1PB,在网易游戏中的应用中已经达到了相当的规模和深度。
二、TiDB 在网易游戏使用场景
TiDB在网易游戏的应用场景非常广泛和复杂。包括基础架构服务、云存储、内部管理和质量治理等 OLTP 场景;以及上游是 MySQL,下游TiDB 作为读扩展的业务场景;重 OLAP 场景下的业务,比如使用 TiSpark 直接请求 PD 进行报表统计计算;利用 TiDB 的横向扩展能力, 进行数据归档
三、TiDB SaaS 平台服务介绍
3.1 套餐定制
针对多样化的业务场景,我们提供定制化的服务套餐,以满足不同计算和存储需求。我们的SaaS服务根据具体的业务需求,设计了多种专属套餐。
- 高并发请求的 OLTP 场景,如游戏服务,我们推出了高性能套餐。例如,18 核 CPU 和 180GB 内存的配置,专为满足高并发业务需求而设。
- 高存储套餐,主要针对大型业务场景的数据归档需求,同时兼容 OLAP 业务需求。
- 普通套餐适用于常规业务场景,常规的的 TP 和 AP 业务。
- 测试套餐,采用较小规格 6C 主机或云虚拟机,以支持业务的测试和验证环境。
3.1.1 虚拟化与资源隔离
资源隔离有几个点需要考虑
1. CPU隔离
- 不同实例使用不同cpu资源
- 实例间使用cpu互不影响
2. 内存隔离
- 不同实例使用不同的内存段
- 实例间使用内存互不影响
3. 磁盘IO隔离
- 独占实例间使用不同的磁盘
- 独占实例间磁盘互不影响
- 独占实例可以动态进行扩容
4. 虚拟节点请求独立
- 实例间的进程和数据互不可见
- 实例有独立的请求入口
- 实例间安装的依赖包互不依赖互不可见
在实施套餐定制后,我们对节点进行虚拟化处理。在此过程中,资源隔离至关重要。我们采用轻量级LXC虚拟化技术,以实现 CPU 和内存的有效隔离。对于 IO 密集型节点,例如 TiKV 节点,我们在 SSD 盘上创建不同的 LVM,并将其挂载至不同虚拟机下,确保磁盘响应的独立性。至于网卡流量隔离,得益于多张万兆网卡的配置,通常流量不会成为限制因素。
3.1.2 套餐升级
平台支持套餐升级,以适应业务量的增长。如果需要从标准套餐升级至更高性能的套餐,会根据宿主机的资源情况,提供动态扩容服务。包括动态调整CPU、内存和磁盘资源。若宿主机资源不足,后端服务将执行节点的增加和删除操作。虽然这一过程可能较长,但通过新增节点、负载均衡后再删除旧节点,确保整个升级过程的顺利进行。
3.2 备份
3.2.1 快照备份
在 TiDB SaaS 平台上,备份快照服务扮演着至关重要的角色。尤其在 OLTP 场景中,快速备份和恢复的能力对于数据回档等操作至关重要。用户可以通过简单的操作,在进行游戏维护或其他业务操作时,实现整个系统的完整备份,而不会对业务流程造成任何干扰。
快照服务使用 LVM 技术来创建 snapshot,用户只需一键操作,即可生成快照并继续进行其他任务,无需等待复杂的备份流程完成。根据需要,生成的快照可以被复制到备份盘,或者上传至 S3 存储,这一过程完全由用户自行选择。这样的设计使得备份过程轻量且快速,对业务的影响降到最低。
然而,快照备份作为一项可选操作而非默认备份方式,是因为它存在一些局限性。例如:
l 可能会造成一定的空间浪费,因为数据盘需要预留空间给 snapshot;
l 不支持库表级别的备份;
l 恢复时,必须在相同规模的 TiKV 节点集群中进行
尽管如此,快照备份仍然满足了一部分业务需求。
3.2.2 BR 备份
我们也提供 TiDB 官方的 BR 备份作为常规备份方式。BR 备份操作简便,直接备份至远程 S3 存储。我们广泛使用公有云服务,如 AWS、GCP、阿里云和微软云等,对于支持 S3 的云服务,我们直接备份至 S3;对于不支持的,则采用快照备份方式。
BR 备份的优点包括灵活简单的备份操作,支持库表级别的备份,以及稳定的 5.0 以上版本。此外,它无需预留数据盘空间,并且恢复过程相对灵活,无需指定同等规模的 TiKV 节点。
3.2.3 恢复过程
对于不同的备份方式,采取不同的恢复策略。
l 快照备份,我们会下载每个节点的备份,然后使用 TiDB 的 recover 工具将其恢复至 TiDB 集群。为防止数据覆盖,我们会为 alloc_id 赋予较大的值,确保恢复过程中数据的完整性。
l BR 备份的恢复则更为直接,只需从 S3 拉取备份并恢复至 TiDB 集群即可。
通过这些备份与恢复策略,确保了数据的安全性和可靠性,为用户提供了灵活的数据保护解决方案。
3.3 DTS
3.3.1 MySQL 与 TiDB 数据流向的闭环
在 TiDB SaaS 平台中,我们经常需要在 TiDB 集群与 MySQL 之间进行数据同步。为此,我们提供了 DTS 服务,允许用户直接在 MySQL 中指定库表,并根据预设的规则进行同步,如同步特定表、更改库名等,通过我们封装的 DM 服务实现与 TiDB 集群的同步。若需反向同步,即从 TiDB 同步回 MySQL,用户可以通过 TiCDC 服务进行注册,实现指定表的反向同步,确保数据迁移的完整性和正确性。
3.3.2异构数据的同步
此外,我们还支持异构数据的同步。通过 TiCDC,我们可以根据用户定义的规则,将增量或全量数据同步至 Kafka 集群,并进一步同步到其他非关系型数据库。提供了一个全面的异步数据同步解决方案,满足不同数据同步需求。
3.4 定制化监控调度服务
在我们使用的初期,在实际业务的应用中也遇到了很多问题,比如:
- 监控探测不够灵敏:发现探测不够灵敏,业务访问 TiDB 出现严重卡顿情况时,探测没有任何报警
- 热点问题频发:业务热点问题频繁,没有很好的方式去打散,需要人工干预处理
- 空间异常暴涨:长事务或者 TiCDC 异常导致,GC清理异常,空间暴涨
- TiKV leader 频繁抖动:海量 region,PD 根据空间占比进行调度
针对这样的情况,我们也因此打造了定制化的监控调度服务。
- 我们实现了秒级的心跳探测机制,通过简单的写操作来实时监测实例状态,防止实例卡顿无法发现。同时,为了避免单点探测的不准确性,我们采用了多点多次探测策略,大多数情况下只有在多次探测均出现问题时才会触发报警,在一些特殊的业务实例中,我们也会根据敏感性来配置单次探测失败的告警。
- 针对热点问题,我们采取了主动监控和自动处理的策略。监控 TiKV 的 CPU 使用情况,判断是否存在热点。一旦发现热点,会实时查询并尝试 split region。对于使用特定字段作为主键的业务场景,我们会主动打散热点,无需人工干预
- 对于空间异常问题,我们通过监控 GC 的运行状态和长事务来预防空间暴涨。如果 GC 运行不正常或存在长期未提交的事务,我们会及时报警,避免空间异常。
- 针对 TiKV leader 抖动问题,我们虽然不会直接处理,但根据各种可能存在的情况提供了一系列的解决方案。例如,优化 raft-base-tick-interval 参数,开启静默 region,或根据版本加大 region merge 的力度,以减少抖动现象。
四、高并发请求运维实践
4.1 业务背景
接下来分享一些我们在高并发场景下的运维实践。
在处理高并发请求的场景中,我们积累了一系列运维实践经验。以网易内部某项目为例,在业务启动初期,我们预估并发量可能超过 10 万,而实际生产环境中,该业务已达到 36 万 QPS,高峰期甚至超过 40 万。同时,插入和更新操作的数量巨大,高峰期间的 I/O 需求极为严苛。此外,大规模数据的过期清理也对数据库性能构成了挑战。
4.2 前期优化准备
因此,在真正投入使用前的设计阶段,我们就考虑到不仅要从数据库层面,也要从业务角度尽量去优化和避免这些问题。
- 针对大量写入,我们与业务团队合作,确保所有表使用 AUTO_RANDOM 策略来分散热点,减少单个热点的影响。
- 实施了分区表策略,根据业务需求设定过期时间,定期清理过期数据表,以减轻 GC 压力。
- 限制了单个 KV 的 region 数量,以避免过大的 region 导致的性能抖动。
4.3 碰到的问题与解决方案
在业务规划初期,我们遇到了几个主要问题:
- 使用 TiDB 5.1 版本时,GC 清理速度慢,导致数据堆积和空间异常增长,TiKV 节点不断增加,成本过高。
- 单个 TiDB Region 过大,一些更新非常频繁的表单个 region 可达 300G 以上(正常的 region 大小不会超过 96M),影响了数据的备份和升级;以及高并发请求下的raft抖动问题,会导致业务的波动。
为解决这些问题,我们采取了以下措施:
- 从 TiDB 5.1 升级至 TiDB 6.1.7 版本,优化了 GC 清理效率,减少了 1/4 的空间占用,并降低了成本。
- 在面对庞大集群的升级任务时,我们无法通过建立新集群并进行数据同步的传统方法来实现。因此,我们采取了滚动升级的策略,确保在新版本经过充分验证后,逐步对集群进行升级。在此过程中,我们会先创建快照,以便在升级过程中出现问题时能够迅速回滚到升级前状态。针对因 Region 过大而无法进行 split 和备份的问题,通常会在业务流量较低的时段,创建一个新的表并将数据迁移过去。然后执行删除操作(drop table),以此来减少 Region 的大小,并允许正常的数据备份和升级流程进行。
- 关于raft性能抖动,TiDB 6.1 版本会默认开启 raft engine,以降低 raft 平均时延,但随之而来的性能抖动是我们的业务难以接受的,所以我们选择关闭 raft engine,回归到 rocksdb 的默认写入方式,有效解决了性能抖动问题。
通过这些措施,我们确保了在高并发场景下的业务稳定性和数据库性能,为用户提供了更加可靠的服务。