0 基本概念
0.1 Sharding
Sharding 是把数据库横向扩展(Scale Out)到多个物理节点上的一种有效的方式,其主要目的是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。
Shard这个词的意思是“碎片”。如果将一个数据库当作一块大玻璃,将这块玻璃打碎,那么每一小块都称为数据库的碎片(DatabaseShard)。将整个数据库打碎的过程就叫做sharding,翻译为分片。
形式上,Sharding可以简单定义为将大数据库分布到多个物理节点上的一个分区方案。
每一个分区包含数据库的某一部分,称为一个shard,分区方式可以是任意的,并不局限于传统的水平分区和垂直分区。
一个shard可以包含多个表的内容甚至可以包含多个数据库实例中的内容。每个shard被放置在一个数据库服务器上。一个数据库服务器可以处理一个或多个shard的数据。系统中需要有服务器进行查询路由转发,负责将查询转发到包含该查询所访问数据的shard或shards节点上去执行。
0.2 Scale Out/Scale Up 和 垂直切分/水平拆分
0.2.1 MySQL的扩展方案
包括Scale Out和Scale Up
Scale Out(横向扩展)是指Application可以在水平方向上扩展
一般对数据中心的应用而言,Scale out指的是当添加更多的机器时,应用仍然可以很好的利用这些机器的资源来提升自己的效率从而达到很好的扩展性Scale Up(纵向扩展)是指Application可以在垂直方向上扩展
一般对单台机器而言,Scale Up值得是当某个计算节点(机器)添加更多的CPU Cores,存储设备,使用更大的内存时,应用可以很充分的利用这些资源来提升自己的效率从而达到很好的扩展性
0.2.2 MySQL的Sharding策略
包括垂直切分和水平切分
垂直(纵向)拆分:按功能模块拆分,以解决表与表之间的I/O竞争
比如分为订单库、商品库、用户库...这种方式多个数据库之间的表结构不同水平(横向)拆分:将
同一个表
的数据进行分块保存到不同的数据库中
来解决单表中数据量增长出现的压力。这些数据库中的表结构完全相同
表结构设计
垂直切分
常见的一些场景包括
a). 大字段的垂直切分
单独将大字段建在另外的表中,提高基础表的访问性能,原则上在性能关键的应用中应当避免数据库的大字段
b). 按照使用用途垂直切分
例如企业物料属性,可以按照基本属性、销售属性、采购属性、生产制造属性、财务会计属性等用途垂直切分
c). 按照访问频率垂直切分
例如电子商务、Web 2.0系统中,如果用户属性设置非常多,可以将基本、使用频繁的属性和不常用的属性垂直切分开水平切分
常见的一些场景包括
a). 比如在线电子商务网站,订单表数据量过大,按照年度、月度水平切分
b). Web 2.0网站注册用户、在线活跃用户过多,按照用户ID范围等方式,将相关用户以及该用户紧密关联的表做水平切分
c). 例如论坛的置顶帖子,因为涉及到分页问题,每页都需要显示置顶贴,这种情况可以把置顶贴水平切分开来,避免取置顶帖子时从所有帖子的表中读取
0.3 分表特点
1 实现方式上
MySQL的分表是真正的分表,一张表分成很多表后,每一个小表都是完整的一张表,都对应三个文件(MyISAM引擎:一个.MYD数据文件,.MYI索引文件,.frm表结构文件)
2 数据处理上
分表后数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面
3 提高性能上
分表后,单表的并发能力提高了,磁盘I/O性能也提高了
分表重点是存取数据时,如何提高 MySQL并发能力上
4 实现的难易度上
分表的方法有很多,用merge来分表,是最简单的一种方式。对程序代码来说可以做到透明的
分表的适用场景
一张表的查询速度已经慢到影响使用
当频繁插入或者联合查询时,速度变慢
分表的实现需要业务结合实现和迁移,较为复杂
1 分表和分库
分表能够解决单表数据量过大带来的查询效率下降
的问题,但是,却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问,当数据库master服务器无法承载写操作压力时,不管如何扩展slave服务器,此时都没有意义了。
因此,我们必须换一种思路,对数据库进行拆分,从而提高数据库写入能力
,这就是所谓的分库
与分表策略相似,分库可以采用通过一个关键字取模的方式,来对数据访问进行路由,如下图所示
1分库分表的几种形式
把一个实例中的多个数据库拆分到不同的实例
以后有的节点还是无法负担写负载
把一个库中的表分离到不同的数据库中
终极大招水平拆分!即分片处理(通常所说的分库分表即此)
不同于MySQL的分区表是在同一个节点中的同一个数据库建立的
而分片后通常是存在不同的物理节点上
由于技术难度极高,难以维护,情非得已,谨慎操作
2分片前的准备
对一个库中的相关表进行水平拆分到不同实例的数据库中
选择分区键
尽量避免跨分区查询的发生(无法完全避免)
尽量使各个分片中的数据平均
存储无需分片的表
每个分片中存储一份相同的数据
对于数据量不大且并不经常被更新的字典类表,经常需要和分区表一起关联查询,每个分片中存储一份冗余的数据可以更好提高查询效率,维护其一致性就很重要了使用额外的节点统一储存
没有冗余问题,但是查询效率较差,需要汇总
在节点上部署分片
每个分片使用单一数据库,并且数据库名也相同
结构也保持相同,和单一节点时的一致将多个分片表存储在一个数据库中,并在表名上加入分片号后缀
在一个节点中部署多个数据库,每个数据库包含一个切片
分配分片中的数据
期望尽量平均分配
按分区键的Hash值取模来分配分片数据
可以相对平均的分配数据,但是难以人为控制江苏数据分配到哪个分片中按分区键的范围来分配分片数据
常用于分区键为日期或数值类型,可以清楚知道数据被分配到哪个分片中,但易产生分配不均及访问量不均
利用分区键和分片的映射表来分配分片数据
前面两种都无人发灵活地控制哪些数据存储在哪些分片中于是有此法
可使用缓存方式读写 映射表,防止成为数据库瓶颈
生成全局唯一ID
使用
auto_increment_increment
和auto_increment_offset
服务器变量让MySQL以期望的值和偏移量来增加auto_increment
列的值
方法简单,不依赖于某节点,比较普遍采用但需要非常仔细的配置服务器,不适用于一个节点包含多个分区表情况使用全局节点来生成ID
在一个全局数据库节点中创建一个包含auto_increment
列的表,APP通过该表生成唯一数字,但该表易成为系统瓶颈在Redis等缓存nosql服务器中创建全局ID
避免了MySQL性能低的问题
分库分表存在的问题
1 事务问题。
在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
2 跨库跨表的join问题
在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,这时,表的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。
3 额外的数据管理负担和数据运算压力。
额外的数据管理负担,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算,例如,对于一个记录用户成绩的用户数据表userTable,业务要求查出成绩最好的100位,在进行分表之前,只需一个order by语句就可以搞定,但是在进行分表之后,将需要n个order by语句,分别查出每一个分表的前100名用户数据,然后再对这些数据进行合并计算,才能得出结果。
解决方案
使用类似JTA提供的分布式事务机制
作者:芥末无疆sss
链接:https://www.jianshu.com/p/d4e8804b52b9
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章