突破数据存储瓶颈!转转业财系统亿级数据存储优化实践

1.背景

1.1 现状

目前转转业财系统接收了上游各个业务系统(例如:订单、oms、支付、售后等系统)的数据,并将其转换为财务数据,最终输出财务相关报表和指标数据,帮助公司有效地进行财务管理和决策。

转转业财系统于2021年开始构建,前期为了满足需求短时间内上线,选择了主动接收上游业务系统的数据。然而随着时间的推移,数据量在不断增长,系统已经达到无法承载的边缘,引发了许多问题。因此,我们需要对数据存储进行优化。

1.2 数据量统计

业财系统数据量较大表统计:

表名 行数 数据长度 索引长度
出库明细表 106280176 29.48GB 34GB
出库单头表 25344110 7GB 6GB
入库明细表 22766910 8GB 5GB
销售订单表 29578659 10GB 9GB
应收单表 24686267 5GB 2GB
入库单表 20777457 4GB 6GB
应付单表 15387724 4GB 2GB

以下是数据量较大的表数据增量趋势图,可以观察到近几个月由于新业务的增加,每月的数据增量已经达到一千万。

1.3 慢查询情况

从慢查询监控平台可以看到,每天慢查询个数已经到达千量级别。慢查询不仅影响用户体验,还会大量消耗所在机器资源,严重可能导致机器宕机。另外,转转MySQL数据库架构属于单机多实例,一台物理机上部署多套集群的实例,所以不仅会影响系统本身集群,还会拖累其他集群,引发雪球效应。

2.设计目标

2.1 解决数据量问题

在未来五年,不用考虑数据库数据量问题,能够轻松应对未来的业务增长和覆盖公司全量业务,且具备良好的扩展性,最终可以稳定向外输出更多数据报表等。

2.2 解决读写性能

通过此次优化,提升报表查询效率,减少定时任务执行时间,避免因为慢查询导致任务失败和接口超时问题,提高服务稳定性。

3.方案选择

3.1 db存储方案选型

为解决底层表数据量问题,我们对比了以下四个方案:

  • 方案一:分库分表
  • 优点
  1. 将数据分散到多个数据库和表中,从而减轻单一数据库的负载压力。这样可以提高数据库的读写性能和响应速度,降低查询延迟。
  2. 拆分的表结构相同,程序改造较少。
  • 缺点
  1. 需要提前规划好分片规则,一旦定好规则就难以移动,扩展性比较差。
  2. 拆分规则很难抽象出来。
  3. 跨库事务问题。
  • 适用场景
  1. 数据库面临高并发访问的压力,又需要面对海量数据的存储问题,这时需要对数据库既采用分表策略,又采用分库策略,以便同时扩展系统的并发处理能力,以及提升单表的查询性能。
  2. 数据有统一的业务规则主键,使数据可以均匀分布。
  • 业财系统适用分析
  1. 业财系统作为底层系统,接受了各个业务系统的数据,数据比较多样性和复杂性,很难定义出一个业务主键,数据分布均匀困难。
  2. 若某业务数据量迅速增长或接入其他业务数据,那么可能又会面对数据量问题。
  • 方案二:冷热库
  • 优点
  1. 将不常访问的数据从在线存储中移动到归档存储中,减少了在线存储的容量需求,从而降低了存储成本。
  2. 减少了在线存储中数据的数量,因此可以提高数据库读写性能。
  3. 可以将历史数据长期保存,避免了数据的丢失。
  4. 可以将数据备份到不同的存储位置,以便在需要时进行数据恢复。
  • 缺点
  1. 需要保证归档事务性,防止归档数据同时出现在冷热库,出现数据重复。
  2. 需要考虑合适的归档策略,不影响服务访问。
  3. 需要有明确的业务边界,业务复杂的数据不适用。
  • 适用场景
  1. 数据库中存在大量的历史数据,且查询频率比较低。
  2. 数据库的写入操作比读取操作更频繁。
  3. 数据库的存储成本较高,需要降低成本。
  • 业财系统适用分析
  1. 业财系统业务数据复杂,现阶段还会更改和查询历史数据,时间口径不统一,边界比较模糊,无法确认一个准确的边界。
  2. 考虑后续接入更多的业务数据,由于目前无法统一数据格式,那么可能就需要重新考虑边界等问题。
  • 方案三:TiDB
  • 优点
  1. 高度兼容 MySQL:大多数情况下,无需修改代码即可从MySQL轻松迁移至TiDB。
  2. 水平弹性扩展:通过简单地增加新节点即可实现 TiDB 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景。
  • 缺点
  1. 仍有一些MySQL的特性和行为,TiDB目前暂时不支持或表现与MySQL有差异。
  2. 系统复杂,组件太多。
  • 适用场景
  1. 对数据一致性及高可靠、系统高可用、可扩展性、容灾要求较高的金融行业属性的场景。
  2. 对存储容量、可扩展性、并发要求较高的大量数据及高并发的OLTP场景。
  3. 数据汇聚、二次加工处理的场景。
  • 业财系统适用分析
  1. 由于TiDB兼容了MySQL,所以改动点也较少。
  2. 近几年是不用考虑数据量问题,可以接入更多样化数据。
  3. TiDB能够支持大表经常有加列减列的需求,可扩展性高,目前也比较符合业财现状。
  • 方案四:OceanBase
  • 优点
  1. 高性能:采用了读写分离的架构,把数据分为基线数据和增量数据。其中增量数据放在内存里(MemTable),基线数据放在SSD盘(SSTable)。对数据的修改都是增量数据,只写内存。所以DML是完全的内存操作,性能非常高。
  2. 高兼容:兼容常用MySQL/ORACLE功能及MySQL/ORACLE前后台协议,业务零修改或少量修改即可从MySQL/ORACLE迁移至OceanBase。
  3. 高可用:数据采用多副本存储,少数副本故障不影响数据可用性。
  • 缺点
  1. 对环境要求极高,需要采购使用其指定的服务器。
  2. 学习和运维成本比较高。
  3. 尽管OceanBase具有高可用性的特性,但其实现仍然依赖于底层硬件和网络的稳定性。
  • 适用场景
  1. 金融级数据可靠性需求。金融环境下通常对数据可靠性有更高的要求,OceanBase 每一次事务提交,对应日志总是会在多个数据中心实时同步,并持久化。
  2. 数据库面对飞速增长的业务数据量。
  • 业财系统适用分析
  1. 目前运维没有维护,所以就不考虑此方案,大家可以参考此方案是否适用于本身系统。

综合以上各个方案的分析,目前最适用于转转业财系统的方案是TiDB。该方案能够在短时间内解决数据量问题,并且改动成本相对较低。

3.2 慢查询优化方案

在分析了慢查询语句以后,发现大部分慢查询都是由于联表查询导致的,所以此次主要解决联表问题。 联表解决方案对比如下,根据适用分析选择ES方案。

方案 业财适用分析
宽表 1.宽表可能包含大量重复数据,导致存储空间的浪费。这会增加数据库的存储需求,尤其在大规模数据集上会更为显著 2.由于涉及到大量列和关联数据,后续性能优化可能需要考虑更多的因素,而且可能需要采用复杂的索引策略 3.复杂度增加,改动量比较大
ES 1.通过建立索引方式解决联表问题,也一并提高了查询效率 2.后续可扩展性比较高,增加查询条件等,都易实现 3.需要保持数据源与ES数据一致问题 4.可以减低现有的数据库索引数据量

4.方案实践

4.1 方案实践步骤

根据方案选择分析,最适合业财系统当前状况的方案是首先切换底层数据存储,然后再接入ES。在实施这两个方案之前,我们需要考虑它们的先后顺序,并分析业财系统的现状。 由于数据量的突增,考虑到现有业务和后续新增业务,同时在不影响现有使用的前提下,首要需要解决的问题是数据量。因此,我们建议首先切换底层数据存储。这样做的好处是,即使在后续的实施中遇到问题,我们仍然可以回滚到原有的数据存储。这样既可以保证数据的完整性,也减少了实施过程中的风险。另一方面,如果我们选择先接入ES,就需要考虑如何保证数据切换过程中的数据完整性,并且同步方式也需要考虑两种不同数据存储方案之间的兼容性,这将增加许多额外的工作量和风险。

综上所述,我们选择的优化步骤是首先切换底层数据存储,待其稳定后再接入ES。这样能够有效解决当前的数据量问题,同时保证系统的稳定性和数据完整性。随后,我们可以继续进行ES的接入,以进一步优化业财系统的性能。

4.2 切换底层数据存储步骤

在选择数据迁移方式时,考虑到业财系统对实时性要求并不是很高,且评估了下目前大部分数据接入写入方式,是可以接受停写几分钟,这样便大大降低了整个数据迁移成本。

迁移过程要求:

  1. 检查TiDB是否都能兼容目前服务中的SQL语句,保证迁移之后系统不会报错。
  2. 数据需要保证完整性,迁移之后需要保证MySQL库和TiDB库的数据是严格一致。
  3. 迁移过程中需要做到可以回滚,一旦迁移过程中出现问题,可以立即回滚到MySQL库,不会对系统可用性造成影响。

4.3 接入ES

  1. 根据报表查询页面的功能和联表SQL分析,我们进行了索引模型设计,核心是优化查询性能和提高系统的响应速度。
  2. 在建立索引模型之后,我们需要考虑数据库(DB)与Elasticsearch(ES)之间增量数据的同步方式。

以下表格是对比了四种不同的同步方式,我们根据已设计的索引分析,考虑到每个索引涉及的表较多、相关业务代码尚未收口以及对实时性较高的需求,我们决定采用数据订阅的方式进行同步。在当前公司提供的实现方式中,我们选择了Kafka。

同步方式 优点 缺点
同步双写 这种方式简单粗暴,实时性高 1.业务耦合:这种方式代码侵入性强,耦合大量数据同步代码,要在写DB的地方写ES的代码 2. 影响性能:写入两个存储,响应时间变长,系统的性能必然会下降 3.不便扩展:搜索可能有一些个性化需求,需要对数据进行聚合,这种方式不便实现 4.高风险:存在双写失败丢数据风险
异步双写 1.性能高 2.不易出现数据丢失问题 3.多源写入之间相互隔离,便于扩展更多的数据源写入 1.硬编码问题,接入新的数据源需要实现新的消费者代码 2.系统复杂度增加,引入了消息中间件 3.MQ是异步消费模型,用户写入的数据不一定可以马上看到,造成延时
定期同步 实现比较简单 1.实时性难以保证 2.对存储压力较大
数据订阅 1.业务入侵较少 2.实时性比较高 需要选型数据订阅框架,系统复杂度增加
  1. 在增量数据同步以后,最后一步就是需要完成历史数据的同步,此次我们选择的同步方式是公司内部提供的ECP,可以参考文章: 不可思议!亿级数据竟然如此轻松同步至ES!

5.总结与成果

目前,业财系统已成功完成底层数据存储的切换,可以看到近几年来不再担心数据量存储的问题,并且成功接入了更多的业务数据。随着引入了Elasticsearch(ES),业务人员也不再反馈报表页面超时等问题。这次针对数据存储的优化实质上是对系统的重构,选择方案时考虑了对系统影响范围较小且不影响业务人员使用的因素,这也是优化的核心所在。

由于历史原因,业财系统仍存在许多需要优化的方面,如慢SQL的持续治理、定时任务优化等。因此,我们需要保持此优化的核心理念,并在后续的重构中继续完善,以使业财系统更加稳定。


关于作者

戴美琪,转转交易中台研发工程师

> 转转研发中心及业界小伙伴们的技术学习交流平台,定期分享一线的实战经验及业界前沿的技术话题。

> 关注公众号「转转技术」(综合性)、「大转转FE」(专注于FE)、「转转QA」(专注于QA),更多干货实践,欢迎交流分享~

相关推荐
小灰灰__14 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭18 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果38 分钟前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林44 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨1 小时前
El表达式和JSTL
java·el
许野平1 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
duration~2 小时前
Maven随笔
java·maven
zmgst2 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD2 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构