高并发情况下MySql面对亿级流量如何力挽狂澜?
1.单库到多库的变革是为什么?分库分表是什么?
为什么分库?
遇到性能瓶颈
MySql最大连接数为16384(但是没有这样的机器支持mysql性能全开) 一般mysql安装默认最大连接数为100 线上环境一般扩展至500
程序的每次请求都需要一个连接(Conection) 假设MySQL有同时处理500请求的能力,但是现在有1000流量(QPS)进来,那么就会有500个请求等待获取连接,一般应用请求有峰值和低估之分,但是如TB双11情况下,请求一直在峰值,长久下去,会造成大量的请求堆积,就会拖垮服务器,导致宕机
提高查询速度
Mysql数据都存储在磁盘中,假设现在有一张表有5000W的数据,每次检索数据都是一次磁盘IO,虽然可以通过索引优化连接速度,但是Mysql索引结构为B+Tree,索引一样是存储在磁盘中,数据量过大会导致tree树高过高(每一次树高在检索时会进行一次磁盘IO),磁盘IO次数高,会导致查询速度慢
数据量
数据库数据过多,一般是数据库运行很久了,这样肯定是部分数据库表数据量大,数据基数大,查询速度慢,造成请求堆积,服务宕机
总结. 类似于Nginx服务转发
2.多维的业务场景&不同的性能瓶颈应该如何拆分?
分库
垂直分库: 不同属性的sql并发,一般按照功能进行库的划分。例如一个商场,用户一个库,商品一个库,订单一个库…不同的请求进根据自己的属性进不同的库查询。
水平分库: 假设2000QPS中有1800去请求订单库,但是当前分库后订单库连接数还是在500。 此时需要将订单库进行扩展,建立多个相同结构的订单库,对数据进行均摊。以缓解单库的压力
分表
分表方式,分为水平分表和垂直分表
垂直分表:(减少查询次数)Mysql在查询之后会将数据丢入Mysql缓存中,以便下次查询能够直接命中数据,不需要扫描库,减少查询时间。但是即使每次只查询了少量字段,MySQL还是会将整行数据丢入缓存中,而缓存是有大小的,列过多,缓存的数据越少。,命中次数就会越少,查询速度就会越慢。而垂直分表,将热字段和冷字段分离之后,缓存中能够存放的记录数就会越多,查询的命中次数增加,就可以减少查询时间。 垂直分表之后通过外键链接两条数据
水平分表: 数据行过多,引起性能瓶颈,一般是单表数据量增长过快,在某个节点,创建另外一张结构相同的表
分表的前提在整个数据库没有遇到性能瓶颈的情况
3.(技术有风险)引入分库分表后产生的问题剖析
表: 订单库,库存库
垂直分库会产生的问题
- 事务
例: 下订单,加订单 -> 减库存 单库添加数据就可以了1
2
3
4
5
6
7
8@Transition
Methods
try{
成功
commit
}catch(Exception e){
rollback
}
解决方式:
- 1PC
待补充
- XA
待补充
- 2PC
待补充
- 3PC
待补充
- TCC
待补充
- MQ(分布式事务)
待补充
- 远程表
待补充
- 广播表
待补充
- 连表查询(join)
解决方式- 在客户端做数据组合
字段冗余 表冗余例: 先查用户信息,再查订单信息 组合
- 在客户端做数据组合
水平分库会产生的问题
分页
例: 分页且按照订单金额排序怎么办?- 并行查询,第一页,每页10条,三个库分别查询前十条返回三十条数据,然后筛选出前十条数据。但是返回的数据一旦过多会出现问题。
- 提前做数据聚合,丢入nosql,定时同步,不能保证数据的实时性
聚合函数
count(1)查询全部数据库,最后做数据汇总
ID唯一性
- 第三方生成
- Redis incr (Redis Incr 命令将 key 中储存的数字值增一)
- uuid (会影响效率)
- 主键步长 db1: 1,3,5,7 db2: 2,4,6,8 一旦添加了新的库,数据主键需要全部改变
- 特殊算法生成: 雪花…
hbase + flive + 实时风控
分库分表之后程序应该如何去访问?
编码层 –> AbstracRoutingDataSource()
1
2
3
4
5if(id < 10000){
conn db1
}else if(id > 10000 && id < 20000 ){
conn db2
} ...灵活的数据源切换,但是代码臃肿
框架层 –> Mybatis Interceptor接口
驱动层 –> Sharding JDBC
代理层 –> MyCat(类似NG,统一管理,请求分发) 详情
服务层 –> SQL特殊版本支持
4.驱动层Sharding-JDBC实战
5.当MySql单库扛不住一定要分库分表吗?
6.分库分表经典面试题深入浅出
收获
- 我们要知道为什么这样做。 知其然,知其所以然
- begin connit rollback