一台数据库服务器能够承受多大的并发量,数据量,受内外两方面因素影响。
搞清楚需要估算的数据库服务器是什么配置:
- 确定数据库是MySQL还是Oracle或者其他的DB2/postgreSQL
- CPU是几核,现代数据库应用都充分的运用了多核CPU的并行处理能力
- 内存大小,数据库的索引数据,缓存数据都存放在内存中
- 磁盘io能力,数据库文件都存储在磁盘上面,所有磁盘的io能力是影响数据库性能的直接因素
- 网络带宽: 网络的上行和下行带宽,数据库服务器可支持的最大连接数是多少
做数据库并发量最好的方法就是压力测试:
- QPS: 数据库每秒处理的查询书
- TPS: 每秒处理的事务数量
- IOPS: 每秒磁盘进行IO的操作次数
一般来说电商的日订单都是百千万级别,小小的数据库肯定是撑不住的,这个时候可以考虑分库分表了。
国内一般大厂的规则参考:
- 单表500万记录,正常水平
- 800万条警戒线
- 1000万条必须进行分库分表
1500qps
当数据库产生性能瓶颈,CPU瓶颈和IO瓶颈。
两种瓶颈最终都会导致数据库的活跃连接数增加,继而达到数据库课程时的最大活跃连接阈值,终会导致应用服务无连接可用,造成灾难性的后果。
可以先从代码,sql,索引几方面进行优化,这几方面优化没有什么空间的情况下,在进行分库分表。
- 磁盘读IO瓶颈
由于热点数据太多,数据库缓存完全放不下,查询时会产生大量的磁盘IO,查询素的会比较满,这样会导致产生大量的活跃连接,最终可能会发展成无链接可用的后果。 可以采用一主多从,读写分离的方式,用多个从库分摊查询流量,或者采用分库+水平分表(把一张表的数据拆成多张表来存放,比如订单表可以按照user_id来拆分)的方案。
- 磁盘写IO瓶颈
由于数据库写入频繁,会产生频繁的磁盘写入IO操作,频繁的磁盘iO操作导致产生大量的活跃连接,最终同样会发展成无连接可用的后果。 这是只能采用分库方案,用多个库来分摊写入压力。再加上水平分表的策略,分表后,单表存储的数量会更小,插入数据是索引查找和封信的成功成本会更低,插入速度自然会更快。
- SQL问题
如果SQL中包含join,grouy by, order by ,非索引字段条件查询等增加CPU运算的操作,会对CPU产生明显的压力,这是可以考虑SQL优化,创建适当的索引,也可以把一些计算量大的SQL逻辑放到应用中处理。
- 单表数据量太大。
由于单张数据表量过大,比如超过1000万,查询是便利树的层次太深或者扫描的行太多,SQL效率会很低,也会非常消耗CPU,这时可以按照业务场景水平分表。
场景 | 分库分表前 | 分库分表后 |
---|---|---|
并发支撑情况 | MySQL单机部署,扛不住高并发 | MySQL从单机到多实例,能承受的并发增加了多倍 |
磁盘使用情况 | MySQL单机磁盘容量几乎盛满 | 拆分为多个数据库,数据库服务器磁盘使用率大大降级 |
SQL执行性能 | 单表数据量太大,SQL越跑越慢 | 单表数据量减少,SQL执行效率明显提升 |
就是把一张表的数据分到多张表中,表的结构都是一样的,只不过每张表的数据都是不同的,这些表加起来的数据组成分表前那张大表的数据。
水平拆分的意义,就是将数据均匀的放到更多的库中,然后用多个库来抗更高的并发,还有就是用多个库的存储容量来进行扩容。
目标 从扩容角度,提高并发能力
水平拆分一般是分库和分表的结合,水平拆分就是让每个表的row数量控制在一定的范围内,保证sql的性能。
否则,单表数据量太大,SQL性能就会比较差,一般是500万行左右,SQL越复杂,就最好让单表的行数越少
垂直拆分就是把一个有很多字段的表拆分成多个表, 每个表的数据结构都不一样,每个库表包含部分字段,一般来说,会将较少访问频率很高的字段方法放到一张表中,然后将较多的访问频率很低的字段放到另一张表中。
因为数据库是有缓存的,访问频率高的字段越少,就可以在缓存中缓存更多的行,性能也就越好
数据分片主要的方式:
一种是按照range来分,就是每个库一段连续的数据,这个一般是按照时间范围来的。但是这种一般较少使用,因为很容易发生数据倾斜,发量流量都打在最新的数据上。
一般是按照某个字段hash一下,分到不同的表中,均匀分散。 hash分发,好处在于说,可以平均分配在每个库的数据量和请求压力。
但是这种方式的扩容比较麻烦,会有一个数据迁移的过程,之前的数据需要重新计算hash值重新分配到不同的库或者表
这种分片规则将数据分成n份,从而将数据均匀的分配在各个表中,或者各个节点上,扩容方便。
表的数量规划
即便按照每天100万,2年内保持稳定的要求,进行表的数据量的规划。
2年数据量总量是7.3亿, 假设没涨表的标准值是500万,表的数据量平均是146张。换成2的幂,比较接近128张。 或者说,中表(570万)也是可以接受的,所有就按照128张规划。
库的数量规划
即使按照qps峰值5万的要求,进行数据库的规划。
每个库正常承载的写入并发量是1500,那么8个库就可以承载 8 * 1500 = 12000的写并发
悲观一点,如果每秒写入超过5万qps,可以通过MQ削峰+批写入的降级策略,MQ的写入吞吐量可以轻松达到10万级别
总的规划
采用 16 * 8 来分库分表,即使用8个库, 每个库16张表,也就是128张表,根据某个id先路由到某个库上面,然后在路由到具体的表上面。