数据分库分表和迁移方案

news/2025/1/22 22:47:26/文章来源:https://www.cnblogs.com/lmz-blogs/p/18686900

在我们业务快速发展的过程中,数据量必然也会迎来突飞猛涨。那么当我们的数据量百倍、千倍、万倍、亿倍增长后,原有的单表性能就不能满足我们日常的查询和写入了,此时数据架构就不得不进行拆分,比如单表拆分成10张表、100张表、单个月分多张表等等。下面我们针对具体案例分析下这种情况。

一、现状分析

直播签到业务中,有如下两张表,签到表和用户签到记录表。其中用户签到记录表t_sign_in_record现有数据量达到了18亿,数据占用空间为233G,索引占用空间为310G,总占用空间为543G。单表数据量太大,导致数据查询和写入性能过低。如果某条sql查询未使用到索引,很容易就会将数据库打挂。所以对t_sign_in_record的单表拆分很迫切

CREATE TABLE `t_sign_in` (`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',`sign_in_id` varchar(64) NOT NULL DEFAULT '' COMMENT '签到id',`shop_id` varchar(64) NOT NULL DEFAULT '' COMMENT '商家id',`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_shop_sign` (`shop_id`,`sign_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='签到表';CREATE TABLE `t_sign_in_record` (`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',`sign_in_id` varchar(64) NOT NULL DEFAULT '' COMMENT '签到id',`shop_id` varchar(64) NOT NULL DEFAULT '' COMMENT '商家id',`user_id` varchar(64) NOT NULL DEFAULT '' COMMENT '用户id',`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_shop_sign_user` (`shop_id`,`sign_id`,`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户签到记录表';

二、数据库设计

1、分表实例:依现有的存储空间做10倍的余量参考,所需空间大小为5.3T左右。而腾讯云MySQL最高支持存储空间上限是6TB,所以原有的腾讯云MySQL实例能满足需求。如果数据量更大,超过6TB的话,可以考虑将数据库迁移至TDSQL-C MySQL 版,最高支持至400TB。参考文档:https://cloud.tencent.com/document/product/1003/30488

2、分表数量:按照业务增长规模,每个月增量7千万-1亿,预计分10张表,平均单表数量在700万-1000万左右

3、分表算法:根据签到表t_sign_in的created_at中的年月日做如下算法,能让数据较均匀的落入每个月的10个分表中。分表的10张表名为t_sign_in_record_0、t_sign_in_record_1......t_sign_in_record_9

三、迁移方案

1、第一阶段:
双写数据,即将数据同时写入旧表t_sign_in_record和分表t_sign_in_record_0、t_sign_in_record_1、t_sign_in_record_2...中,此时需要去代码层创建和更新t_sign_in_record表的地方做处理,写入旧表的同时,写一份数据到新的分表。

2、第二阶段:
双写数据一致性校验,经过第一阶段的双写后,我们的新数据已经同时存在于新表和旧表中了,这个时候需要去check一下数据在旧表t_sign_in_record和分表t_sign_in_record_0...中是不是保持一致。有两个常用的检验方法:
(1)第一种是人工校验,即随机挑选一些签到,去check对应的签到记录条数和数据记录是否一致;
(2)另一种是写脚本去校验(全量数据或部分数据),将其中新老表中数据不匹配的记录输出到日志中,再去排查。

3、第三阶段:
写脚本,将旧表t_sign_in_record的存量数据都刷到分表t_sign_in_record_0...中。

4、第四阶段:
跟第二阶段的方式一样,去check第三阶段刷入的分表存量数据是否和旧表一致

5、第五阶段:
切读,将现网读 t_sign_in_record 表的地方都改为读新分表 t_sign_in_record_0、t_sign_in_record_1、t_sign_in_record_2...

6、第六阶段:
确认旧表 t_sign_in_record没有新的读请求。可通过DBA审计的方式。

7、第七阶段:
停止双写,即将代码改为只往新分表 t_sign_in_record_0、t_sign_in_record_1、t_sign_in_record_2... 里面写数据。

如上所述,迁移方案大概分为7个阶段,其中有三个阶段都是check数据一致性,在实际迁移时可以和其它步骤同时进行。拆分的整体时间周期一般为半个月到一个月之间,主要是其中为了确保数据一致性,需要灰度比较久

上面就是我们工作中常用的数据库表迁移方案了,有同学可能会甩锅给最初设计库表的同学,为啥当初设计的时候不考虑下分表呢?其实,这个是很难预估的,谁能知道最初一年只有几万数据的签到业务,现在每年会新增十来亿呢?这个主要取决于公司的发展了。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Power BI 连接GaussDB提取数据方法

Power BI本身没有直接的链接器来获取GaussDB,目前连接GaussDB的方法有2个: ODBC, JDBC,这两种方式在云端都要通过设置网关,pbi云端通过网关链接到虚拟机或者某台电脑上,电脑安装个人网关(组织网关没有成功,不知道为什么,知道原因的希望能留言),下面说下两种连接方式: …

2025-1-20-盒子模型-弹性盒子模型

重新学一下巩固,之前发的看不了,本来还想着直接看呢 盒子模型 width,height是宽高,padding是内边距,如果里边有文本的话一般是贴着左上方,但是有内边距就不会,类似下边的演示图;border是内外之间边框,就是给宽高之外加一层;margin是外边距,可以理解为是你构造的边框…

【Ubuntu】安装OpenSSH启用远程连接

【Ubuntu】安装OpenSSH启用远程连接 零、安装软件 使用如下代码安装OpenSSH服务端: sudo apt install openssh-server壹、启动服务 使用如下代码启动OpenSSH服务端: sudo systemctl start ssh贰、配置SSH(可跳过) 配置文件 OpenSSH的配置文件所在位置:/etc/ssh/sshd_confi…

CTF-web第二步!

菜狗杯web的传说之下。打开F12,发现有个Game=new Underophidian(gameCanvas)表明有个Game变量存储着数据。在控制台输入Game获取,根据题意,修改分数,然后玩一下就可以得到flag了。

【CodeForces训练记录】Codeforces Round 1000 (Div. 2)

训练情况赛后反思 C题猜了个假结论WA4,每次选择度最多的删掉,在连续三个度都是最大的情况下,删中间的会寄 A题 有点前缀和的感觉,\([1,l]\) 互质个数为 \(l\),\([1,r]\) 互质个数为 \(r\),所以区间 \([l,r]\) 的个数就是 \(r-l\),特判一下 \(l=1,r=1\) 的情况答案是 \(1\…

GUIClip在IMGUI中的作用

目录简介IMGUIGUIClipPush Pop Count局部坐标StyleDraw中Rect点的位置鼠标位置绝对坐标ScrollOffset对局部坐标的影响局部坐标和绝对坐标的相互转化裁剪参考链接 简介 Unity中的IMGUI是一个独立于ugui的UI系统。IMGUI是事件(消息)驱动的UI系统,主要用于编写开发工具。 Unity官…

ceph-安装

【os】 ubuntu1804 【文心上找到的】 【步骤】一、环境准备‌配置节点名称‌:配置集群各节点的hostname,确保互相可以通过hostname来解析节点IP,不需要通过DNS。 ‌时间同步‌:确保所有节点的时间同步,以避免时间不一致导致的问题。 ‌关闭防火墙和SELinux‌:为了简化安装…

开源项目芋道源码解析 [开篇]

文章首发于我的博客:https://blog.liuzijian.com/post/source-code-about-ruoyi-vue-pro.html 1.引言 芋道(又名yudao,ruoyi-vue-pro)是一个基于spring-boot框架的单体Java后端开源项目,拥有基于RBAC模型的组织架构管理、CRM、ERP、商城、代码生成、AI等多个功能模块。封装了…

【跟着阿舜学音乐-笔记】2.2了解架子鼓

2.2了解架子鼓 架子鼓:学名爵士鼓,最早起源于爵士乐,后演变为流行音乐中最主要的套鼓。这里展示一下架子鼓构成2.2.1.底鼓 低音大鼓,在整套乐器中声音最低、最重的鼓,它主要的作用就是铺设节奏。导入导出音轨时,一般写作BD,即英文Bass Drum。(在音乐当中,越是低音的部…

Java编程规范-常量定义

常量定义规范【强制】常量不允许任何魔法值(即未经定义的常量)直接出现在代码中。 反例: String key = "Id#taobao_" + tradeId; cache.put(key, value);【强制】long 或者 Long 初始赋值时,必须使用大写的 L,不能是小写的 l,小写容易跟数字 1 混淆,造成误解…

2025省选模拟8

2025省选模拟8题目来源: 2024省选联测10 \(T1\) HZTG5836. 小幸运 \(18pts\)将坐标扩大 \(2\) 倍后答案只可能为整数,证明显然。二分答案, \(check\) 时考虑 \(2-SAT\) 。将一个点可能构成的等腰直角三角形划分成如下四个部分,最终仅能选择相邻的两个。不妨两条对角线上的取…

2025临沂一中强基考试游记

大烂特烂,故作此篇。 友情出演:王茂 *:八下年级rk1、常年年级前五。 范明 *:实力不详,遇强则强,至少比我强。 张晨 *:考过全区rk1,磕头。 公续 *、刘子 *:仅次于王张的大神。 韩梓 *:六边形战士。 张嘉 *、左世 *:实力不是很清楚( 比我强就对了Day -2 被我妈施压了…