分库分表?如何做到永不迁移数据和避免热点?

2023-11-10

在这里插入图片描述

本文经授权转载自今日头条号:老顾聊技术
原文地址:www.toutiao.com/i6677459303055491597

一、前言

中大型项目中,一旦遇到数据量比较大,小伙伴应该都知道就应该对数据进行拆分了。有垂直和水平两种

垂直拆分比较简单,也就是本来一个数据库,数据量大之后,从业务角度进行拆分多个库。如下图,独立的拆分出订单库和用户库。

图片水平拆分的概念,是同一个业务数据量大之后,进行水平拆分。

图片

上图中订单数据达到了4000万,我们也知道mysql单表存储量推荐是百万级,如果不进行处理,mysql单表数据太大,会导致性能变慢。使用方案可以参考数据进行水平拆分。把4000万数据拆分4张表或者更多。当然也可以分库,再分表;把压力从数据库层级分开。

二、分库分表方案

分库分表方案中有常用的方案,hash取模和range范围方案;分库分表方案最主要就是路由算法,把路由的key按照指定的算法进行路由存放。下边来介绍一下两个方案的特点。

2.1、hash取模方案

在这里插入图片描述

在我们设计系统之前,可以先预估一下大概这几年的订单量,如:4000万。每张表我们可以容纳1000万,也我们可以设计4张表进行存储。

那具体如何路由存储的呢?hash的方案就是对指定的路由key(如:id)对分表总数进行取模,上图中,id=12的订单,对4进行取模,也就是会得到0,那此订单会放到0表中。id=13的订单,取模得到为1,就会放到1表中。为什么对4取模,是因为分表总数是4。

  • 优点:

订单数据可以均匀的放到那4张表中,这样此订单进行操作时,就不会有热点问题。

热点的含义:热点的意思就是对订单进行操作集中到1个表中,其他表的操作很少。

订单有个特点就是时间属性,一般用户操作订单数据,都会集中到这段时间产生的订单。如果这段时间产生的订单 都在同一张订单表中,那就会形成热点,那张表的压力会比较大。

  • 缺点:

将来的数据迁移和扩容,会很难。

如:业务发展很好,订单量很大,超出了4000万的量,那我们就需要增加分表数。如果我们增加4个表

图片

一旦我们增加了分表的总数,取模的基数就会变成8,以前id=12的订单按照此方案就会到4表中查询,但之前的此订单时在0表的,这样就导致了数据查不到。就是因为取模的基数产生了变化。

遇到这个情况,我们小伙伴想到的方案就是做数据迁移,把之前的4000万数据,重新做一个hash方案,放到新的规划分表中。也就是我们要做数据迁移。这个是很痛苦的事情。有些小公司可以接受晚上停机迁移,但大公司是不允许停机做数据迁移的。

当然做数据迁移可以结合自己的公司的业务,做一个工具进行,不过也带来了很多工作量,每次扩容都要做数据迁移

那有没有不需要做数据迁移的方案呢,我们看下面的方案

2.2、range范围方案

range方案也就是以范围进行拆分数据。

图片

range方案比较简单,就是把一定范围内的订单,存放到一个表中;如上图id=12放到0表中,id=1300万的放到1表中。设计这个方案时就是前期把表的范围设计好。通过id进行路由存放。

  • 优点

我们小伙伴们想一下,此方案是不是有利于将来的扩容,不需要做数据迁移。即时再增加4张表,之前的4张表的范围不需要改变,id=12的还是在0表,id=1300万的还是在1表,新增的4张表他们的范围肯定是 大于 4000万之后的范围划分的。

  • 缺点

有热点问题,我们想一下,因为id的值会一直递增变大,那这段时间的订单是不是会一直在某一张表中,如id=1000万 ~ id=2000万之间,这段时间产生的订单是不是都会集中到此张表中,这个就导致1表过热,压力过大,而其他的表没有什么压力。

2.3、总结:

hash取模方案:没有热点问题,但扩容迁移数据痛苦

range方案:不需要迁移数据,但有热点问题。

那有什么方案可以做到两者的优点结合呢?,即不需要迁移数据,又能解决数据热点的问题呢?

其实还有一个现实需求,能否根据服务器的性能以及存储高低,适当均匀调整存储呢?

图片

三、方案思路

hash是可以解决数据均匀的问题,range可以解决数据迁移问题,那我们可以不可以两者相结合呢?利用这两者的特性呢?

我们考虑一下数据的扩容代表着,路由key(如id)的值变大了,这个是一定的,那我们先保证数据变大的时候,首先用range方案让数据落地到一个范围里面。这样以后id再变大,那以前的数据是不需要迁移的

但又要考虑到数据均匀,那是不是可以在一定的范围内数据均匀的呢?因为我们每次的扩容肯定会事先设计好这次扩容的范围大小,我们只要保证这次的范围内的数据均匀是不是就ok了。

图片

四、方案设计

我们先定义一个group组概念,这组里面包含了一些分库以及分表,如下图:

图片

上图有几个关键点:

1)id=0~4000万肯定落到group01组中

2)group01组有3个DB,那一个id如何路由到哪个DB?

3)根据hash取模定位DB,那模数为多少?模数要为所有此group组DB中的表数,上图总表数为10。为什么要去表的总数?而不是DB总数3呢?

4)如id=12,id%10=2;那值为2,落到哪个DB库呢?这是设计是前期设定好的,那怎么设定的呢?

5)一旦设计定位哪个DB后,就需要确定落到DB中的哪张表呢?

图片

五、核心主流程

图片

按照上面的流程,我们就可以根据此规则,定位一个id,我们看看有没有避免热点问题。

我们看一下,id在【0,1000万】范围内的,根据上面的流程设计,1000万以内的id都均匀的分配到DB_0,DB_1,DB_2三个数据库中的Table_0表中,为什么可以均匀,因为我们用了hash的方案,对10进行取模。

上面我们也提了疑问,为什么对表的总数10取模,而不是DB的总数3进行取模?我们看一下为什么DB_0是4张表,其他两个DB_1是3张表?

在我们安排服务器时,有些服务器的性能高,存储高,就可以安排多存放些数据,有些性能低的就少放点数据。如果我们取模是按照DB总数3,进行取模,那就代表着【0,4000万】的数据是平均分配到3个DB中的,那就不能够实现按照服务器能力适当分配了。

按照Table总数10就能够达到,看如何达到

图片

上图中我们对10进行取模,如果值为【0,1,2,3】就路由到DB_0,【4,5,6】路由到DB_1,【7,8,9】路由到DB_2。现在小伙伴们有没有理解,这样的设计就可以把多一点的数据放到DB_0中,其他2个DB数据量就可以少一点。DB_0承担了4/10的数据量,DB_1承担了3/10的数据量,DB_2也承担了3/10的数据量。整个Group01承担了【0,4000万】的数据量。

注意:小伙伴千万不要被DB_1或DB_2中table的范围也是0~4000万疑惑了,这个是范围区间,也就是id在哪些范围内,落地到哪个表而已。

上面一大段的介绍,就解决了热点的问题,以及可以按照服务器指标,设计数据量的分配。

图片

六、如何扩容

其实上面设计思路理解了,扩容就已经出来了;那就是扩容的时候再设计一个group02组,定义好此group的数据范围就ok了。

图片

因为是新增的一个group01组,所以就没有什么数据迁移概念,完全是新增的group组,而且这个group组照样就防止了热点,也就是【4000万,5500万】的数据,都均匀分配到三个DB的table_0表中,【5500万~7000万】数据均匀分配到table_1表中。

七、系统设计

图片

思路确定了,设计是比较简单的,就3张表,把group,DB,table之间建立好关联关系就行了。

图片

group和DB的关系

图片

table和db的关系

上面的表关联其实是比较简单的,只要原理思路理顺了,就ok了。小伙伴们在开发的时候不要每次都去查询三张关联表,可以保存到缓存中(本地jvm缓存),这样不会影响性能。

在这里插入图片描述

一旦需要扩容,小伙伴是不是要增加一下group02关联关系,那应用服务需要重新启动吗?

简单点的话,就凌晨配置,重启应用服务就行了。但如果是大型公司,是不允许的,因为凌晨也有订单的。那怎么办呢?本地jvm缓存怎么更新呢?

其实方案也很多,可以使用用zookeeper,也可以使用分布式配置,这里是比较推荐使用分布式配置中心的,可以将这些数据配置到分布式配置中心去,对分布式配置中心不了解的,可以看下《三种主流的微服务配置中心深度对比!你怎么看!

到此为止,整体的方案介绍结束,希望对小伙伴们有所帮助。谢谢!!!

这边隐含了一个关键点,那就是路由key(如:id)的值是非常关键的,要求一定是有序的,自增的,这个就涉及到分布式唯一id的方案,有对分布式ID不清楚的小伙伴,可以查看往期内容《如果再有人问你分布式ID,这篇文章丢给他!


往期热门文章:

1、历史文章分类导读列表!精选优秀博文都在这里了!》

2、17 张程序员专属壁纸,太太太太太太骚了…

3、刚刚,腾讯每人发100股:市值7万,不算年终奖!员工:愿为小马哥拼命

4在 IDEA 中用了热部署神器 JRebel 之后,开发效率提升10倍!

5、Typora + GitHub = 效率

6、女朋友为我写了一个防猝死插件

7、请谨慎使用Arrays.asList、ArrayList的subList

8全球顶级的14位程序员!膜拜!

9、万亿级数据应该怎么迁移?

10从应用到底层 36张图带你进入Redis世界图片

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分库分表?如何做到永不迁移数据和避免热点? 的相关文章

随机推荐

  • Maven安装步骤汇总

    Maven安装步骤汇总 最近老是换机器开发 机器上又没有Maven 每次都要下载 安装 重复写配置文件 很麻烦 而习惯的常用配置网上教程很分散 故做整合 目录 Maven下载安装 配置环境变量测试 修改maven配置文件 3 1 修改本地仓
  • STM32在应用编程(IAP)详解

    什么是IAP STM32单片机的程序烧写有多种方法 分别为 JTAG SW ISP IAP gt JTAG的方式需要专用的烧写工具 在产品布置到现场后 更新产品程序比较麻烦 gt ISP即为 在系统编程 In System Programm
  • python之计算系统空闲内存、列表字典相互转换

    python之计算系统空闲内存 usr bin env python coding utf8 Time 2017 11 30 14 25 Author hantong File count free memory py 统计linux系统空
  • element date-picker range类型时间选择器 限制选中前后7天的时间的方法

    实现效果 代码
  • 使用webpack-bundle-analyzer分析uni-app 的微信小程序包大小(HbuilderX运行)

    1 找到vue config js 文件 如果找不到 则在项目根目录下 跟pages json同一个目录下 创建一个JS文件 命名为vue config js 2 安装webpack bundle analyzer 官方网站 https g
  • Java连接数据库警告WARN: Establishing SSL connection without server's identity ......

    今天搭了个框架 发现数据库发出了警告 Fri Mar 23 13 49 33 CST 2018 WARN Establishing SSL connection without server s identity verification
  • python乱码怎么办_解决python发送邮件乱码问题

    使用python发邮件很简单 但是遇到乱码问题很烦恼 乱码问题有几种 有发件人名称乱码 有标题乱码 也有正文乱码的问题 一 发件人名称乱码 要解决发件人名称乱码问题 必须使用Header 如下代码 from email header imp
  • 记忆化搜索简介

    记忆化搜索 算法上依然是搜索的流程 但是搜索到的一些解用动态规划的那种思想和模式作一些保存 一般说来 动态规划总要遍历所有的状态 而搜索可以排除一些无效状态 更重要的是搜索还可以剪枝 可能剪去大量不必要的状态 因此在空间开销上往往比动态规划
  • 【IDEA】Idea 报错 Module was compiled with an incompatible version of Kotlin. The binary version of its

    1 场景1 提示 在项目本地DEBUG或者build的时候报了以下错误 kotlin stdlib common kotlin module Module was compiled with an incompatible version
  • vant的中文的文档

    vant的中文的文档 拿走把小傻瓜 https vant contrib gitee io vant zh CN 但是本着点赞自愿 收藏吃灰 还是多少可以支持一下
  • TCP连接的状态详解以及故障排查

    1 TCP状态 了解TCP之前 先了解几个命令 linux查看tcp的状态命令 1 netstat nat 查看TCP各个状态的数量 2 lsof i port 可以检测到打开套接字的状况 3 sar n SOCK 查看tcp创建的连接数
  • C++中非常好用的泛型函数

    1 泛型函数 泛型函数结合lambda函数可以实现很多功能如 将序列中的每个负数替换为其绝对值 transform vi begin vi end vi begin int x return x lt 0 x x 查找第一个长度大于等于sz
  • Camera ISP

    1 ISP工作原理 ISP Image Signal Processor 即图像信号处理 主要作用是对前端图像传感器输出的信号做后期处理 依赖于 ISP 才能在不同的光学条件下都能较好的还原现场细节 景物通过 Lens 生成的光学图像投射到
  • 微信小程序- 选择器 合并时间和日期

    https developers weixin qq com miniprogram dev component picker html 从底部弹起的滚动选择器 类型有普通选择器 多列选择器 时间选择器 日期选择器 省市区选择器 没有现成的
  • Unity3D打包时,编译错误

    最近打包Unity3D的APK包时 报编译错误 Failed to compile Java code to DEX D Work Parkour branches 20131219 box360 Temp StagingArea gt j
  • VLC裁剪和移植到S3C6410

    1 由于项目需求 这几天在折腾VLC 需要将它裁剪并移植到PowerPC上 由于板子没有到 先在6410上跑 目前从需求看我们只要VLC作为一个server即可 先贴配置 如下 几乎disable掉所有东东 bin sh for arm C
  • Loki搭建日志收集系统

    Loki 什么是Loki Loki是受Prometheus启发的水平可扩展 高度可用的多租户日志聚合系统 他被设计为非常经济高效且易于操作 它不索引日志内容 而是为每个日志流设置一组标签 Loki文档网址 https grafana com
  • 牛客面试必刷TOP101——二分查找排序

    列表 二分查找 I BM17 二维数组中的查找 BM18 寻找峰值 BM19 组中的逆序对 BM20 旋转数组的最小数字 BM21 比较版本号 BM22 二分查找 I BM17 原题 请实现无重复数字的升序数组的二分查找 给定一个 元素升序
  • 不可控器件——电力二极管(电导调制效应)

    电力二极管 也被称之为半导体整流器 是不可控器件 原理简单 工作可靠 以半导体PN结为基础 PN结是由一个N型掺杂区和一个P型掺杂区紧密接触所构成的 由于两者的多子是不同的 会造成两者的多子向另一个方向做扩散运动 到对方区域形成少数载流子
  • 分库分表?如何做到永不迁移数据和避免热点?

    本文经授权转载自今日头条号 老顾聊技术 原文地址 www toutiao com i6677459303055491597 一 前言 中大型项目中 一旦遇到数据量比较大 小伙伴应该都知道就应该对数据进行拆分了 有垂直和水平两种 垂直拆分比较