做者介绍:李文杰,网易互娱计费组,高级数据库管理工程师,TiDB User Group Ambassador。
计费组是为网易互娱产品提供统一登陆和支付高效解决方案的公共支持部门,对内是互娱的各个游戏工做室,对外是国内外数百个渠道。因为业务场景的特殊性,咱们为各个游戏产品部署了不一样的应用服务,其中大产品环境独立,小产品集中部署。前端
随着部门业务量的激增,单机 MySQL 在容量、性能、扩展性等方面都遇到了瓶颈,咱们开始对其余数据库产品进行调研选型。本文将详细介绍网易互娱计费组针对本身场景的数据库选型对比方案,以及使用 TiDB 后解决的问题,并分享了使用 TiDB 过程当中集群管理、监控和数据迁移等方面的最佳实践,以供你们参考和交流。git
网易互娱计费组线上 MySQL 的基本使用架构,以下图所示,其中箭头方向表示数据或请求的指向:github
<center>图 1 网易互娱计费组线上 MySQL 使用架构</center>数据库
随着业务的发展,部门内各应用服务产生的数据量也在快速增加。业务落地数据量不断激增,致使单机 MySQL 不可避免地会出现性能瓶颈。主要体如今如下几个方面:后端
容量服务器
性能网络
扩展性多线程
SQL 复杂架构
数据壁垒并发
 <center>图 2 现状之数据孤岛</center>
针对目前存储架构存在的问题,有须要使用其余存储方案的可能。考虑到目前的业务与 MySQL 高度耦合,对数据库选型的主要要求有:
其余要求:
序号 | 方案 | 说明 |
---|---|---|
1 | MySQL 分库分表 | 基于 MySQL |
2 | MySQL Cluster | 基于 MySQL |
3 | MySQL + Vitess | 基于 MySQL |
4 | MySQL + MyCAT | 基于 MySQL |
5 | CockroachDB(简称 CRDB) | 兼容 PostgreSQL 协议,不兼容 MySQL 协议 |
6 | TiDB | 兼容 MySQL 协议 |
一开始仍然是倾向使用基于 MySQL 的解决方案,好比 MySQL InnoDB Cluster 或 MySQL + 中间件的方案。
咱们测试了 MySQL 集群 5.7.25 版本对比 8.0.12 版本,在 128 并发写各 1000 万行的 10 个表,比较单节点、3 节点和 5 节点下的状况,以下图所示:
<center>图 3 对比结果</center>
在测试中发现,使用 MySQL InnoDB 集群的方案写性能比单机 MySQL 差约 30%,其余的读写测试结果也不甚满意。以后陆续测试 MySQL InnoDB Cluster 或 MySQL + 中间件的方案,不是测试结果性能不达要求,就是须要修改大量代码。
所以咱们得出了基于 MySQL InnoDB Cluster 或 MySQL + 中间件的方案的不知足咱们的业务场景的结论。总结来讲,咱们不使用 MySQL 分库分表、中间件或 MySQL 集群,缘由主要是如下两点:
仔细分析来看,其实基于 MySQL InnoDB Cluster 或 MySQL + 中间件的方案,本质上是 MySQL 主从结构的延伸,并不是真正的分布式拓展,像是以打“补丁”的方式来实现横向扩展,不少功能特性天然也难以让人满意。
在开源的分布式 NewSQL 领域,知名的有 TiDB 和 CockroachDB(简称 CRDB),两者都是基于 Google Spanner 论文的开源实现。咱们对这两种数据库的功能和性能作了大量的调研和测试。
测试方面,咱们也进行了全面地对比和测试。这里说其中一个测试案例:10 台机器 5 存储节点,160 并发访问单表 2 亿行,咱们于 2018 年 7 月,对 CRDB-v2.1.0 版本和 TiDB-v2.0.5 版本进行了读写测试(CRDB 和 TiDB 集群均使用默认配置,未进行调优)。
集群拓扑
<center>图 4 CockroachDB 测试集群搭建</center>
<center>图 5 TiDB 测试集群搭建</center>
测试语句
范围查询:
SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ? SELECT SUM(k) FROM sbtest%u WHERE id BETWEEN ? AND ? SELECT c FROM sbtest WHERE id BETWEEN ? AND ? ORDER BY c SELECT DISTINCT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c
随机 IN 查询:
SELECT id, k, c, pad FROM sbtest1 WHERE k IN (?)
随机范围查询:
SELECT count(k) FROM sbtest1 WHERE k BETWEEN ? AND ? OR k BETWEEN ? AND ?
更新索引列:
UPDATE sbtest%u SET k=k+1 WHERE id=?
更新非索引列:
UPDATE sbtest%u SET c=? WHERE id=?
其中一个重要的测试结果以下:
<center>图 6 测试结果</center>
结论:
CRDB 和 TiDB 在性能表现上不相上下;
注:上面是 2018 年 7 月的基于 TiDB 2.0.5 版本的测试结果,如今 TiDB 已发布 3.0 GA 版本,在性能上有了质的提高,咱们在近期进行了补充测试,大多数场景下 3.0 版本较 2.1 版本有数倍的性能提高,最新的测试结果图以下:
<center>图 7 TiDB 2.1.15 vs 3.0.3:OLTP 峰值比较</center>
<center>图 8 TiDB 2.1.15 vs 3.0.3:TPC-C</center>
综合对比结果以下表:
数据库 | 扩展 | TP | AP | 文档程度 | 社区活跃度 |
---|---|---|---|---|---|
MySQL | 否 | 是 | 否 | 丰富 | 高 |
PostgreSQL | 否 | 是 | 是 | 丰富 | 高 |
MySQL InnoDB Cluster | 否 | 是 | 否 | 少 | 低 |
MysQL + 中间件 Vitess | 是 | 是 | 否 | 丰富 | 中 |
CRDB | 是 | 是 | 是 | 少 | 低 |
TiDB | 是 | 是 | 是 | 丰富 | 高 |
通过谨慎的考量,咱们选择了 TiDB。
<center>图 9 选择 TiDB 的重要理由</center>
网易互娱使用 TiDB 的架构设计以下:
<center>图 10 基于 TiDB 的架构设计</center>
需求 | 解决方案 |
---|---|
大容量存储 | TiDB 在线实时伸缩,无需停机和频繁清理数据 |
性能需求 | TiDB 支持多点读写,QPS 随节点数量增长而增加,理论上无限制 |
高可用需求 | TiDB 强一致性多副本存储,节点宕机不影响服务 |
数据备份和容灾 | 数据多副本;支持跨机房、跨地域部署;Mydumper + Loader 多线程并发导出和恢复 |
分库分表 | 无需分库分表,自然支持超大表的高效读写 |
打破数据壁垒 | 支持 |
业务
集群
规模
Ansible(推荐)
K8s
官方集成了 Prometheus + Grafana 的实时监控平台,从集群的各个方面进行了完善的监控,包括:
PD 监控示意图以下,集群管理员能够很方便地掌握集群的最新状态,包括集群的空间 Region 等全部状况。
<center>图 11 最佳运维实践:Prometheus 实时监控</center>
若是集群运行过程出错,在监控面板上很容易就发现,下图是使用过程当中的一个案例:
<center>图 12 最佳运维实践案例</center>
应用访问 TiDB 写入数据时发现特别慢,读请求正常。排查后,根据 TiKV 面板发现 Raft Store CPU 这项指标异常。深刻了解缘由是由于数据库副本复制是单线程操做,目前已经到了集群的瓶颈。解决办法有如下两点:
解决方法:删除过时数据。
解决方法:从 2.1.5 升级到 2.1.15,开启自动 Region Merge 功能。
问题 | 问题版本 | 缘由及解决方案 |
---|---|---|
大表建索引时对业务有影响 | 2.0 | 官方建议在业务低峰期操做,在 2.1 版本中已经增长了操做优先级以及并发读的控制,状况有改善。 |
上下游表结构不一致,同步异常 | 2.1 | TiDB 下游表比上游 MySQL 多增长几列时,DM 同步异常,其没法按指定列同步(insert into A (a,b,c) values ...)。官方表示已经在增长该功能,预计 2019 年 Q4 推出支持上下游表结构不一致的版本。 |
在一个 DDL 里不能对多个列或者多个索引作操做 | 2.1 | ADD/DROP INDEX/COLUMN 操做不支持同时建立或删除多个索引或列,须要拆分单独执行,官方表示 3.0 版本有计划改进。 |
重启 PD 节点,业务报 PD server timeout | 2.1 | 重启 Leader 节点前需手动切换 Leader。官方建议经过重启前作 Leader 迁移来减缓,后续也会对通信相关参数进行优化。 |
建表语句执行速度相比 MySQL 较慢。 | 2.0 & 2.1 | 多实例 TiDB 部署时,DDL Owner 和接收Create 语句的 Server 不是同一个时间,可能比 MySQL慢一些,耗时约 0.5s,官方表示会再完善。 |
Delete 大量数据,GC 跟不上 | 2.1 | GC 是单线程的,当删除数据量很是大时会致使 GC 速度较慢,极可能 GC 的速度跟不上写入,可经过扩容和缩短 GC 周期间隔解决,长期须要实现分布式 GC,官方表示对此已经在 3.0 版本实现。 |
存储空间放大 | 2.1 & 2.0 | 该问题属于 RocksDB。RocksDB 的空间放大系数最理想的值为 1.111。官方建议在合适场景下经过 TiKV 开启 RocksDB 的 dynamic-level-bytes 以减小空间放大。 |
Truncate Table 空间没法彻底回收 | 2.0 | Truncate 一张大表后,发现 2 个现象:一是空间回收较慢,二是最终也没有彻底回收。目前 2.1 版本优化底层 RocksDB 的机制,使用 DeleteFilesInRange 接口删除整个表占用的空间,而后清理少许残留数据,已经解决。 |
之前部分业务遍历全网数据库获取所需数据,须要维护多个源,并且是异构源,很是复杂和繁琐。使用 TiDB 很好地解决了这个问题,只须要访问一个源就能够获取到全部想要的数据。
<center>图 13 全网数据库遍历</center>
<center>图 14 数据从 MySQL 迁移到 TiDB</center>
MySQL 数据库迁移到 TiDB 分为两个部分:全量和增量。
全量
增量
<center>图 15 数据迁出 TiDB</center>
若是数据须要反向导入或同步,能够利用 TiDB Binlog 工具将 TiDB 集群的 binlog 同步到 MySQL。TiDB Binlog 支持如下功能场景:
导入的方式:
<center>图 16 去分库分表举例</center>
举例:一个超级大表按天分表,如今打算查询某个帐号一年间的信息。
上游 MySQL
SELECT xx FROM HFeeall join HFee20190101 join ... join ...join ... join HFee20190917 WHERE xx;
须要链接 N 个 join 条件,查询须要等待较长时间。
下游 TiDB
SELECT xx FROM SuperHfeeall WHERE xx ;
应用此方案,最大单表 700+GB,13+ 亿行,索引查询秒返回。
目标:利用 TiDB 的水平扩展特性,解决容量瓶颈和系统吞吐量瓶颈。
迁移原则:
1)数据同步
使用 DM 或者 Syncer 将上游 MySQL 的数据同步到 TiDB 集群。同步流搭建后注意须要检查上下游数据一致性。
观察一段时间,同步无误后,能够根据业务须要迁移部分读流量到 TiDB 集群。
<center>图 17 业务迁移之数据同步</center>
2)读写验证
这一阶段是验证应用访问 MySQL 和访问 TiDB 能够获得相同的结果,验证业务访问的准确性问题。
中止数据同步,使用流量复制工具将线上流量彻底拷贝出来,同时读写 MySQL 和 TiDB。将两边的访问结果进行对比,核查 TiDB 是否可靠和可信。根据须要,这个阶段能够测试较长时间。
<center>图 18 业务迁移之读写验证</center>
3)灰度切换
将步骤 2 的双写中止,即关双写,同时拉起上游的 DM 同步。
把访问部分非核心业务的库表写操做迁移到 TiDB,打开 TiDB 的 Binlog 开关对线上 MySQL 进行反向同步。这个操做,保证只写 MySQL 的数据同步到 TiDB ,只写 TiDB 的数据也能够反向同步到 MySQL,保证出了问题,随时能够回滚。当业务长时间访问正常,能够增长切换流量,进行灰度切换。建议观察一段时间,至少一个月。
<center>图 19 业务迁移之灰度切换</center>
4)迁移完成
当流量彻底迁移完成,保持 TiDB 反同步到 MySQL 过程,继续观察一段时间,确认无误后,断开反向同步,100% 迁移完成。
<center>图 20 完成迁移</center>
TiDB 兼容 MySQL 协议,支持 TP/AP 事务且扩展性好,能很好地解决网易互娱计费组业务大容量、高可用等问题。目前咱们的业务在不断深刻和扩大规模使用 TiDB,由于看好它,因此这里提出一些使用中的问题以帮助原厂持续打磨产品:
最后,根据网易互娱计费组已有的使用状况,咱们计划继续加大、加深 TiDB 的使用场景,丰富业务类型和使用规模,期待 TiDB 给咱们的业务带来更多便利。
原文阅读:https://pingcap.com/cases-cn/user-case-wangyihuyu/
更多案例阅读:https://pingcap.com/cases-cn/