MySQL的分片

article/2025/9/13 8:36:03

前言
从开发人员的角度来说,为什么要了解和掌握MySQL分片?

第一,了解MySQL分片可以更合理地定制分片策略,选分片字段是要讲科学的。

第二,了解MySQL分片以后如果出现故障报错,也有助于问题的排查。

第三,关系到开发过程中的代码调整,做分片后的MySQL数据库操作受到限制,比如join之类的操作,跨分片的操作,事务管理等,都是要注意的,可能需要代码的调整。

分区、分表、分片、分库的概念
那么首先,我们要理解一下分区、分表、分片、分库的概念。

分区,局限于单一数据库节点,将一张表分散存储在不同的物理块中。MySQL5以后支持分区,但是不支持二级分区,并且单机MySQL的性能远远不如Oracle,所以分区并不能解决性能问题。

分表,分表有两种,应用层面的分表和代理层面的分表。

应用层面的分表,人工把一张逻辑上完整的表分成若干个小表。比如T_PAYMENT表分为T_PAYMENT_0101…T_PAYMENT_1231。对代码不透明。

代理层面的分表,通过MERGE引擎或者代理中间件把表分成若干的字表,对应用只保留一个“表壳”,对代码透明。(MERGE引擎示意)

 

分表和分区比较类似,侧重点不同,分区侧重提高读写性能,分表侧重提高并发性能。两者不冲突,可以配合使用。

分库,单纯的分库就是垂直切分,把不同业务逻辑的表分开存储在在不同的数据库。

分片,分片就是分库+分表,属于水平切分,将表中数据按照某种规则放到多个库中,既分表又分库,就相当于原先一个库中的一个表,现在放到了好多个表里面,然后这好多个表又分散到了好多个库中。分片和分区也不冲突。

MySQL分片
分片键

数据分片是将一张分布式表按照指定的分片键(Partition Key)和分片模式(Partition Mode)水平拆分成多个数据片,分散在多个数据存储节点中。对于分片的表,要选取一个分片键。一张分布式表只能有一个分片键,分片键是用于划分和定位表的列,不能修改。

分片模式

•枚举/列表List

{1 => Cluster A, 2 => Cluster B}

•范围Range (仅支持数字或ASCII字符串类型的分片键)

{[1 - 100] => Cluster A, [101 - 199] => Cluster B}

•散列Hash (仅支持数字或ASCII字符串类型的分片键)

{1024n + 1 => Cluster A, 1024n + 2 => Cluster B}

分片方式类似于分区方式,可以选择枚举,范围Range或者散列哈希。不同的是分片不支持时间range。

分片策略

在做分片的时候,选择合适的分片规则非常重要,将极大地避免后续数据的处理难度,有以下几点需要关注:

1. 能不分就不分,对于1000万以内的表,不建议分片,通过合适的索引,读写分离等方式,可以更好地解决性能问题。

2. 分片数量不是越多越好,并且尽量均匀分布在多个存储节点上,只在必要的时候进行扩容,增加分片数量。

3. 分片键不能为空,不能修改,所以要选择表中中最常用且不变的字段。

4. 分片键选择时尽量做到可以将事务控制在分片范围内,可以避免出现跨分片的操作。

5. 选择分片规则时,要充分考虑数据的增长模式,数据的访问模式,分片关联 性问题,以及分片扩容问题。

总体上来说,分片的选择是取决于最频繁的查询 SQL 的条件。找出每个表最频繁的 SQL,分析其查询条件,以及相互的关系,并结合 ER 图,就能比较准确的选择每个表的分片策略。

MySQL分片要解决的问题
事务问题

分布式数据库分散在多个不同的物理主机,网络环境复杂,关注事务,保证数据一致性是一个问题。

先看单机环境下的事务管理,以Spring为例,利用注解的事务管理:

    @Override
    @Transactional
    public void service(){
        ...
        UserService.updateUserByUserId(userId);
        ...
        OrderService.updateOrderByOrderNo(orderNo);
        ...
}
实际上这段代码相当于:

    @Override
    public void service(){
        ...
        UserService.updateUserByUserId(userId);
        ...
        OrderService.updateOrderByOrderNo(orderNo);
        ...
        try{
            commit();
        }catch(Exception e){
            rollback();
        }
}

 

如何给多主机发commit并且保证他们最终状态一致就是分布式事务要解决的问题。

解决这个问题有两种方案。

第一种由应用程序和数据库共同控制,将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务,并通过应用程序来总控各个小事务。

    @Override
    public void service(){
        ...
        userService();
        ...
        try{
            orderService();
        }catch(Exception e){
            rollback();
        }
        ...
        }

    
    @Override
    @Transactional
    public void userService() throws RuntimeException{
        ...
        UserService.updateUserByUserId(userId);
        ...
    }

    @Override
    @Transactional
    public void orderService() throws RuntimeException{
        ...
        OrderService.updateOrderByOrderNo(orderNo);
        ...
    }
}
这个方法是性能上比较高效,缺点就是需要应用程序在事务控制上做灵活设计。如果使用 了Spring的事务管理,改动起来会面临一定的困难。

第二种是交由数据库管理,简单有效。比较常见的方案有两阶段提交2PC、补偿事务TCC,MQ事务消息等。下图演示了2PC的过程。

除了图中提到的三个缺点,两阶段提交的方案影响的整体性能。

根据CAP原理,分布式数据库无法做到完全的ACID原则,几乎所有分布式解决方案都牺牲了部分一致性或者可用性。比如用最终一致性代替强一致性。

跨节点Join的问题

只要是进行切分,跨节点Join的问题是不可避免的。但是良好的设计和切分却可以减少此类情况的发生。解决这一问题的普遍做法是分两次查询实现。在第一次查询的结果集中找出关联数据的id,根据这些id发起第二次请求得到关联数据。

如果频次较高,可以考虑添加一张关联表,规避掉join操作,空间换时间。

在交易时直接将记录插入关联表,即可在查询时查询关联表获得想要的结果。

跨节点的count,order by,group by以及聚合函数问题

这些是一类问题,因为它们都需要基于全部数据集合进行计算。多数的代理都不会自动处理合并工作。

解决方案:与解决跨节点join问题的类似,分别在各个节点上得到结果后在应用程序端进行合并。和join不同的是每个结点的查询可以并行执行,因此很多时候它的速度要比单一大表快很多。但如果结果集很大,对应用程序内存的消耗是一个问题。

值得提醒的是,如果你的应用中包含大量的此类分析及聚合操作,考虑是否你对系统类型判断有误,是OLAP而非OLTP系统。对于OLAP系统不推荐使用MySQL更不推荐使用DRDS分布式数据库存储。

数据迁移,容量规划,扩容等问题

在前期如果对系统数据仓库的容量没有正确的预估,会遇到扩容问题。

利用对2的倍数取余具有向前兼容的特性(如对4取余得1的数对2取余也是1)来分配数据,避免了行级别的数据迁移,但是依然需要进行表级别的迁移,同时对扩容规模和分表数量都有限制。

举例说明,扩容前有两个集群作为存储节点,现要扩容为四个。

 

将原先的备机(A1,B1)升级为主机,然后再分别给他们配置备机,即完成了两倍的扩容。根据前面说的向前兼容的特性,分片规则不需要变化,是目前比较常用的扩容方案。

这部分实际和开发人员关系不大,了解即可。

ID问题

一旦数据库被切分到多个物理结点上,我们将不能再依赖数据库自身的主键生成机制。

一方面,某个分区数据库自生成的ID无法保证在全局上是唯一的;

另一方面,应用程序在插入数据之前需要先获得ID,以便进行SQL路由。

比较常见的ID解决方案是应用生成UUID,或者在数据库中维护一个Sequence表。
 

跨分片的排序分页

一般来讲,分页时需要按照指定字段进行排序。当排序字段就是分片字段的时候,我们通过分片规则可以比较容易定位到指定的分片,而当排序字段非分片字段的时候,情况就会变得比较复杂了。为了最终结果的准确性,我们需要在不同的分片节点中将数据进行排序并返回,并将不同分片返回的结果集进行汇总和再次排序,最后再返回给用户。如下图所示:

上面图中所描述的只是最简单的一种情况(取第一页数据),看起来对性能的影响并不大。但是,如果想取出第10页数据,情况又将变得复杂很多,如下图所示:

有些读者可能并不太理解,为什么不能像获取第一页数据那样简单处理(排序取出前10条再合并、排序)。其实并不难理解,因为各分片节点中的数据可能是随机的,为了排序的准确性,必须把所有分片节点的前N页数据都排序好后做合并,最后再进行整体的排序。很显然,这样的操作是比较消耗资源的,用户越往后翻页,系统性能将会越差。

那如何解决分库情况下的分页问题呢?有以下几种办法:

如果是在前台应用提供分页,则限定用户只能看前面n页,这个限制在业务上也是合理的,一般看后面的分页意义不大(如果一定要看,可以要求用户缩小范围重新查询)。

如果是后台批处理任务要求分批获取数据,则可以加大page size,比如每次获取5000条记录,有效减少分页数(当然离线访问一般走备库,避免冲击主库)。

分库设计时,一般还有配套大数据平台汇总所有分库的记录,有些分页查询可以考虑走大数据平台。

分库策略

比较常见的两种分库策略,按照范围分库或者按照Mod分库,各有侧重点。

按照范围分库一般在前期数据量较小,在使用过程中用户数据不断增长,在数据库数量少时全库查询消耗小,后期调整数据库数量也比较容易。

按照Mod分库在初期就要规划好数据库数量,单库查询性能好,如果调整Mod因子会导致数据库迁移,后期增加数据库数量也比较麻烦。

实际使用中为了处理简单,一般选mod分库,数据库数量选择2的倍数,方便扩容。

分库数量

分库数量首先和单库能处理的记录数有关,一般来说,Mysql 单库超过5000万条记录,Oracle单库超过1亿条记录,DB压力就很大(当然处理能力和字段数量/访问模式/记录长度有进一步关系)。

在满足上述前提下,如果分库数量少,达不到分散存储和减轻DB性能压力的目的;如果分库的数量多,好处是每个库记录少,单库访问性能好,但对于跨多个库的访问,应用程序需要访问多个库,如果是并发模式,要消耗宝贵的线程资源;如果是串行模式,执行时间会急剧增加。

最后分库数量还直接影响硬件的投入,一般每个分库跑在单独物理机上,多一个库意味多一台设备。所以具体分多少个库,要综合评估,一般初次分库建议分4-8个库。

路由透明

分库从某种意义上来说,意味着DB schema改变了,必然影响应用,但这种改变和业务无关,所以要尽量保证分库对应用代码透明,分库逻辑尽量在数据访问层处理。

历史数据清理

历史数据的清理是一个比较棘手的问题。

假设我有一张订单表,联机系统只保存最近五天的订单,之前的要删除掉。

我们没办法根据日期进行分片,因为日期每天都在变化,按照日期分片意味着分片规则每天都在变化。这和常见的在Oracle定时任务删除分区和新建分区是不一样的。

假使我们根据设备进行分片,那么常规情况下,同一天的订单会均匀分布在各个分片上。最起码的原则是避免跨分片操作,因为跨分片操作性能极其低而且很多时候你也不知道会发生什么未知的事情。

所以比较容易想到的方法就是找到每个分片然后再每个分片上进行单独的数据清理操作。

如果是自研的分布式架构,应该可以通过脚本将清理语句分别路由到各个分片。如果是使用的开源中间件,大部分都会提供分片操作的方法(如果没有,那只能另寻他法了。)。如果是使用的商业服务的分布式数据库,也会提供分片数据清理操作的方法。

这部分我自己也确实没有其他更好的方案。
 

 

// 转自: https://blog.csdn.net/rl_leee/article/details/83143335


http://chatgpt.dhexx.cn/article/fohEk1Xk.shtml

相关文章

外汇天眼:新手如何模拟炒外汇?模拟炒外汇的一点心得分享

模拟炒外汇通常是在没有进行外汇交易之前利用外汇交易软件的模拟账户进行无风险的外汇交易。是刚入门的投资者为熟悉外汇交易软件和外汇市场而经常使用的方法。 新手如何模拟炒外汇? 外汇市场的火热让不少投资者纷纷加入,很多高手也都是从新手走过来的…

外汇套利原理及策略EA

外汇套利,通俗解释就是当相同货币对或相关货币对之间的价差偏离正常范围时进行买卖,当价差回归正常范围时获利平仓的一种交易策略。 外汇套利分为三类 单品种的跨平台套利两相关品种的对冲套利三相关品种的三角套利 如何开发三角套利策略 “三角” 是…

外汇平台怎么选择?玩外汇又有那些优势呢?

外汇平台怎么选择?玩外汇又有那些优势呢? 怎么选择好的外汇平台呢? 第一个 是优先选择大炒外汇的交易平台,虽然也不排除一些小平台是优质的,不过对于新手投资者来说在判断上是很难下决断的。选大平台的主要原因是可以搜索相关的口碑&…

创建模拟外汇网站

1.创建网站模板 2.创建网站服务器 1.创建网站模板 打开pycharm,File→New Project,创建项目文件夹project1 单击项目文件project1,右键新建一个名称为rates.csv的文件。 输入以下内容: 交易币,交易币单位,现汇卖出价,现钞卖出价,现汇买入价…

量化交易之平台搭建

该篇主要是是用来展示量化交易的效果,不构成任何投资建议,仅供参考 搭建的环境: ​ 系统 linux-centos7 python环境: ​ python3.7.4 先安装好我们的库: cd demo pip install -r requirements.txt -i https://pypi.douban.com/simple安…

外汇交易平台怎么选择?

近年来,外汇业发展可谓是生机勃勃,形形色色外汇交易商如雨后春笋般涌出,铺天盖地的外汇广告不停袭击着你的眼球,一夜暴富的神话天天都在上演……外汇市场一片繁荣。市场繁荣说明大众投资理财意识正日渐成熟,但是这个杂…

五步看平台,选好安全的MT4交易外汇平台

在选择MT4外汇交易平台时,如何避免不正规的平台?以下是5招教你远离不正规MT4交易外汇平台。 1. 查看平台是否取得合法许可证 首要考虑的是该平台是否取得了合法的许可证。许可证是证明一个交易平台合法的最重要证据,因此务必在选择时核查该平台的许可证…

结算平台的搭建

写在前头的话: 希望这一系列可以多多帮到一些人——想要做后端产品经理的人、正在做后端产品经理的人、已经放弃了后端产品的人。博主产品经理的资历不深,是一个”复盘“派。 因为涉及部分商业信息,所以时隔了好几年后,才在这里…

如何搭建自己的外汇平台,教你如何搭建外汇平台,如何省钱

外汇市场从世纪之初进入中国,到如今有十几个年头。从起初耳熟能详的几个平台商到现在如雨后春笋般出现,中国的外汇市场越来越开放,价格成本也越来越透明。很多外汇代理商不断发展壮大,对搭建自己的平台有了需求。 开外汇平台赚钱,是一个普遍流传的说法。但是开平台到底有…

泰坦科技MT4平台搭建提供一站式白标方案 快速开启外汇经纪业务

众所周知,外汇市场是全球最大的金融市场,而利用白标技术成为外汇服务提供商是很多人选择运营外汇业务的第一步。相对于外汇主标需要购买整套系统和独立服务器这样的高额成本,搭建一个白标平台要容易的多,也可以相对较快地开展外汇…

领歌敏捷协作——修改密码

文章目录 领歌敏捷协作——修改密码1、进入用户中心2、点击修改密码3、输入原密码进行确认 领歌敏捷协作——修改密码 1、进入用户中心 2、点击修改密码 3、输入原密码进行确认

领歌敏捷协作——自定义领歌背景

文章目录 领歌敏捷协作——自定义领歌背景1、登陆领歌2、点击菜单,选择设置背景3、选择背景图片 领歌敏捷协作——自定义领歌背景 1、登陆领歌 领歌地址:https://www.leangoo.com 2、点击菜单,选择设置背景 3、选择背景图片 选择背景图片&…

领歌敏捷协作——设置备用邮箱,主备切换

文章目录 领歌敏捷协作——设置备用邮箱,主备切换1、进入用户中心2、点击添加备用邮箱3、输入备用邮箱并进行验证4、主备邮箱切换 领歌敏捷协作——设置备用邮箱,主备切换 1、进入用户中心 2、点击添加备用邮箱 3、输入备用邮箱并进行验证 4、主备邮箱切…

领歌敏捷协作——通过数据筛选进行快速定位

文章目录 领歌敏捷协作——通过数据过滤进行快速定位1、选择并进入一个看板2、进入筛选面板1、点选标签2、点选成员3、输入关键词 3、全局搜索4、执行搜索 领歌敏捷协作——通过数据过滤进行快速定位 1、选择并进入一个看板 点击右侧菜单的筛选 2、进入筛选面板 1、点选标签 …

领歌敏捷协作——设置微信接收卡片提醒

文章目录 领歌敏捷协作——设置微信接收卡片提醒1、进入用户中心2、进入第三方帐号页面3、点击绑定4、关注领歌公众号5、哪几种情况才会收到领歌的微信通知 领歌敏捷协作——设置微信接收卡片提醒 1、进入用户中心 2、进入第三方帐号页面 3、点击绑定 打开微信,扫描…

领歌敏捷协作——修改看板名称

文章目录 领歌敏捷协作——修改看板名称1、进入看板列表2、选择一个看板3、点击修改名称4、输入新名称并保存 领歌敏捷协作——修改看板名称 1、进入看板列表 2、选择一个看板 进入看板后,点击看板名称 3、点击修改名称 4、输入新名称并保存

领歌敏捷协作——显示折叠视图

文章目录 领歌敏捷协作——显示折叠视图1、选择并进入一个看板2、使用折叠视图 领歌敏捷协作——显示折叠视图 1、选择并进入一个看板 2、使用折叠视图 点击红框所示位置,进入折叠视图 折叠视图如图所示 通过折叠视图,我们可以快速的查看整个看板的…

轻量级看板任务协作工具Leangoo领歌实现多泳道看板任务管理

在敏捷开发的实践当中,通过可视化的任务看板来实现团队协同和透明化管理是必不可少的一个实践。通过可视化的任务看板我们可以达到如下几个目的: 1. 可视化管理团队的目标; 2. 明确目标的优先级; 3. 明确目标分解后的任务项; 4. 可视化管理任务的进展状…

ScrumMaster认证培训(CSM)记录篇-Leangoo领歌

前不久参加了Leangoo领歌CSM认证公开班,简单记录下我的学习之旅 当初选课程时也很是纠结,最终选择了Leangoo领歌,Leangoo领歌是Scrum中文网旗下的一款敏捷研发管理工具。 Leangoo领歌由Scrum中文网资深的敏捷顾问团队和敏捷研发团队经过近十…

领歌敏捷协作——创建看板

文章目录 领歌敏捷协作——创建看板1、点击新建看板2、选择创建选项,并命名看板3、如何选择适合的模版,模版一览1、Sprint Backlog2、产品Backlog3、缺陷看板4、敏捷看板方法-看板5、通用任务管理看板6、用户反馈管理7、OKR目标管理8、Issue管理&#xf…