导读
本文整理自新东方数据库和大数据运维负责人傅少峰对于新东方从 2017 年起使用 TiDB 的历程与经验。
文章详细阐述了新东方在快速增长的业务需求下,如何通过选择和升级 TiDB 来应对大表查询、高并发处理和复杂数据架构的挑战。
从最初的 TiDB v1.0 版本到最新的 v6.5 和 v7.5 版本,新东方通过不断的技术迭代和优化,实现了数据架构的现代化升级,提升了系统的性能与稳定性。文章还分享了 TiDB 在 OLTP、HTAP 和未来的多模态应用场景中的实践,展现了 TiDB 如何支撑企业的数字化转型与创新需求。
本文包含以下内容:
- 新东方选择 TiDB 的背景和原因
- 新东方 TiDB 应用场景及版本分布
- TiDB 升级策略和相关考虑分享
- TiDB 后续升级计划
- TiDB 新版本新特性分享
大家好,我是新东方数据库和大数据运维负责人傅少峰。我们属于较早使用 TiDB 的一批互联网用户,从 TiDB 的 v1.0 版本直至 v6.5 版本,历经了 6 个大版本的升级。接下来,我以新东方的业务场景为例,给大家分享一下我们对于选择和升级 TiDB 的综合考量。
新东方选择 TiDB 的背景和原因
探索与尝试
2017 年,我们着手对分布式数据库架构展开探索,主要目的在于解决数据存储与查询方面的性能问题,特别是针对大表的查询。这些需求主要源自于我们OA工作流数据以及业务归档数据,我们迫切需要一个强大的查询分析引擎,以满足对归档数据进行查询和分析的业务需求。此外,我们当时还尝试处理一些分析和探索性的数据,主要是报表类的数据。在 2017 年,社区开源的分布式数据库选择极其有限。我们对一些老牌的分布式数据库进行了验证,比如Postgres-XC/XL 和 MySQL 的 NDB。经过全面的验证,这些产品都没有达到我们的预期,所以我们开始寻找其他解决方案。
2017 年,国产数据库 TiDB 开源,我们把握住了这个契机,对该产品进行了尝试,并将其与国外的数据库(如 CockroachDB)展开了大量的对比。最终,我们决定选用国产的开源分布式数据库 TiDB 作为我们的数据基础架构。正因如此,我们在 2017 年积累了有关分布式数据库的经验和知识。
挑战与迭代
到了 2018 年,随着业务的快速增长,我们核心 ERP 报名 2.0 系统已难以承载高并发的状况。因此,我们研发团队启动了报名系统的重构工作。原有系统基于 SQL Server,采用分校策略,每个学校都需要独立部署一套系统,这导致整体维护成本高昂,且不易进行升级维护。尽管报名 2.0 系统功能完备,但由于功能过于繁杂,性能并不理想,无法满足业务需求和支撑高并发请求。
在我们完成重构后,实现数据的集中化管理和业务的水平扩展,系统能够承载每分钟约 500 万的请求量。分校分系统的集中式数据库架构,转变为集中数据管理的分布式数据库架构。
系统重构过程中我们面临的挑战是如何有效处理大表数据问题。在数据库领域,处理大表数据是一个非常痛苦的事情。为什么我们在 2017 年没有选择常用的分库分表和中间件机制,而是选择了分布式数据库。主要原因是常用的拆表、拆库、拆实例的数据拆分策略会增加开发成本和后续维护成本;而采用分布式中间件,无论是对开发还是运维,成本都相对较高。基于 2017 年我们在分布式方面的技术沉淀、经验积累以及深度探索,最终我们选择了分布式数据库,因为综合成本相对较低。
当时,我们考虑过 MySQL、PostgreSQL,以及后来的 TiDB。因此,无论是代码还是底层数据架构,都需要进行大规模的重构,这意味着我们不会涉及到平滑迁移的问题。我们在开发时完全基于 TiDB v2.0 版本的特性进行开发,过程中遇到了许多挑战,包括分布式事务最初不支持悲观锁,只有乐观锁。为了解决这个问题,我们做了大量的实现工作,包括自己实现分布式锁。因为在高并发情况下,尤其是事务之间冲突时,乐观锁的性能开销是非常大的。因此,我们自己实现了内存级的分布式锁来解决事务冲突问题。但随着 TiDB 版本的迭代,特别是在 v5.0 版本以后,它既支持悲观事务,也支持乐观事务,所以我们基本上不再需要自研分布式事务架构。
新东方 TiDB 应用场景及版本分布
TiDB 在新东方的应用覆盖了多个关键 OLTP 业务场景。我们的核心 ERP 系统、支付系统、清结算系统以及学习机系统等均部署在 TiDB 架构上。
针对 HTAP(事务/分析处理) 融合场景,例如商机系统等,对轻量级分析处理平均响应时间有明确需求,因此选择了 TiDB 这样的 Real-time HTAP 架构来满足业务查询需求。随着业务数据量的迅速增长,TiDB v5.0 在这个场景下也力不从心了,我们计划升级到 v7.5 版本来提升集群整体计算性能。
我们也利用 TiDB 来满足部分轻量级的分析型 OLAP 需求,如企业、人财物等报表数据的存储和查询。至于纯 OLAP 场景我们采用的是 Doris、StarRocks MPP 架构方案,满足 AP 场景下的即席查询、实时分析、数据探索等需求。
最近,我们也开始尝试 TiDB v7 版本,TiDB v7 版本在性能和租户管理方面都有显著的提升。我们目前也针对 TiDB v7.5 进行功能和性能方面的验证。
TiDB 升级策略和相关考虑分享
我将简要介绍选择 TiDB 的原因以及在升级过程中采取的策略和积累的经验。
最初,我们使用的是 TiDB 的 V1 版本,随后也采用了 V2 和 V3 版本。自 2017 年起,TiDB 每年都会推出一个新的大版本,直至 2024 年发布的 V8 GA 版本。在早期,由于版本中存在一些 bug 和限制,我们几乎每年都会进行一次大版本升级,尽量减少使用过程中踩到坑。
随着 TiDB 5.0 版本的推出,我们发现相较于之前的版本,bug 和限制问题大大减少,因此近期的版本变得更加稳定,我们数据库版本升级的频率也相应减缓,主要是为了确保系统的稳定性。
到了 2024 年,也就是今年年初,我们开始进行大规模的版本升级。这次升级主要基于稳定性、安全性和成本三方面的考虑。TiDB 的 v4、v5 及 v5.1 等版本已于 2024 年 4 月停止官方的更新和维护。为了确保安全和稳定,我们逐步将 TiDB 集群升级到 v6.5 长期支持版本(LTS)。在选择这个版本时,我们也对比了其他版本,最终评估确定 v6 版本已经能够满足我们的业务需求,因此我们选择了一个相对保守的版本,即 v6.5。
LTS 版本是经过了广泛的测试和验证,确保了其稳定性和可靠性,并且会定期接收安全更新和补丁。对于企业用户而言,选择 LTS 版本可以减少因频繁升级而产生的维护成本。尽管支持平滑滚动升级,我们仍然致力于减少升级带来的维护成本。这就是我们当时的升级计划和策略。
接下来,我们简单分享一下升级过程中的一些考虑。
精选稳定的版本
使用过 TiDB 的人都知道,从 2017 年到现在,TiDB 几乎每年都会发布一个大版本。在 V5 版本中,包括社区用户和我司在使用时都感到非常困惑,因为 V5 版本之后出现了各种 plus 版本,使得在版本选择上成为一个难题,我们不知道哪个版本最适合我们。
随着 V6、V7、V8 版本的推出,这个问题基本上得到了解决。在后续的版本中,版本管控已经做了严格的控制,基本上每个大版本会发布两个小版本。因此,我们建议如果刚开始使用 TiDB,可以选择 V6.5 版本进行项目适配。包括后续的新版本,如 V7.5 和 V8 的 LTS 版本,这些社区长期维护的 LTS 版本对我们来说,整体稳定性有很大的保障。
非核心业务先行
我们在项目升级时,会选择非核心业务先行。在测试环境(T 环境、Q 环境)以及灰度环境中进行全面的升级验证,全面评估 SQL 兼容性和性能,确保升级后不会出现任何隐患。
升级方式的选择
在升级 TiDB 时,我们面临两种官方提供的升级方式:迁移升级和在线升级(也称为滚动升级)。迁移升级可能涉及停机,对服务影响较大,操作也更为复杂。选择此方式时,我们通常需要部署新集群,并将旧集群的系统和数据库参数迁移到新集群,确保参数一致性,以避免因参数设置不当引发系统不稳定。
迁移升级的优势在于,一旦升级过程中出现问题,我们可以迅速回退到历史版本,对业务的影响较小,风险可控。相比之下,滚动升级无需停机,对业务的影响更小,可以逐个组件进行升级,将业务影响降至最低。操作相对简单,只要升级前做好充分验证和有效的回退方案,执行一个 update 命令即可将整个集群从低版本升级到高版本。但这种情况下,业务需要支持重试机制。
TiDB V8 版本中提出了 TiDB 的 TiProxy。使用 TiProxy 可以使业务升级更加平滑,将业务感知度降到最低,从而减少对重试机制的依赖,可能只需要利用进程自带的重试能力即可。
虽然滚动升级的风险相对于迁移升级可能更高,但我们通过全流程验证和完善的灾备环境来将风险降至最低。这样,在升级过程中或迁移失败时,我们可以快速切换到备用环境,确保业务连续性。
准备好回退方案
最后关键点是准备好我们的回退方案。即使我们升级了数百套系统,一个良好的回退方案也是我们保命的机制。因此,我们必须制定一个周密的回退方案,这是至关重要的。回退的目的就是将业务恢复到原始状态,保证业务连续性,尽量减少对业务的影响。这是我们在升级过程中积累的一些经验。
TiDB 后续升级计划
我将概述一下 TiDB 在新东方的未来版本规划和升级计划。
如前所述,V3、V4、V5 等常规版本已于 4 月份停止更新,这促使我们继续进行版本升级。即使当前系统稳定,若社区停止更新,一旦出现安全问题,可能会引发数据安全风险。因此,我们建议升级到社区中较为稳定的 LTS(长期支持)版本。目前,社区提供了 V6 版本,包括 V6.1 和 V6.5,我们选择了 V6.5 版本。同时,V7 和 V8 版本也可供选择使用。
我们本次大版本升级计划开始于 24 年年初,截至目前,已将 20 多套 TiDB 集群从 v4 和 v5 版本升级至 v6.5,完成了整体升级任务的 50%。目标是在 25 年年底,即财年结束前,完成所有 TiDB 集群的升级工作。在升级方案中,98%的集群采用了在线升级或滚动升级方案,仅 2%采用了迁移升级方案。
对于支付中心等关键业务系统,数据规模不大但要确保数据安全和一致性。因此,此类业务系统,我们计划采用迁移升级来降低升级过程中的数据风险。迁移升级需要业务方的配合,特别是在需要停机窗口的情况下。
如果业务对升级时间非常敏感,或者要求服务必须始终保持在线,迁移升级仍然是一个相对影响较大的选择。因此,我们建议在做好充分的升级前验证后,采用本地滚动升级方案,这是最优雅的解决方案。
新东方目前主要在 OLTP 场景中使用 TiDB,其中绝大多数核心业务都运行在 TiDB 上。这些业务包括我们的报名系统、订单系统、商品系统、支付系统和学习机系统等。
在 HTAP 场景的应用实践中,我们也对几个系统进行了尝试。如商机系统,其中大约 70%的业务属于事务型处理(TP),而剩余的 30%则涉及分析型处理(AP),包括执行一些复杂的 SQL 查询。为了支持这些轻量级的 AP 业务场景并提升性能,我们选择了 TiDB v7.5 版本。这一版本能够满足商机系统中对于性能要求较高的 AP 部分,确保系统的高效运行。
TiDB 新版本新特性分享
TiDB v6.5
首先,让我们简单介绍一下 TiDB v6 版本中的几个关键特性,这些特性显著提升了与 MySQL 的兼容性。尤其是 v6 版本中的 auto increment(自增)属性,这是一个重要的进步。在以往的 TiDB 分布式数据库中,自增 ID 无法保证严格的递增顺序,但在 v6 版本中,自增 ID 现在可以保证单调递增,从而保持了顺序性。对于依赖自增 ID 进行排序的业务而言,这一特性至关重要。
如果你的数据库是 MySQL,并且业务依赖于主键 ID 进行排序,那么升级到 TiDB v6.5 版本时,这个特性可以确保业务的预期不会受到影响。在 v6.5 版本中,自增 ID 已经能够保证递增,因此可以更好地兼容现有业务,并与业务需求更紧密地适配。
其次,我们经常使用的一个特性是类型转换。在早期版本中,虽然可以调整精度,但对于类型转换,比如从 VARCHAR 到 BIGINT,是不支持的。在 TiDB 的新版本,尤其是 v6 版本中,我们现在开始支持这样的类型转换,这大大方便了我们对表结构的修改。
此外,v6.5 版本中引入了 V2 版本的优化器,其性能相较于 V1 版本有了显著提升。我们在业务场景中进行了尝试,发现整体性能确实有很大的提升。例如,在 INDEX MERGE 方面,以前只支持 OR 条件下的索引合并,而在 AND 条件下可能无法使用 INDEX MERGE。现在 v6 版本在这方面做了优化,优化器也在这方面做了增强。
TiDB v7.5
目前,我们在生产环境中尚未正式使用 TiDB V7.5 版本,但正在尝试将商机系统数据同步至 V7.5 版本集群。在此过程中,我们主要关注性能和兼容性两个方面。正如帅萌老师之前提到的,他们计划未来升级至 7.5 版本,并已进行了业务性能测试,相关技术分享已在 asktug 上发布。我们可以参考这些资料,或进一步阅读他的文章。
在生产环境中,我们对商机系统分析类的场景进行了验证,使用了复杂的 SQL 语句,涉及多表 JOIN 操作。在处理复杂 SQL 时,涉及的核心表的数据量大约为 800 万条左右,会存在多个这样规模的表。在 TiDB 5.0 版本中,这类查询的执行时长约为 56s。而当我们对 TiDB 7.5 版本进行性能测试时,同样的查询仅需 3.7s,尽管 SQL 可能还有优化空间,但版本升级带来的性能提升非常明显,整体提升了约 15 倍。
接下来,使用商机系统的 SQL 进行了对比测试,特别是在优化器的算子上,对比了 v5.0 和 v7.5 版本的性能表现。使用的 SQL 语句采用了 NOT IN 的方式,而非 NOT EXISTS。但在 NOT IN 的情况下,两个版本在执行计划中采用的算子有所不同。在 v5.0 版本中,使用的是 cartesian 半连接的算子,导致执行效率非常低,大约需要 2min 左右才能完成查询。而升级到 v7.5 版本后,优化器采用了 null-aware 半连接的算子,整体效率显著提高,同样的 SQL 大约在 2.7s 就能完成。这表明 TiDB 7.5 版本在优化器和算子方面进行了大量优化。
关于租户隔离方面,我们还没有在生产环境中进行大规模使用。目前,我们计划未来在租户隔离方面,将商机系统中的 TP 和 AP 请求通过租户进行分离,实现不同用户查询的租户级别隔离。
另一个场景是,我们有些业务可能需要从主集群和备集群中进行数据查询,这些查询通常是一些数据低延时的需求,比如业务历史的定时任务、故障排查等非核心业务查询。为了减少对主库的影响,我们通常会将这些查询放在备集群中。但这样做的问题是,备集群会有一定的延时。在 TiDB 7.5 版本之后,我们可以通过租户的方式来解决这个问题,将这些查询放在主库上,并利用 Resource Group 进行控制,以减少这些查询对主集群的影响。
因此,我们计划在未来尝试租户这种做法。但我们也不会将所有核心业务都放在一套 TiDB 集群中。我们仍然建议,对于非常核心的业务系统,最好还是独立部署,以确保业务系统整体的稳定性。对于某些非关键业务,考虑到降本增效的目的,我们可以尝试将这些业务放在一套 TiDB 集群多个租户中。
TiDB v8.x
我们目前重点关注的是 TiDB 的 V8.5 版本。V8.5 版本预计将成为一个重要的里程碑,因为我们之前与官方社区的交流中得知,该版本可能会引入多模态功能。在云栖大会上,我注意到许多数据库系统,无论是面向分析型(AP)还是事务型(TP)系统,都在强调多模态和融合能力。TiDB 在这方面也进行了相应的功能增强,可能在 V8.5 版本中发布。
TiDB 原本是一个纯分布式架构的 HTAP 场景解决方案,但现在它增加了多模态和融合查询的能力,支持 Vector store、Document store 以及 Graph store 等。这大大提升了 TiDB 的整体融合能力,减少了我们根据不同场景设置不同数据库的需求。
如果我们需要使用向量数据库,单独搭建一个向量数据库集群,这无疑会大大增加我们的运维成本。同样,如果我们需要图数据库的需求,可能也需要搭建一个图数据库集群。这些需求并不纯粹是图数据库的需求,可能还涉及到 AI 领域的一些应用,比如在推荐系统(RAG)架构中,除了向量数据外,还可能包含图关系数据,以提升召回率和准确度。
因此,我们希望有一个支持多模态的数据库来解决这些多样化的需求。我们也正在探索这方面的解决方案,比如在知识库方面的设计,未来可能会涉及到存储向量数据等。
值得庆幸的是,TiDB 在 V8.5 版本中提供了内置的向量类型和向量索引,以及通过搜索方式检索向量数据的能力。这意味着我们可以使用一套引擎来处理多种数据类型,这对于降低业务开发成本是非常有利的。
未来 TiDB 还有可能支持图数据库类型,这样我们在进行顶层数据库设计时就变得非常简单。因为无论有什么类型的查询请求,都可以通过 DB 来满足我们的业务需求。此外,在 TiDB 的高版本中,TiDB 的 CDC(Change Data Capture)能力也得到了极大的增强,包括支持生成 Debezium 格式的数据变更事件,以及 Canal 格式的日志。这些功能可以很好地提升我们的开源生态,并且快速集成我们的实时计算平台,为下游数据的实时打通提供了高效的支持。
目录