分库分表——从理论到最佳实践

目录

  • 1、为什么要分库分表?
  • 2、切分方案有哪些?
    • 2.1 分库
      • 2.1.1 垂直分库
      • 2.1.2 水平分库
    • 2.2 分表
      • 2.2.1 垂直分表
      • 2.2.2 水平分表
    • 2.3 分库分表
  • 3、数据水平分片方法
    • 3.1 Hash分片
    • 3.2 一致性Hash分片
    • 3.3 Range分片
  • 4、分库分表的挑战
    • 4.1 分布式id
    • 4.2 分布式事务
    • 4.3 动态扩容
    • 4.4 跨库关联问题
    • 4.5 服务、数据平滑迁移
    • 4.6 数据库基本的增删改功能
    • 4.7 子表分库分表
  • 5、项目实战

1、为什么要分库分表?

随着业务的不断发展,系统数据量不断增加,即便正确设置了索引,仍然无法掩盖因为数据量过大从而导致的数据库性能下降的事实。 对于单台 MySQL 服务器来说,硬件资源(如存储容量、连接数与处理能力)是有限的。当数据量过大或读写操作并发过高时,超出了单服务器的性能瓶颈,可能会对系统的稳定性产生严重隐患,甚或导致系统整体不可用。

在仅查询请求量增加的场景中,通过主从架构实现读写分离能够满足业务读多写少的需求,从而保证系统的可靠性。然而,当数据库中单表数据量增大时,业务操作的耗时会增加。有时,由于业务特点的限制,归档或删除操作无法从根本上解决问题。此外,进行大表结构变更时需要拷贝数据,若表数据量过大会导致无剩余空间进行表结构修改。

当单表数据量过大或写操作负荷过高,以至于达到存储或性能的上限时,必须通过数据切分等方式进行治理。核心思想是通过分割数据,确保单表和单机的负荷在机器性能许可的范围内。


2、切分方案有哪些?

切分方案主要解决的问题
只分库不分表(分库)数据库读/写QPS过高,数据库连接数不足
只分表不分库(分表)单表数据量过大,存储性能遇到瓶颈
既分库又分表(分库分表)以上两种问题

2.1 分库

分库,指的是将数据从单个数据库拆分成多个数据库的过程。拆分后的数据库往往部署在多套集群中,这也就意味着降低了单个集群的负载压力,提升整体的读写性能。

分库通常有两种方式,垂直分库和水平分库。

2.1.1 垂直分库

垂直分库是指根据业务领域划分,将不同领域的库表拆分到多个数据库中,从而分散数据存储和读取压力,降低数据层面的耦合度。

垂直分库

2.1.2 水平分库

水平分库通常与分表操作一起进行。当单表数据量过大,导致存储容量和读写性能出现瓶颈时,可以根据一定规则将单表拆分成多个表,并将这些表存储在不同的数据库中,从而解决存储容量和性能问题。
水平分库


2.2 分表

分表,指的是将单张数据表拆分成多张表的过程,以减少单表容量,提升读写效率。如提升数据写入时索引的构建效率、减少锁范围等;对于读流量也能较好减少耗时。

分表通常有两种方式:垂直分表和水平分表。

2.2.1 垂直分表

垂直分表是指根据实际应用场景,将数据表中的部分列拆分出来,改变原有表结构。通常可以结合实际查询需求、冷热数据分离和大字段独立存储等方式进行分表。如将db库中的订单表拆分为订单基本信息表和订单详细信息表。
垂直分表

2.2.2 水平分表

水平分表是指当单表数据量过大且不断增长,导致存储备份缓慢和读取效率低下时,将单表按一定规则拆分成多张表。这样可以降低单表容量,提升数据查询效率。如将db库中的订单表拆分为32个分表,order_[0-31],分表还位于同一个库中。
水平分表

2.3 分库分表

在处理海量数据时,单一的数据库和数据表会面临存储容量和性能瓶颈。通过同时进行分库和分表,我们可以将单表的数据水平拆分为多个表,并将这些表分散存储在多个数据库中。这样不仅能有效降低单一数据库和数据表的负载压力,还能提升数据的读写性能和系统的整体稳定性。


3、数据水平分片方法

确定了分库分表后就需要考虑如何将数据分到哪个库或哪个表中。分片是一种水平切分数据表的方式,可以将数据按特定策略切分成多个数据文件,这些文件既可以存储在单节点上,也可以存储在分布式的多个节点上,从而实现更强大的存储和计算能力。下面介绍几种常见的数据分片方法。

3.1 Hash分片

Hash分片,就是按照数据记录中指定关键字的Hash值将数据记录映射到不同的分片中。如图所示,通过一个Hash函数计算用户ID的Hash值而后取模,分配到对应的分片。模为4的原因是系统一共有四个节点,每个节点作为一个分片。

hash分片
优点:这种方法实现简洁,可以保证数据非常均匀地分布到多个分片上。
缺点:直接用节点数作为模,如果系统节点数量变动,模也随之改变,数据就要重新Hash计算,从而带来大规模的数据迁移。显然,这种方式的扩展性不好。

必须找一个方法提升系统的扩展性,就是接下来要介绍的一致性Hash。

3.2 一致性Hash分片

一致性哈希是一种特殊的哈希算法,其核心思想是在一个虚拟的环上分布数据和节点,不同于传统的哈希算法,这种方法在增加或删除节点时能够最小化数据重分布。

如图所示,首先会引入虚拟节点,每个虚拟节点就是一个分片。这个案例中将分片数量设定为16。(因为分片数量决定了集群的最大规模,所以实践中它通常会远大于初始集群节点数。)

一致性Hash
16个分片构成了整个Hash空间,数据记录都要通过Hash函数映射到这个空间,我们换一种方式画图,可以看得更清楚些。如下图所示,Hash空间构成了一个Hash环,数据按照顺时针找到最近的节点。
hash环

当我们新增一台服务器,即节点E时,受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向的第一台服务器)之间数据。结合我们的示例,只有小红分享的消息从节点B被移动到节点E,其他节点的数据保持不变。此后,节点B只存储Hash值6和7的消息,节点E存储Hash值4和5的消息。
hash环加节点
一致性哈希优点:

  • 数据均衡:能够将数据均衡地分布到多个表中,避免某些表过度负载。
  • 扩展性强:当需要增加新的表时,一致性哈希允许新的表平滑地加入系统,不会导致大量数据重新分布。部分表失效或移除的情况下,一致性哈希能将其数据分布到剩余的表中,减小影响范围。

3.3 Range分片

范围分片是一种根据数据值的范围将数据拆分成多个部分(片)的分片方法。每个片包含一个特定范围内的连续数据。通常,这种方法使用数据的某个关键字段来确定数据的范围,例如日期、用户ID、订单号等。

假设有一个订单表 orders,我们可以按订单日期将其拆分成不同的分片:

orders_2020: 存储2020年的订单
orders_2021: 存储2021年的订单
orders_2022: 存储2022年的订单

这种方式使用偏少,先介绍到这。工作中MySQL分片最常用的还是Hash分片。


4、分库分表的挑战

4.1 分布式id

在分库分表后,我们不能再使用mysql的自增主键。因为在插入记录的时候,不同的库生成的记录的自增id会出现冲突。因此需要有一个全局的id生成器。

4.2 分布式事务

原本采用单库,通过本地事务就可以保障一致性。分库后因为涉及到了同时更新多个数据库,如何保证要么同时成功,要么同时失败。分布式事务是分库分表绕不过去的一个坎。柔性事务是目前比较主流的方案,柔性事务包括:最大努力通知型、可靠消息最终一致性方案以及TCC两阶段提交等。

4.3 动态扩容

动态扩容指的是增加分库分表的数量。例如原来的user表拆分到2个库的4张表上。现在我们希望将分库的数量变为4个,分表的数量变为8个。这种情况下一般要伴随着数据迁移。

4.4 跨库关联问题

单库下的表连接操作,在分库后需要进行改造。常见的方式有冗余存储数据、应用层拼接等;

4.5 服务、数据平滑迁移

单库单表迁移到分库分表后,为了保证平稳过渡,上层无影响,需要采用相应的策略进行服务、数据的迁移;

4.6 数据库基本的增删改功能

对于开发人员而言,虽然分库分表,但还是希望能和单库单表那样的去简单地操作数据库,包括查询与DML操作。(通常是通过数据库中间件实现,中间件的原理大体分为:数据源代理、数据库代理。具体可搜索cobar、zebra、sharding-jdbc等关键字了解其原理)

4.7 子表分库分表

在进行主表分库分表时,子表也需要进行相应的处理。需要按照相同的分片规则进行分库分表,确保数据的关联性和查询的效率。工作量会翻倍。


5、项目实战

XXXXXXXXXXXXXXXXXXX 待补充XXXXXX

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

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

相关文章

LLM:归一化 总结

一、Batch Normalization 原理 Batch Normalization 是一种用于加速神经网络训练并提高稳定性的技术。它通过在每一层网络的激活值上进行归一化处理,使得每一层的输入分布更加稳定,从而加速训练过程,并且减轻了对参数初始化的依赖。 公式 …

分类模型——逻辑回归和Fisher线性判别分析

个人学习笔记,课程为数学建模清风付费课程 目录 一、引例 二、逻辑回归 2.1线性概率模型 2.2Fisher线性判别分析 2.3两点分布(伯努利分布) 2.4连接函数的取法 2.5如何求解 2.6如何用于分类 三、SPSS 3.1二元分类 3.1.1逻辑回…

MySQL内如何改变编码格式

查找数据库的编码格式&#xff1a; show variables like character%;具体内容时这些 在创建表时设定编码格式&#xff1a; create database <要创建的数据库的名字> charset utf8; 修改数据库默认编码&#xff1a; set character_set_databaseutf8mb4; character_…

eclipse ui bug

eclipse ui bug界面缺陷&#xff0c;可能项目过多&#xff0c;特别maven项目过多&#xff0c;下载&#xff0c;自动编译&#xff0c;加载更新界面异常 所有窗口死活Restore不回去了 1&#xff09;尝试创建项目&#xff0c;还原界面&#xff0c;失败 2&#xff09;关闭所有窗口&…

Vue.js 搭建大屏可视化项目

引言 在数字化转型的时代背景下&#xff0c;大屏可视化项目因其直观的数据展示和实时的业务监控能力而变得日益重要。Vue.js&#xff0c;以其简洁的语法、高效的虚拟DOM和强大的组件化能力&#xff0c;成为了构建大屏可视化应用的首选框架之一。本文将从零开始&#xff0c;引导…

Springboot @Validate @Valid 基于复杂嵌套对象的参数校验示例

Springboot Validate Valid 基于复杂嵌套对象的参数校验示例 复杂对象 Data public class Object1 {Length(max 50,message "长度不能超过50位字符")NotBlank(message "名称不能为空")private String name;NotNull(message "不能为空")pri…

将TP5链接导入笔影个人博客代码

首先第一步&#xff0c;打开界面 第二步&#xff0c;这里卡住了&#xff0c;无法看到源代码&#xff0c;我们使用其他软件看看源代码 调试乱码&#xff0c;因为没有找到相应的笔影个人博客源码。源码在桌面上。询问百度&#xff0c;说了有的没的一大堆。 尝试的结果就是失败…

时间复杂度与O(n)

文章目录 1 复杂度分析1.1 时间复杂度1.1.1 循环执行次数1.1.2 大O(n)表示法 1.2 空间复杂度 1 复杂度分析 1.1 时间复杂度 ​ 时间复杂度用来表示算法运行时间的长短&#xff0c;用来定性的描述程序的运行时间。要了解时间复杂度&#xff0c;我们需要先了解程序执行的次数。…

机器学习(二十二):精度和召回率

一、倾斜数据集 倾斜数据集&#xff1a;一个数据集中的正面和负面例子的比例非常不平衡&#xff0c;比如数据集中&#xff0c;结果为1的占比20%&#xff0c;结果为0的占比80% 例子&#xff1a;如果数据集的结果中只有0.5%是1&#xff0c;其余结果是0。有一个模型的预测准确度…

【elasticsearch实现词重复,文档长度不影响匹配度】

elasticsearch实现词重复&#xff0c;文档长度不影响匹配度 前言BM25&#xff08;默认&#xff09;索引重建 前言 搜索场景要求&#xff1a; 关键词重复出现不影响匹配度【默认重复匹配度会提高】记录的文档长度不影响匹配度【默认文档越短&#xff0c;匹配度越高】 BM25&am…

【信创】udisk2服务异常导致U盘使用中自动移除问题解决

原文链接&#xff1a;【信创】udisk2服务异常导致U盘使用中自动移除问题解决 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在信创终端操作系统上由于udisk2服务异常导致U盘等移动设备在使用中自动移除问题的排查文章。udisk2是一个管理存储设备的服务&#xf…

restTemplate实现http远程调用

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /*** description 将RestTemplate注入到容器当中&#xff0c;让他保持单例&#xff0c;当我们哪个…

树莓派下,docker中安装部署TensorFlow java版本

在树莓派上安装和部署TensorFlow Java版本需要一些特定的步骤,尤其是当你打算使用Docker容器来运行它时。以下是详细的步骤,帮助你在树莓派上完成这一任务。 一、准备工作 确保你的树莓派操作系统已更新,并安装了Docker。如果尚未安装,使用以下命令进行安装和更新: sud…

C++学习第四天

文章目录 1. 存储变量值的内存2. 声明并初始化指针3.引用运算符4. 解除引用运算符 1. 存储变量值的内存 /* - 指针是一个变量&#xff0c;与所有变量一样&#xff0c;指针也占用内存空间- 指针的特殊之处在于&#xff0c;指针包含的值&#xff08;这里为0x558&#xff09;被解…

【计算机网络】OSPF单区域实验

一&#xff1a;实验目的 1&#xff1a;掌握在路由器上配置OSPF单区域。 2&#xff1a;学习OSPF协议的原理&#xff0c;及其网络拓扑结构改变后的变化。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS交换机、网线、内网网卡接口、Windows 2019操作系统的计算机等。…

Vue 3 实现左侧列表点击跳转滚动到右侧对应区域的功能

使用 Vue 3 实现左侧列表点击跳转到右侧对应区域的功能 1. 引言 在这篇博客中&#xff0c;我们将展示如何使用 Vue 3 实现一个简单的页面布局&#xff0c;其中左侧是一个列表&#xff0c;点击列表项时&#xff0c;右侧会平滑滚动到对应的内容区域。这种布局在很多应用场景中都…

Llama 3.1 405B 详解

2024 年 7 月 23 日星期二&#xff0c;Meta 宣布推出 Llama 3.1&#xff0c;这是其Llama 系列大型语言模型 (LLM)的最新版本。虽然只是对 Llama 3 模型进行小幅更新&#xff0c;但它特别引入了Llama 3.1 405B——一个 4050 亿参数的模型&#xff0c;这是迄今为止世界上最大的开…

力扣刷题录——链表

一、移除链表元素 移除链表元素 法一&#xff1a;不使用虚拟头节点 ListNode* removeElements(ListNode* head, int val) {//若删除头节点while(head!NULL&&head->valval)//连续删除头节点的条件{headhead->next;} //删除其他节点&#xff08;先判断是不是空链…

【Qt 关于信号和槽 的参数类型和参数顺序关系】

前言&#xff1a;信号的参数类型和参数顺序一定要严格要求并且指明&#xff08;特别是当同一信号会发出不同参数类型和顺序的信号时&#xff09;&#xff0c;槽会根据参数类型和参数顺序进行匹配相应的槽函数&#xff0c;期间槽函数的自动类型匹配也可以生效。 信号定义&#x…

运行ruoyi

nacos 数据库配置 修改nacos/conf/application.properties 单机版运行 startup.cmd -m standalone redis 运行后端 运行gateway,auth,modules/system模块 可能遇到的问题&#xff1a;端口正在使用 解决 netstat -ano | findstr 9200 taskkill -pid 18284 -f