亿级大表拆分过程记录

news2024/11/27 1:28:19

两年前接手公司的财务系统的开发和维护工作。在系统移交的初期,笔者和团队就发现,系统内有一张5000W+的大表。

跟踪代码发现,该表是用于存储资金流水的表格,关联着众多功能点,同时也有众多的下游系统在使用这张表的数据。

进一步的观察发现,这张表还在以每月600W+的数据持续增长,也就是说,不超过半年,这张表会增长到1个亿!

这个数据量,对于mysql数据库来说是绝对无法继续维护的了,因此在接手系统两个月后,我们便开起了大表拆分的专项工作。(两个月时间实际上主要用来熟悉系统、消化堆积需求了) 

1、拆表前系统状态

 

 

  • 涉及到流水表流水的接口超时频发,部分接口基本不可用

  • 每日新增流水缓慢,主要是插入数据库的时候非常慢

  • 单表占用空间过大,DBA的数据库监控经常报警

  • 无法对表进行变更,任何alter操作都会引起主从的高延迟和长时间锁表

2、拆表的目标 

  • 将流水大表数据拆分至各个分表,保证每张分表数据在1000W左右(经验上看单表1000W的量对mysql来说没啥压力)

  • 在拆表的前提下,针对不同接口的查询条件进行优化,保证各个对外、对内接口的可用性。彻底杀死mysql慢查询。

3、难点分析 

  • 该表的数据可以说是整个财务系统最基础的数据,相关功能和下游系统非常多。这要求开发、测试和上线流程必须极其严密,任何小失误都会引起大问题。

  • 涉及的场景非常多。统计下来,一共有26个场景,需要改造32个mapper方法,具体需要改造的方法就更加无计其数了。

  • 数据量非常大,迁移数据的过程必须保证系统稳定。

  • 用户较多且功能重要。分表功能上线时,必须尽量压缩系统无法使用时长,同时需要保证系统可用性。这要求团队必须设计完整可靠的上线流程、数据迁移方案、回滚方案、降级策略。

  • 上文提到,表的拆分势必带来部分接口的变化,接口的变化又会带来其他系统的改造。如何推动其他系统进行改造,如何协调多方合作的开发、测试和上线是另一个难点。

4、整体过程 

 

4.1、分表中间件调研

分表插件:采用sharding-jdbc作为分表插件。

其优势如下:

1、支持多种分片策略,自动识别=或in判断具体在哪张分表里。

2、轻量级,作为maven依赖引入即可,对业务的侵入性极低。

为提升查询速度,在整个项目的初期,团队成员考虑引入ES存储流水以提升查询速度。

经过与ES维护团队的两轮讨论,发现公司提供的ES服务对于我们的业务场景并不匹配(见表),经过反复考量,最终我们放弃了引入ES的计划,直接从数据库查询数据,采用每张表设置一个查询线程的方式提升查询效率。

4.2、分表依据的选择

分表的方式有很多种,有纵向分表,有横向分表,有分为固定的几个表存储然后取模进行表拆分等等。总的来说,适合我们具体业务的分表方式只有横向分表。

因为对于资金流水这种特殊数据来说,是不能清理数据的,那么纵向分表和拆成固定的几个表都不能解决单表数据无限膨胀的问题。而横向分表,可以把每张表的数据量恒定,到一定时间后可以进行财务数据归档。

分表的依据一般都是根据表的某个或者某几个字段进行拆分,最终其实是对数据和业务分析综合出来的结果。总的来说,原则有这几个:

  • 尽可能选择查询条件里最常出现的字段,这样能够减少方法改造的工程

  • 需要考虑根据某个字段拆分数据是否能够均匀分布,是否能够满足单表1000W左右的要求

  • 该字段必须是必现字段,不允许出现空值

综合分析我们的数据以及业务需要,“交易时间”这个分表依据就呼之欲出了。

首先,这个字段作为流水最重要的字段之一一定会出现;

第二,如果按照交易月份进行拆表,每张表大概也就是600W-700W的数据;

最后,有70%的查询都附带“交易时间”作为查询条件。

5、技术难点

5.1、多数据源事务问题

sharding-jdbc在使用的时候是需要用自己的独立数据源的,那么就难免出现多数据源事务问题。

这个我们通过自定义注解,自定义切面开启事务,通过方法栈逐层回滚or提交的方式解决的。出于保密原则,具体代码细节不再展开。

5.2、多表的分页问题

拆表一定会引起分页查询的难度增加。由于各个表查出来的数据量不等,原始的sql语句limit不再适用,需要设计一个新方法便捷的获取分页信息。

在此介绍一个分页的思路供大家参考(团队共同的成果,笔者不敢私自占有):

综合考虑业务实际与开发的复杂程度,项目团队决定在出现跨表查询的情况下,每一张表采用一个线程进行查询,以提高查询效率。

这个方案的难点在于分页规则的转换。例如,页面传入的offset和pageSize分别为8和20。各分表中符合条件的数量分别为10,10,50。那么我们需要将总的分页条件转化为三个分表各自的分页条件,如图

通过上图可以看到,大分页条件(offset=8,pageSize=20),转换为(offset=8,pageSize=2),(offset=0.pageSize=10),(offset=0,pageSize=8)三个条件。

整个计算过程如下:

1)      多线程查询各个分表中满足条件的数据数量

2)      将各个表数量按照分表的先后顺序累加,形成图 8的数轴

3)      判断第一条数据和最后一条数据所在的表

4)      除第一条和最后一条数据所在表外,其他表offset=0,pageSize=总数量

5)      计算第一条数据的offset,pageSize

计算最后一条数据的pageSize,同时将该表查询条件的offset设置为0

5.3、数据迁移方案

在数据迁移前,团队讨论过两套迁移方案:

1)请DBA迁移数据;

2)手写代码迁移数据,他们各有自己的优缺点:

综合考虑时间成本和对线上数据库的影响,团队决定采用两种方案结合的方式:

  • 交易时间为三个月前的冷数据,由于更新几率不大,采用代码的方式迁移,人为控制每次迁移数量,少量多次,蚂蚁搬家;

  • 交易时间为三个月内的热数据,由于会在上线前频繁出现更新操作,则在上线前停止写操作,而后由DBA整体迁移。这样将时间成本平摊到平时,上线前只有约2个小时左右迁移数据时系统无法使用。

  • 同时,除了最后一次DBA迁移数据外,能够人为控制每次迁移的数据量,整体避免数据库实例级别的高延迟。

5.4、整体上线流程

为保证新表拆分功能的稳定性和大表下线的稳定,团队将整个项目分为三个阶段:

  • 第一阶段:建立分表,大表数据迁移分表,线上数据新表老表双写,所有查询走分表(验证观察)

  • 第二阶段:停止写老数据表,其他业务直连数据库改为资金提供对外接口(验证观察)

  • 第三阶段:大表下线

 

6、总结 

  • 应再进一步调研分表相关中间件。由于项目分表依据的特殊性,导致sharding-jdbc的很多功能无法利用,其对于简化查询逻辑的帮助低于预期。并且sharding-jdbc独立数据源的特性,引发了多数据源事务问题,反而增加了开发的工作量。

  • 多线程需要仔细分析线程池核心线程的大小,同时分析多线程池同时存在的时候是否会引起核心线程数过多,避免机器线程打满。

  • 如果是一个已有的项目,在进行分表改造时,一定要将各种场景都罗列清楚,将各个场景细化到程序中的每个类、每个方法中,将所有业务场景都覆盖到。

  • 在迁移历史数据时,一定要做好迁移数据方案,以及应对出现数据不一致时的处理方案。要综合考虑时间成本、数据准确性、对线上功能的影响等诸多因素。

  • 在上线一个比较复杂的方案时,一定要提前设计好回滚方案和降级措施,能够极大保证稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/573468.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Doris-----Aggregate 聚合模型及案例实现

Aggregate 模型 是相同key的数据进行自动聚合的表模型。表中的列按照是否设置了 AggregationType,分为 Key(维度列)和 Value(指标列),没有设置 AggregationType 的称为 Key,设置了 Aggregation…

外包实在是太坑了,干了三年,感觉人都废了

先说一下自己的情况,专科生,19年通过校招进入杭州某个外包软件公司,干了接近3年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了3年的功…

【JMeter中的View Result Tree显示中文乱码】

JMeter中的View Result Tree显示中文乱码 检查JMeter的安装目录下的bin文件夹中的jmeter.properties配置文件 用记事本打开并搜索:sampleresult.default.encoding 找到该行 改成sampleresult.default.encodingutf-8 修改后重启JMeter ok, 解决乱码 附加 : 下载 J…

【Linux高级 I/O(7)】初识文件锁——fcntl()方法及其独占性、共享性实验(附全文代码)

fcntl()函数在前面系列内容中已经多次用到了&#xff0c;它是一个多功能文件描述符管理工具箱&#xff0c;通过配合不同的 cmd 操作命令来实现不同的功能。为了方便述说&#xff0c;这里再重申一次&#xff1a; #include <unistd.h> #include <fcntl.h>int fcntl(…

大模型对世界的改变,从一时一地,到无处不在、无时不有

作者 | 曾响铃 文 | 响铃说 大模型正在中国遍地开花&#xff0c;做过的没做过的都要过来参合一下。 汹涌浪潮中&#xff0c;不免有更多人开始关注那个最先发布的文心一言。 全球科技大厂中第一个发布GPT大模型产品的百度&#xff0c;在刚刚的中关村论坛上透露了一些文心一言…

nodejs连接mysql

npm i express #node后端框架npm i corsnpm i mysqlconst app require(express)(); const cors require(cors); const port 5000; const mysql require(mysql) //引入mysql 模块app.use(cors({}))const conn mysql.createConnection({user: root,password: qwertyuiop…

普通人想自学软件测试?我还是劝你算了吧。。。

本人7年测试经验&#xff0c;在学测试之前对电脑的认知也就只限于上个网&#xff0c;玩个办公软件。这里不能跑题&#xff0c;我为啥说&#xff1a;自学软件测试&#xff0c;一般人我还是劝你算了吧&#xff1f;因为我就是那个一般人&#xff01; 软件测试基础真的很简单&…

gtest单元测试

gtest单元测试 1. gtest是什么&#xff1f;简答&#xff1a;做测试用的2. gtest的优点3. 搭建测试框架4. gtest_范例演示 1. gtest是什么&#xff1f;简答&#xff1a;做测试用的 gtest是Google的一套用于编写C测试的框架&#xff0c;可以运行在很多平台上&#xff08;包括Lin…

【JavaSE】Java基础语法(十四):Static

文章目录 概述特点与应用注意事项为什么一个静态方法中只能访问用static修饰的成员? 概述 Java中的static是一个修饰符&#xff08;也可称关键字&#xff09;&#xff0c;可以用于修饰变量、方法和代码块。 特点与应用 static修饰的成员具有以下特点&#xff1a; 被类的所有对…

如何在Mac上抓取安卓设备的日志

要在 Mac 上抓取 Android 设备的日志&#xff0c;您可以使用 Android SDK 中的 adb 工具。以下是一个简单的步骤&#xff1a; 1.您需要在 Mac 上安装 Android SDK。您可以从 Android 开发者网站上下载最新版本的 Android SDK&#xff0c;并按照说明进行安装。 2.将您的 Andro…

重学 Symbol

重学 Symbol 之前在写基础类型的笔记时暂时性的先跳过了 symbol&#xff0c;现在也有了一些项目的使用经验后&#xff0c;觉得还是需要重新回滚并且学习一下&#xff0c;温故而知新。 首先依旧回顾一下 symbol 的特点&#xff1a; 是原始值 唯一 不可变 可以提供私有属性&…

javaWeb ssh沙发销售系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh沙发销售系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Mye…

【SUMO】SUMO运行自带的OSM入门教程

文章目录 一、运行CMD命令行二、进入OSM选择地图位置 首先给出官网教程&#xff1a; https://sumo.dlr.de/docs/Tutorials/OSMWebWizard.html 一、运行CMD命令行 代码&#xff1a; 先进入osmWebWizard.py文件地址 cd /d D:\SUMO\sumo-1.17.0\tools&#xff08;替换成自己的…

智慧PG(pgting),一款拖拽式智能页面搭建系统

目录 前言 一、介绍 二、设计理念 1&#xff0c;资源整合&#xff0c;开箱即用 2&#xff0c;降低系统颗粒度 3&#xff0c;组件共享 4&#xff0c;简化配置 三、系统功能 1&#xff0c;可视化大屏搭建&#xff1a; 四、技术架构 1&#xff0c;技术栈 2&#xff0c;整体架构 五…

LeetCode 1091. Shortest Path in Binary Matrix【BFS,A星】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

C++ 代码整洁之道

NOTICE: 这篇文章的框架条目来自《C代码整洁之道&#xff1a;C17可持续软件开发模式实践》&#xff0c;作者: [德] 斯提芬罗特。书籍原名"Clean C: Sustainable Software Development Patterns and Best Practices with C 17"。 文章目录 编码基本原则保持简单和直接…

Unity | HDRP高清渲染管线学习笔记:示例场景解析

目录 一、HDRP入门 1.HDRP设置 1.1 HDRP配置文件中的全部设置项 1.1.1 Rendering下的Lit Shader Mode 1.1.2 Lighting 下的Volumetrics&#xff08;体积光&#xff09;和Screen Space Reflection&#xff08;屏幕空间反射&#xff09; 2.离线渲染VS实时渲染 3.Volume组件 …

文字gif闪图怎么做?高效的gif闪图制作方法

相信不少新媒体行业的小伙伴&#xff0c;一定都见过那种闪动文字效果的gif动图吧。效果非常的炫酷还很吸引人们的眼球&#xff0c;但是作为设计小白这种闪烁gif图要怎么制作呢&#xff1f;有没有那种小白也能轻松上手的工具呢&#xff1f; 一、什么样的工具能够在线生成gif动态…

《Spring Guides系列学习》guide35 - guide40

要想全面快速学习Spring的内容&#xff0c;最好的方法肯定是先去Spring官网去查阅文档&#xff0c;在Spring官网中找到了适合新手了解的官网Guides&#xff0c;一共68篇&#xff0c;打算全部过一遍&#xff0c;能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gu…

项目管理自动化 工作效率顶呱呱

项目管理&#xff0c;是职场人进阶发展的必备高阶能力&#xff0c;需要在复杂的环境中有效整合资源、高效助力团队实现整体的项目目标。 一个好的项目管理者&#xff0c;需要合理规划项目进展&#xff0c;实时同步需求、及时沟通进展&#xff0c;合理判断项目风险&预警&am…