Skip to content

Latest commit

 

History

History
165 lines (78 loc) · 6.68 KB

81.亿级架构核心:存储架构——亿级库表的架构设计.md

File metadata and controls

165 lines (78 loc) · 6.68 KB

亿级架构核心:存储架构——亿级库表的架构设计

数据库服务器的参考能力

一台数据库服务器能够承受多大的并发量,数据量,受内外两方面因素影响。

内在因素

搞清楚需要估算的数据库服务器是什么配置:

  1. 确定数据库是MySQL还是Oracle或者其他的DB2/postgreSQL
  2. CPU是几核,现代数据库应用都充分的运用了多核CPU的并行处理能力
  3. 内存大小,数据库的索引数据,缓存数据都存放在内存中
  4. 磁盘io能力,数据库文件都存储在磁盘上面,所有磁盘的io能力是影响数据库性能的直接因素
  5. 网络带宽: 网络的上行和下行带宽,数据库服务器可支持的最大连接数是多少

外在因素

做数据库并发量最好的方法就是压力测试:

  • QPS: 数据库每秒处理的查询书
  • TPS: 每秒处理的事务数量
  • IOPS: 每秒磁盘进行IO的操作次数

业界单表的参考量

一般来说电商的日订单都是百千万级别,小小的数据库肯定是撑不住的,这个时候可以考虑分库分表了。

国内一般大厂的规则参考:

  1. 单表500万记录,正常水平
  2. 800万条警戒线
  3. 1000万条必须进行分库分表

单库的流量峰值并发能力

1500qps

为什么需要分库分表?

当数据库产生性能瓶颈,CPU瓶颈和IO瓶颈。

两种瓶颈最终都会导致数据库的活跃连接数增加,继而达到数据库课程时的最大活跃连接阈值,终会导致应用服务无连接可用,造成灾难性的后果。

可以先从代码,sql,索引几方面进行优化,这几方面优化没有什么空间的情况下,在进行分库分表。

IO瓶颈

  • 磁盘读IO瓶颈

由于热点数据太多,数据库缓存完全放不下,查询时会产生大量的磁盘IO,查询素的会比较满,这样会导致产生大量的活跃连接,最终可能会发展成无链接可用的后果。 可以采用一主多从,读写分离的方式,用多个从库分摊查询流量,或者采用分库+水平分表(把一张表的数据拆成多张表来存放,比如订单表可以按照user_id来拆分)的方案。

  • 磁盘写IO瓶颈

由于数据库写入频繁,会产生频繁的磁盘写入IO操作,频繁的磁盘iO操作导致产生大量的活跃连接,最终同样会发展成无连接可用的后果。 这是只能采用分库方案,用多个库来分摊写入压力。再加上水平分表的策略,分表后,单表存储的数量会更小,插入数据是索引查找和封信的成功成本会更低,插入速度自然会更快。

CPU瓶颈

  • 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

一种是按照range来分,就是每个库一段连续的数据,这个一般是按照时间范围来的。但是这种一般较少使用,因为很容易发生数据倾斜,发量流量都打在最新的数据上。

hash分片

一般是按照某个字段hash一下,分到不同的表中,均匀分散。 hash分发,好处在于说,可以平均分配在每个库的数据量和请求压力。

但是这种方式的扩容比较麻烦,会有一个数据迁移的过程,之前的数据需要重新计算hash值重新分配到不同的库或者表

id取模

这种分片规则将数据分成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先路由到某个库上面,然后在路由到具体的表上面。