分库、分表、分区

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1、 读写分离 & 一主多备

在实际的应用中绝大部分情况都是读远大于写。Mysql提供了读写分离的机制所有的写操作都必须对应到Master读操作可以在 Master和Slave机器上进行Slave与Master的结构完全一样一个Master可以有多个Slave甚至Slave下还可以挂 Slave通过此方式可以有效的提高DB集群的 QPS。
所有的写操作都是先在Master上操作然后同步更新到Slave上所以从Master同步到Slave机器有一定的延迟当系统很繁忙的时候延迟问题会更加严重Slave机器数量的增加也会使这个问题更加严重。

注意所有的写操作都是先在Master上操作所以Master是集群的瓶颈当写操作过多会严重影响到Master的稳定性如果Master挂掉整个集群都将不能正常工作。
当读压力很大的时候可以考虑添加Slave机器的分式解决但是当Slave机器达到一定的数量就得考虑分库了。
当写压力很大的时候就必须得进行分库操作。

2. 分库分表

2.1. 分库分表的基本原理

为什么要分库分表
– 用户请求量太但是单服务器 TPS内存IO 都是有限的
– 单库太大单库所在服务器上磁盘空间不足单库处理能力有限存在 IO 瓶颈
– 单表太大索引膨胀查询超时
分库分表的目标
– 分表可以解决单表海量数据的读写性能问题
– 分库可以解决单台数据库的并发访问压力问题。
拆分思路
– 垂直拆分垂直分库、垂直分表
– 水平拆分水平分库、水平分表

垂直拆分是指按功能模块拆分垂直拆分解决表与表之间的 I/O 竞争。比如分为订单库、商品库、用户库…这种方式多个数据库之间的表结构不同。
水平拆分将同一个表的数据进行分块保存到不同的数据库中水平拆分解决单表中数据量增长出现的压力。这些数据库中的表结构完全相同。

分库分表的顺序
分库分表的顺序应该是先垂直分后水平分。因为垂直分更简单更符合我们处理现实世界问题的方式

2.2. 垂直分表

垂直分表是基于列字段对表格进行横向拆分。

垂直分表规则
– 数据较大的字段单独存表
– 不常用的的字段单独存表
– 经常一起使用的字段放在一起存表
– 长度较长比如text类型字段的字段单独存表
垂直分表一般是针对那种几百列的大表也避免查询时数据量太大造成的“跨页”问题。
分表能够解决单表数据量过大带来的查询效率下降的问题但是却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问当数据库master服务器无法承载写操作压力时不管如何扩展slave服务器此时都没有意义了。因此我们必须换一种思路对数据库进行拆分从而提高数据库写入能力这就是所谓的分库。

2.3. 垂直分库

垂直分库是针对一个系统中的不同业务进行拆分比如用户User一个库商品Producet一个库订单Order一个库。

垂直切分后一般放在多个服务器上而不是一个服务器上。这是因为一个购物网站对外提供服务会有用户商品订单等的CRUD。没拆分之前 全部都是落到单一的库上的这会让数据库的单库处理能力成为瓶颈。

按垂直分库后如果还是放在一个数据库服务器上 随着用户量增大这会让单个数据库的处理能力成为瓶颈还有单个服务器的磁盘空间内存tps等非常吃紧。 所以我们要拆分到多个服务器上这样上面的问题都解决了以后也不会面对单机资源问题。
数据库往往最容易成为应用系统的瓶颈而数据库本身属于“有状态”的相对于Web和应用服务器来讲是比较难实现“横向扩展”的。 数据库的连接资源比较宝贵且单机处理能力也有限在高并发场景下垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。数据库业务层面的拆分能对不同业务的数据分别的进行管理维护监控扩展等。

2.4. 水平分表不单独使用

针对数据量巨大的单张表比如订单表按照某种规则RANGE,HASH取模等切分到多张表里面去。

水平分表的问题
– 但是这些表还是在同一个库中所以库级别的数据库操作还是有IO瓶颈。
– 无法进行跨表直连连接查询
– 统计数据不方便
– 如果数据持续增长达到现有分表的瓶颈需要增加分表时、会出现数据重新排列的情况。
生产环境中水平分表一般不单独使用而是和水平分库一起使用做水平分库分表。

2.5. 水平分库一般与水平分表同时使用

将单张表的数据切分到多个服务器上去每个服务器具有相应的库与表只是表中数据集合不同。水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力突破IO、连接数、硬件资源等的瓶颈。

水平分库分表策略
– 用户 id 取模
– 如果不是整数可以进行 hash 获取到整数
– 按照地理区域拆分
– 按照时间拆分
– 按照【冷热数据】拆分

分库分表的标准

什么样的情况需要分库分表
– 表体积大于 2G行数大于 1000 万
– 表中含有 text、blob、varchar(1000)
– 数据有时效性可以单独拿出来归档
分库分表的大小多少合适
分表最大分1024一般分100左右比较适合。

2.6. 分库分表存在的问题

维度的问题

假如用户购买了商品,需要将交易记录保存取来如果按照用户的纬度分表则每个用户的交易记录都保存在同一表中所以很快很方便的查找到某用户的 购买情况但是某商品被购买的情况则很有可能分布在多张表中查找起来比较麻烦。反之按照商品维度分表可以很方便的查找到此商品的购买情况但要查找 到买人的交易记录比较麻烦。
维度的问题解决办法记录【两份数据】一份按照用户纬度分表一份按照商品维度分表。

联合查询的问题

联合查询基本不可能因为关联的表有可能不在同一数据库中。这是因为分库分表后表之间的关联操作将受到限制我们无法join位于不同分库的表也无法join分表粒度不同的表 结果原本一次查询能够完成的业务可能需要多次查询才能完成。
联合查询问题的解决方法
– 全局表基础数据所有库都拷贝一份
– 字段冗余这样有些字段就不用join去查询了
– 系统层组装分别查询出所有然后组装起来较复杂。

跨库事务问题

避免在一个事务中修改db0中的表的时候、同时修改db1中的表一个是操作起来更复杂效率也会有一定影响。
分库分表后就成了分布式事务了。如果依赖数据库本身的分布式事务管理功能去执行事务将付出高昂的性能代价 如果由应用程序去协助控制形成程序逻辑上的事务又会造成编程方面的负担。

数据依赖问题

例如卖家a的商品和交易信息都放到db0中当db1挂了的时候卖家a相关的东西可以正常使用。尽量把同一组数据放到同一DB服务器上避免数据库中的数据依赖另一数据库中的数据。

2.7. 分库分表产品方案

MySQL Proxy
Amoeba
Hibernate Shards
sharding-jdbc

3. 分区分片

3.1. 分区原理

表分区就是将数据量比较大的表在物理上分成若干个小表从逻辑来看还是一个大表。MySQL 5 之后才有了数据表分区功能。
数据库的应用分为两类一类是OLTP在线事务处理如Blog、电子商务、网络游戏等另一类是OLAP在线分析处理如数据仓库、数据集市。

对于OLAP的应用分区的确是可以很好地提高查询的性能。
因为OLAP应用大多数查询需要频繁地扫描一张很大的表。假设有一张1亿行的表其中有一个时间戳属性列。用户的查询需要从这张表中获取一年的数据。如果按时间戳进行分区则只需要扫描相应的分区即可。

对于OLTP的应用分区应该非常小心。
在这种应用下通常不可能会获取一张大表10%的数据大部分都是通过索引返回几条记录即可。而根据B+树索引的原理可知对于一张大表一般的B+树需要2~3次的磁盘IO。因此B+树可以很好地完成操作不需要分区的帮助并且设计不好的分区会带来严重的性能问题。
MySQL的分区字段必须包含在主键字段内。

3.2. 分区策略

RANGE分区
最常用的一种分区类型基于属于一个给定连续区间的列值把多行分配给分区。这些区间要连续且不能相互重叠使用VALUES LESS THAN操作符来进行定义。

LIST分区
– LIST分区和RANGE分区类似区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择而非连续的。
– LIST分区通过使用“PARTITION BY LIST(expr)”来实现其中“expr” 是某列值或一个基于某个列值、并返回一个整数值的表达式然后通过“VALUES IN (value_list)”的方式来定义每个分区其中“value_list”是一个通过逗号分隔的整数列表。
– 不同于RANGE分区中定义的VALUES LESS THAN语句LIST分区使用VALUES IN因为每个分区的值是离散的因此只能定义值。

HASH分区
– HASH分区的目的是将数据均匀地分布到预先定义的各个分区中保证各分区的数据量大致都是一样的。在RANGE和LIST分区中必须明确指定一个给定的列值或列值集合应该保存在哪个分区中而在HASH分区中MySQL自动完成这些工作用户所要做的只是基于将要进行哈希分区的列值指定一个列值或表达式以及指定被分区的表将要被分隔成的分区数量。
– 要使用HASH分区来分割一个表要在CREATE TABLE 语句上添加一个“PARTITION BY HASH (expr)”子句其中“expr”是一个返回一个整数的表达式。它可以仅仅是字段类型为MySQL 整型的一列的名字。此外你很可能需要在后面再添加一个“PARTITIONS num”子句其中num是一个非负的整数它表示表将要被分割成分区的数量如果没有包括一个PARTITIONS子句那么分区的数量将默认为1。

3.3. 分区使用场景

一张表的查询速度已经慢到影响使用的时候
表中的数据是分段的
对数据的操作往往只涉及一部分数据而不是所有的数据
数据库比较多、并发不多可以采用表分区
数据量比较大、并发较高可以采用分库分表和分区相结合

3.4. 分表和分区的区别

实现方式
mysql的分表是真正的分表一张表分成很多表后每一个小表都是完正的一张表都对应三个文件MyISAM引擎一个.MYD数据文件.MYI索引文件.frm表结构文件。
数据处理
分表后数据都是存放在分表里总表只是一个外壳存取数据发生在一个一个的分表里面。分区则不存在分表的概念分区只不过把存放数据的文件分成了许多小块分区后的表还是一张表数据处理还是由自己来完成。
提高性能
分表后单表的并发能力提高了磁盘I/O性能也提高了。分区突破了磁盘I/O瓶颈想提高磁盘的读写能力来增加mysql性能。 在这一点上分区和分表的测重点不同分表重点是存取数据时如何提高mysql并发能力上而分区呢如何突破磁盘的读写能力从而达到提高mysql性能的目的。

实现的难易度
分表的方法有很多用merge来分表是最简单的一种方式。这种方式和分区难易度差不多并且对程序代码来说可以做到透明的。如果是用其他分表方式就比分区麻烦了。 分区实现是比较简单的建立分区表跟建平常的表没什么区别并且对代码端来说是透明的。

3.5. 分片策略

分片是把数据库横向扩展Scale Out到多个物理节点上的一种有效的方式。其主要目的是为突破单节点数据库服务器的 I/O 能力限制解决数据库扩展性问题。Shard这个词的意思是“碎片”。如果将一个数据库当作一块大玻璃将这块玻璃打碎那么每一小块都称为数据库的碎片DatabaseShard。将整个数据库打碎的过程就叫做分片可以翻译为分片。
形式上分片可以简单定义为将大数据库分布到多个物理节点上的一个分区方案。每一个分区包含数据库的某一部分称为一个片分区方式可以是任意的并不局限于传统的水平分区和垂直分区。一个分片可以包含多个表的内容甚至可以包含多个数据库实例中的内容。每个分片被放置在一个数据库服务器上。一个数据库服务器可以处理一个或多个分片的数据。系统中需要有服务器进行查询路由转发负责将查询转发到包含该查询所访问数据的分片或分片集合节点上去执行。

3.6. 分片和分区的区别

分片和分区有很多的相似之处。有的时候分片Sharding 也被近似等同于水平分区Horizontal Partitioning网上很多地方也用水平分区来指代 分片Sharding。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6