文章目录
- 生猛干货
- 官方文档
- 主从复制 解决不了 主节点DB写的的压力
- 常见的分库分表的方式
- 分库
- 分表
- DB分片前的准备
- 如何选择分区键 ,尽量避免跨分片查询
- 如何存储无需分片的表
- 如何在节点上部署分片
- 如何分配分片中的数据
- 如何生成全局唯一ID
- 使用oneProxyp 分库分表演示
- 目标效果
- oneProxyp
- 简介
- 下载安装使用
- 搞定MySQL
生猛干货
带你搞定MySQL实战,轻松对应海量业务处理及高并发需求,从容应对大场面试
官方文档
https://dev.mysql.com/doc/
如果英文不好的话,可以参考 searchdoc 翻译的中文版本
http://www.searchdoc.cn/rdbms/mysql/dev.mysql.com/doc/refman/5.7/en/index.com.coder114.cn.html
主从复制 解决不了 主节点DB写的的压力
我们前面的 主从复制 构建的高可用的架构中,主要解决的是 主节点 读的压力。 (通常情况下,一个系统中的读请求占据绝大部分)
那主节点的 写请求呢? — 主从复制高可用架构解决不了了。。。。。
当然了,你可以增加硬件配置,这里我们不讨论。我们这里要讨论的是 通过分库分表 来解决 主节点 写的压力。
常见的分库分表的方式
有个MySQL的集群哈
分库
两种方式,如下
方式一: 把一个实例中的多个数据库拆分到不同的实例
假设我们是个电商系统, DB集群中有 订单、用户、促销 三个数据库。
当然了,如果你的情况是: 订单节点的写入压力比较大,你这样拆也解决不了问题。
那就需要第二种方式了
- 方式二: 把一个库中的表分离到不同的数据库中 。
原来写的压力 都在 一个节点上,这样才到不同的数据库上,原来一个节点的写压力,就被分散到了3个节点上。
如果 随着业务的发展,订单的DB 写压力 又扛不住了呢? -----------> 那只有终极大招-----> 分表
分表
分表 : 就是对一个库中的相关表 进行水平拆分到不同实例的数据库中。
这一块很复杂,坑太多。。。。。 一句话,能不分就不分。
举个订单的表的分表后的例子。
DB分片前的准备
如何选择分区键 ,尽量避免跨分片查询
分区键要能尽量避免跨分片查询的发生 ,
举个例子,博客系统 ,如果我们按照博客id hash进行分片,那么这个blog_id 会分配到各个节点上,那么查询某个用户的博客, 不得不去所有的数据库上去查询。 但如果按照user_id分呢? 那只要查询一个数据库就可以了。 就避免了跨分区的查询
分区键要尽可能的使各个分配片中数据平均
分片的目的,是为了降低数据库的写负载,如果分片不均匀,大部分数据都写到一个节点上了,这个节点很累,其他节点闲的没事儿,那么这个分片还有啥意义???
比较好的方式,如果 分完以后,你的查询能包含这个分区键,那就非常好了。
如何存储无需分片的表
一个库中,大部分的表,是没有必要分片的,只有几个写入非常频繁的表,才需要分片。
那不用分片的如何存储呢?
每个分片中存储一份相同的数据
这种方法通常用于: 表本身数据量不大,而且不怎么变更的表,比如字典表。 查询也经常关联这种表,每个分片都有的话,这样的话 就不用跨分片查询了,提高查询效率。
当然了,缺点要维护多个分片的一致性,避免不一致导致查询出错。
使用额外的节点统一存储
需要查询的话,由应用来分别查询,然后组合了。 效率不如第一种,但好在不用去维护数据一致性。
如何在节点上部署分片
方式一: 每个分片使用单一的数据库,并且数据库名也相同
方式二: 将多个分片表存储在一个数据库中,并在表名上加入分片号后缀
这个是对表进行编号方式三: 在一个节点中部署多个数据库,每个数据库包含一个分片
这个是对数据库进行编号
其他方式。。。。
如何分配分片中的数据
数据如何分布,对查询的性能,影响很大。
这个平均包括 : 数据分部平均,第二 并发访问也要平均
方式一: 按照分区键的hash值取模来分配分片数据
先hash再取模, 并不是所有的分区键都是数字,所以最好hash一下
如果是自增id为主键,也可以不用hash, 直接取模就行。
举个例子 10个分片, 101 这个该存在哪个分片呢 ?
101 % 10 = 1 ----> 第一个分分片 。
方式二: 按照分区键的范围来分配数据
举个例子 10个分片 ,第一个分片存 1 - 100 ,第二个 101 -199 依次类推
那101 放哪里呢 ----> 第二个分片
常用于 分区键为 日期类型或者数值类型的场景。
优点: 很容易知道放哪里
缺点: 容易造成数据的分配不平均 ,从而导致访问也不平均。
比如一个 在线题库,以 课程id作为分区键来分区, 但是Java这个课,大家都爱选这个,导致运行一段时间后,java课程的那个分片,压力特别大,所以前期设计要充分考量。
方式三:利用分区键和分片的映射表来分配分片数据
使用第三种方式,方便控制
需要建立一张 分区键和分片的映射表, 先通过查询映射表 来查询具体的分区。
这个表的压力比较大, 记得做缓存。
如何生成全局唯一ID
这个可能是最关键的了
方式一: 单节点的话,可以采用auto_increament_increament和 auto_increament_offset 参数
方式二: 分片的话 ,也可以用 可以采用auto_increament_increament和 auto_increament_offset 参数
auto_increament_increament 和 分片数目相同
比如 6个节点, auto_increament_increament 就要设置为6 ,auto_increament_offset 分别设置为 1到 6 ,每个节点相同表的自增id ,不冲突。
但这个只适用于 一个节点 只有一套分片表的情况。
方式二:全局节点
弄个全局表 ,但这个表有可能成为瓶颈,所以引入第三种
方式三: 使用redis代替全局节点,Redis缓存服务器中创建全局ID
其他方式。。。。
使用oneProxyp 分库分表演示
目标效果
解释下
原来在一个节点中存储了 订单表 + 订单商品表 + 分类表
经过分库分表后
两个节点
节点1 : 存储 订单表 01 + 订单商品表 01 + 分类表 (每个节点数据一致,冗余)
节点1 : 存储 订单表 02 + 订单商品表 02 + 分类表 (每个节点数据一致,冗余)
oneProxyp
简介
OneProxy 中间件是具备透明读写分离、分库分表功能的数据库中间件,轻松构建分布式数据库集群,支持Oracle/MySQL等多种数据库
下载安装使用
带后续使用的话补充,这里有个思路即可。
链接:https://pan.baidu.com/s/15kdQ-Q2u1sT063A-Qa2tdg
提取码:pbp9