黄东旭解析 TiDB 的核心优势
3460
2023-06-06
本文讲述了一文搞懂MySQL数据库分库分表,分库分表能解决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: 1000000
1: 2000000
2: 3000000
3: 4000000
4: maxvalue
如果分区列值为1500000,则数据放到1号分片上。
2.分库分表中间件
需要使用者感知不到这是分片表,使用时需要和正常表一样,一般需要引入中间件。
操作分片表一般有三种方式:
2.1客户端分片
所谓的客户端分片即在使用数据库的应用层直接操作分片逻辑,分片规则需要在同一个应用的多个节点间进行同步,每个应用层嵌入一个操作切片的逻辑实现。如当当网的Sharding JDBC。
2.2代理分片
代理分片就是在应用层和数据库层之间添加一个代理层,把分片的路由规则配置在代理层,代理层对外提供与JDBC兼容的接口给应用层,在业务实现之后,在代理层配置路由规则即可。如Mycat就是基于此种解决方案来实现的。
2.3支持事务的分布式数据库
支持分布式事务的框架,目前有***、TiDB框架,这些框架将可伸缩特定和分布式事务的实现包装到了分布式数据库内部实现,对使用者透明,使用者不需要直接控制这些特性,但是对事务的支持不如关系型数据,适合大数据日志系统、统计系统、查询系统、社交网站等。
2.4说明
支持事务的分布式数据库算另一种选型了,和MySQL已经没有关系。
对于客户端分片和代理分片,目前工作过的两家公司用的都是代理方式,一家用的是MyCAT,一家用的Dbatman。客户端分片方式没有接触过。这两种的区别为:
3.分布式事务
分片意味数据分布在多台物理机器上,引入分布式事务问题。我们将单表的数据切片后存储在多个数据库甚至是多个数据库实例中,所以依靠数据库本身的事务机制不能满足需要,这时就需要用到分布式事务来解决。关于分布式事务的相关内容可以看分布式系统与一致性协议。
这里不细讲分布式事务如何处理,后面会单独写篇文章。我们聊一下分布式事务会对操作MySQL产生什么影响。
既然知道引入了分布式事务问题,那么操作MySQL的时候,肯定不能和单表一样进行操作。不同中间件能力不一样,所以需要单独分析,我以Dbatman为例,阐述使用上的区别。
1.分片版本不维护自增与主键唯一,业务可自行维护唯一键
意味不同
2.不支持跨分片事务写,可以跨分片事务读
如果确保事务操作的内容在一个分片内,就不是分布式事务,和单机行为一致
一个事务涉及多个分片叫跨节点事务,单分片事务支持
3.update和insert必须带分片列
总结一下就是操作同一个分片没影响,操作不同分片需要看中间件支持不支持。
如果使用中间件,即使同一个分片,尽量不要用特殊的SQL,有些中间件可能无法支持,如insert not exists。
4.是否选择分库分表
选择做分库分表,考虑的几个要素是:
空间方面:单个物理实例无法支撑数据存储需求,单台物理机无法继续通过加盘的方式扩容
主库性能:受限于单个主库的CPU/内存/磁盘IOPS的影响,接近或者达到上限后,需要拆分
容灾方面:减少单个主库宕机对于写入的影响。
针对以上3点,我们还可以多考虑一下,有没有更合适的方案
1.空间方面:
删除历史数据清空空间
修改存储模型降低对于MySQL磁盘的占用
改用空间压缩比更高的存储引擎
2.主库性能:
可以通过读写分离的方式,降低对于写库的读请求量,从而提升对于写入的支撑。
优化数据写入模型,减少批量写入(削峰)
3.容灾方面:
如果业务对于读高可用要求比较高,一般建议是做读写分离,将重要的请求路由至读库。读库数量一般会比写库多N个,在代理层面会做容灾的自动切换。
从集群整体的角度看,分库分表实际上是会扩大故障率,假设单台物理机的SLA是99.99%,那么2台物理机的SLA就是99.98(约数), 10台物理机的SLA就只剩下99.90%了。平均每年的故障时间也会从52分钟提升到525分钟。所以在有些场景下,单个节点故障可能会导致代理整个不可用,从而放大故障的影响范围。
5.设计
现在项目需求为:
生成唯一码,码值为整数
码值需要批量插入数据库
对码的更新操作都是单条处理,而且对码值进行操作需要进行记录
最终数量不定,长远看数据量会很大
基于上面的需求,做如下设计:
以码值为主键,自己控制主键唯一
码表使用range进行分片,如分片范围为01亿,1亿2亿
码表的操作记录表同样使用range进行分片,分片范围和码表一致
通过这种设计能够实现需求。
但计算后发现,单表能存百亿条数据,而且索引设计比较合理,业务逻辑相对简单,无高并发请求,单表好像也可以搞。
总结
正常情况下,我们一般需要做水平分库分表,这就涉及到分布式事务,一定要考虑清楚是否能满足自己的需求、想用的SQL语句是否都能支持,考虑一下是否还有别的方案。
分库分表的优点非常明显,如:将大表拆分成小表,单表数据量控制在 5000 万行以内,使 MySQL 性能稳定可控。将单张大表拆分成小表后,能水平扩展,通过部署到多台服务器,提升整个集群的 QPS、TPS、Latency 等数据库服务指标。
但是,此方案的缺点也非常明显:
分表跨实例后,产生分布式事务管理难题,一旦数据库服务器宕机,有事务不一致风险。
分表后,对 SQL 语句有一定限制,对业务方功能需求大打折扣。尤其对于实时报表统计类需求,限制非常之大。事实上,报表大多都是提供给高层领导使用的,其重要性不言而喻。
分表后,需要维护的对象呈指数增长(MySQL实例数、需要执行的 SQL 变更数量等)。
上文就是小编为大家整理的一文搞懂MySQL数据库分库分表,分库分表能解决MySQL哪些问题?优缺点是什么?
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。