【PHP】一文搞懂MySQL数据库分库分表
如果数据量过大,大家一般会分库分表。分库需要注意的内容比较少,但分表需要注意的内容就多了。
工作这几年没遇过数据量特别大的业务,那些过亿的数据,因为索引设置合理,单表性能没有影响,所以实战中一直没用过分表。最近手里有个项目,预估数据量会很大,分表方案是选项之一,趁着这次机会,把分表的内容整理一下。
这次要讲的主要是水平分库分表,其它种类的分库、分表比较容易理解。后面如果不详细说明,都指水平分库分表。
1.基础知识
1.1分库分表定义
1.1.1分库
垂直分库:按照业务模块进行切分,将不同模块的表切分到不同的数据库中。
如电商系统有电商数据库,按照业务模块可以分为用户库、商品库、订单库,这些都可以当做独立数据库,不需要放到一起。好处是既能独立变更,又能隔绝相互影响。
1.1.2分表
垂直分表:也就是“大表拆小表”,基于列字段进行的。一般是因为表设计不合理,需要进行拆分。
如一张表存放学生、老师、课程、成绩信息,最好拆分为学生表、课程表、成绩表。
水平分表:针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。不建议采用。
水平分库分表:将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。
1.2分区与分片的区别
分表时经常能看到两个名词:分区和分片。这两个词都是指将大表的数据分成多块,但两者还是有本质区别的。
Sharding(分片) 的思想从分区的思想而来,但数据库分区基本上是数据对象级别的处理,比如表和索引的分区,每个子数据集上能够有不同的物理存储属性,还是单个数据库范围内的操作,而 Sharding 是能够跨数据库,甚至跨越物理机器的。
MySQL5.1提供的分区(Partition)功能确实可以实现表的分区,但是这种分区是局限在单个数据库范围里的,它不能跨越服务器的限制。
我们在分表的时候,一般使用的是分片方案,即数据存放在多个物理机器。
1.3分片策略
分片规则一般有如下:
1.3.1按照哈希切片
-
mod-long:用于分区列为数值的hash分区
分片列 id=分区列值 mod 分片数
-
mod-long-by-hash:用于分区列为字符串的hash分区
分片列id=hash(分区列值) mod 分片数
1.3.2按照范围切片
-
range:建表时创建分区规则,根据分区规则就可以确定分区列的值在哪个分区上
一般分区列为时间或者数值,如
date_range:0: 10000001: 20000002: 30000003: 40000004: maxvalue
如果分区列值为1500000,则数据放到1号分片上。
2.分库分表中间件
需要使用者感知不到这是分片表,使用时需要和正常表一样,一般需要引入中间件。
操作分片表一般有三种方式:
2.1客户端分片
所谓的客户端分片即在使用数据库的应用层直接操作分片逻辑,分片规则需要在同一个应用的多个节点间进行同步,每个应用层嵌入一个操作切片的逻辑实现。如当当网的Sharding JDBC。
2.2代理分片
代理分片就是在应用层和数据库层之间添加一个代理层,把分片的路由规则配置在代理层,代理层对外提供与JDBC兼容的接口给应用层,在业务实现之后,在代理层配置路由规则即可。如Mycat就是基于此种解决方案来实现的。
2.3支持事务的分布式数据库
支持分布式事务的框架,目前有OceanBase、TiDB框架,这些框架将可伸缩特定和分布式事务的实现包装到了分布式数据库内部实现,对使用者透明,使用者不需要直接控制这些特性,但是对事务的支持不如关系型数据,适合大数据日志系统、统计系统、查询系统、社交网站等。
2.4说明
支持事务的分布式数据库算另一种选型了,和MySQL已经没有关系。
对于客户端分片和代理分片,目前工作过的两家公司用的都是代理方式,一家用的是MyCAT,一家用的Dbatman。客户端分片方式没有接触过。这两种的区别为:
3.分布式事务
分片意味数据分布在多台物理机器上,引入分布式事务问题。我们将单表的数据切片后存储在多个数据库甚至是多个数据库实例中,所以依靠数据库本身的事务机制不能满足需要,这时就需要用到分布式事务来解决。关于分布式事务的相关内容可以看分布式系统与一致性协议。
这里不细讲分布式事务如何处理,后面会单独写篇文章。我们聊一下分布式事务会对操作MySQL产生什么影响。
既然知道引入了分布式事务问题,那么操作MySQL的时候,肯定不能和单表一样进行操作。不同中间件能力不一样,所以需要单独分析,我以Dbatman为例,阐述使用上的区别。
-
分片版本不维护自增与主键唯一,业务可自行维护唯一键
-
意味不同分片的主键id会重复
-
不支持跨分片事务写,可以跨分片事务读
-
如果确保事务操作的内容在一个分片内,就不是分布式事务,和单机行为一致
-
一个事务涉及多个分片叫跨节点事务,单分片事务支持
-
update和insert必须带分片列
总结一下就是操作同一个分片没影响,操作不同分片需要看中间件支持不支持。
4.是否选择分库分表
选择做分库分表,考虑的几个要素是:
-
空间方面:单个物理实例无法支撑数据存储需求,单台物理机无法继续通过加盘的方式扩容
-
主库性能:受限于单个主库的CPU/内存/磁盘IOPS的影响,接近或者达到上限后,需要拆分
-
容灾方面:减少单个主库宕机对于写入的影响。
针对以上3点,我们还可以多考虑一下,有没有更合适的方案
-
空间方面:
-
删除历史数据清空空间
-
修改存储模型降低对于MySQL磁盘的占用
-
改用空间压缩比更高的存储引擎
-
主库性能:
-
可以通过读写分离的方式,降低对于写库的读请求量,从而提升对于写入的支撑。
-
优化数据写入模型,减少批量写入(削峰)
-
容灾方面:
-
如果业务对于读高可用要求比较高,一般建议是做读写分离,将重要的请求路由至读库。读库数量一般会比写库多N个,在代理层面会做容灾的自动切换。
-
从集群整体的角度看,分库分表实际上是会扩大故障率,假设单台物理机的SLA是99.99%,那么2台物理机的SLA就是99.98(约数), 10台物理机的SLA就只剩下99.90%了。平均每年的故障时间也会从52分钟提升到525分钟。所以在有些场景下,单个节点故障可能会导致代理整个不可用,从而放大故障的影响范围。
5.设计
现在项目需求为:
-
生成唯一码,码值为整数
-
码值需要批量插入数据库
-
对码的更新操作都是单条处理,而且对码值进行操作需要进行记录
-
最终数量不定,长远看数据量会很大
基于上面的需求,做如下设计:
-
以码值为主键,自己控制主键唯一
-
码表使用range进行分片,如分片范围为01亿,1亿2亿
-
码表的操作记录表同样使用range进行分片,分片范围和码表一致
通过这种设计能够实现需求。
但计算后发现,单表能存百亿条数据,而且索引设计比较合理,业务逻辑相对简单,无高并发请求,单表好像也可以搞。
总结
正常情况下,我们一般需要做水平分库分表,这就涉及到分布式事务,一定要考虑清楚是否能满足自己的需求、想用的SQL语句是否都能支持,考虑一下是否还有别的方案。
关于中间件的实现原理,了解的不是很深,后面有时间的话,可以学习一下。
猜你喜欢
- 【PHP】Permission denied怎么解决
- Permission denied的解决方法:1、确保当前用户具有足够的权限来执行该操作;2、如果当前用户没有足够的权限,可以尝试更改文件或目录的权限;3、如果当前用户不是管理员或没有足够的权限,可以尝试使用管理员权限来执行操作;4、可以尝试更改文件系统属性,以便允许写入操作;5、可以尝试释放磁盘空间,以便有足够的空间来执行操作;6、检查文件是否被其他进程占用。当我们遇到Permission denied这样的错误提示时,这通常意味着我们没有足够的权限来执行某个操作。解决Permiss
- 【PHP】php常见的集群有哪些
- php常见的集群有LAMP集群、Nginx集群、Memcached集群、Redis集群和Hadoop集群。详细介绍:1、LAMP集群,LAMP是指Linux、Apache、MySQL和PHP的组合,是一种常见的PHP开发环境,在LAMP集群中,多个服务器运行相同的应用程序,并通过负载均衡器将请求分发到不同的服务器上;2、Nginx集群,Nginx是一种高性能的Web服务器等等。本教程操作系统:windows10系统、PHP 8.1.3版本、DELL G3电脑。PHP是一种广泛使用的服务
- 【PHP】使用ThinkPHP6实现分布式系统
- 随着互联网的发展,越来越多的企业和组织开始使用分布式系统来支持其业务需求。分布式系统是指由多个互相独立的计算机系统集成在一起,共同完成一些任务或处理一些数据,整个系统看起来就像是一个单一的计算机系统。在Web应用程序中,ThinkPHP是一个非常流行的PHP框架。ThinkPHP6是其最新的版本,提供了更多的功能和性能优化。如果你想要使用ThinkPHP6来构建分布式系统,下面是一些实现的步骤:第一步:搭建应用程序框架首先,你需要在你的服务器上安装PHP。然后,你需要安装Composer,这是一
- 【PHP】ThinkPHP与Laravel一样吗
- thinkphp和laravel是不一样的。thinkphp和laravel虽然都是php开发框架,但是有很多区别:1、渲染末班的方式不同,thinkphp用“$this->display()”的方式渲染模版,laravel使用“return view()”方法;2、laravel是一个重路由的框架,而thinkphp要有控制器方法才能正常访问。thinkphp和laravel不一样ThinkPHP是免费开源的,快速的,简单的,面向对象的轻量级PHP开发框架,ThinkPHP可以支持win
- 【PHP】 thinkphp怎样编写单元测试
- 在ThinkPHP框架中编写单元测试,你可以使用ThinkPHP内置的测试功能或者集成第三方测试工具,如PHPUnit。1. 使用ThinkPHP内置的测试功能:首先,确保你的ThinkPHP版本支持测试功能。然后,在应用目录下创建一个名为tests的目录,在该目录内创建测试文件,例如ExampleTest.php。// tests/ExampleTest.php namespace tests\thinkphp; use think\testing\
- 【PHP】RESTfulAPI详解
- 1. 什么是RESTfulAPIRESTful API 是一种互联网软件架构的设计规范,设计指南,设计风格,设计原则(类似于web标准,并不是标准【规范,原则】)2. 产生背景开始开发时,前后端高度融合(耦合) 近些年:前后端分离,前端各种客户端产生。基于这种现状,需要一个统一的机制。为前后端通信服务(API机制) 因此,前后端分离开来前后端基于API 开发,即:面向接口开发 前后端基于接口传递数据。 RESTfulAPI作为制定接口标准的规范而产生了。3. RESTful APIAPI简介:
- 【PHP】PHP8.1新特性大讲解之readonly properties只读属性
- PHP 8.1:只读属性多年来,用 PHP 编写数据传输对象和值对象变得非常容易。以 PHP 5.6 中的 DTO 为例:class BlogData { /** @var string */ private $title; /**
- 【PHP】php中实现3DES算法(ECB加密模式PKCS5Padding填充)
- 讲道理,一提到3DES算法,首先想到的是要和java做交互了==现在3DES已经渐渐被抛弃了,尤其是ECB加密模式使用的更少了,但是没办法,业务需要,合作方用的是他,你头再铁也不能怎样,那就扒扒文档咯网上完整的php实现以经不多了,CBC加密模式居多,所以我参考了好几篇文章,整理了一个class出来,共享上来,避免后来人踩坑感谢前人的整理总结:PHP版3DES加解密类更新成PKCS5填充模式 (http://blog.163.com/hui\_san/blog/static/5710286720