MySQL数据库分库分表

为什么要分库分表

关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。切分的目的就在于减少数据库的负担,缩短查询时间。

数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位、整合。数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性能的目的。数据切分根据其切分类型,可以分为两种方式:垂直(纵向)切分和水平(横向)切分。

数据库的瓶颈

1、IO瓶颈

磁盘读IO瓶颈,热点数据太多,数据库缓存放不下,每次查询时会产生大量的IO,降低查询速度 -> 分库和垂直分表。第二种:网络IO瓶颈,请求的数据太多,网络带宽不够 -> 分库。
2、CPU瓶颈

SQL问题,如SQL中包含join,group by,order by,非索引字段条件查询等,增加CPU运算的操作 -> SQL优化,建立合适的索引,在业务Service层进行业务计算。第二种:单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率先出现瓶颈 -> 水平分表。

分库分表

水平分库

概念:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。结果:

  • 每个库的结构都一样;
  • 每个库的数据都不一样,没有交集;
  • 所有库的并集是全量数据

场景:系统绝对并发量上来了,分表难以根本上解决问题,并且还没有明显的业务归属来垂直分库。分析:库多了,io和cpu的压力自然可以成倍缓解。

MySQL数据库分库分表_第1张图片
水平切分后同一张表会出现在多个数据库/表中,每个库/表的内容不同。

水平分表

概念:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。结果:

  • 每个表的结构都一样;
  • 每个表的数据都不一样,没有交集;
  • 所有表的并集是全量数据。

场景:系统绝对并发量并没有上来,只是单表的数据量太多,影响了SQL效率,加重了CPU负担,以至于成为瓶颈。分析:表的数据量少了,单次SQL执行效率高,自然减轻了CPU的负担。

MySQL数据库分库分表_第2张图片
水平切分的优点:

  • 不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力;
  • 应用端改造较小,不需要拆分业务模块。

缺点:

  • 跨分片的事务一致性难以保证;
  • 跨库的join关联查询性能较差;
  • 数据多次扩展难度和维护量极大。

垂直分库

概念:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。结果:

  • 每个表的结构都一样;
  • 每个表的数据都不一样,没有交集;
  • 所有表的并集是全量数据;

场景:系统绝对并发量并没有上来,只是单表的数据量太多,影响了SQL效率,加重了CPU负担,以至于成为瓶颈。分析:表的数据量少了,单次SQL执行效率高,自然减轻了CPU的负担。

MySQL数据库分库分表_第3张图片

垂直分表

概念:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
结果

  • 每个表的结构都不一样;
  • 每个表的数据也不一样,一般来说,每个表的字段至少有一列交集,一般是主键,用于关联数据;
  • 所有表的并集是全量数据;

场景:系统绝对并发量并没有上来,表的记录并不多,但是字段多,并且热点数据和非热点数据在一起,单行数据所需的存储空间较大。以至于数据库缓存的数据行减少,查询时会去读磁盘数据产生大量的随机读IO,产生IO瓶颈。分析:可以用列表页和详情页来帮助理解。垂直分表的拆分原则是将热点数据(可能会冗余经常一起查询的数据)放在一起作为主表,非热点数据放在一起作为扩展表。这样更多的热点数据就能被缓存下来,进而减少了随机读IO。拆了之后,要想获得全部数据就需要关联两个表来取数据。但记住,千万别用join,因为join不仅会增加CPU负担并且会讲两个表耦合在一起(必须在一个数据库实例上)。关联数据,应该在业务Service层做文章,分别获取主表和扩展表数据然后用关联字段关联得到全部数据。

垂直切分的优点:

  • 解决业务系统层面的耦合,业务清晰;
  • 与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等;
  • 高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈。

缺点:

  • 部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度;
  • 分布式事务处理复杂;
  • 依然存在单表数据量过大的问题(需要水平切分)。

分库分表工具

  • sharding-sphere:jar,前身是sharding-jdbc;
  • TDDL:jar,Taobao Distribute Data Layer;
  • Mycat:中间件。

分库分表的问题

非partition key的查询问题

基于水平分库分表,拆分策略为常用的hash法。

端上除了partition key只有一个非partition key作为条件查询。

映射法

MySQL数据库分库分表_第4张图片

基因法

MySQL数据库分库分表_第5张图片

写入时,基因法生成user_id,如图。关于xbit基因,例如要分8张表,23=8,故x取3,即3bit基因。根据user_id查询时可直接取模路由到对应的分库或分表。
根据user_name查询时,先通过user_name_code生成函数生成user_name_code再对其取模路由到对应的分库或分表。id生成常用snowflake算法。

端上除了partition key不止一个非partition key作为条件查询。

映射法

MySQL数据库分库分表_第6张图片

冗余法

MySQL数据库分库分表_第7张图片

后台除了partition key还有各种非partition key组合条件查询。

NoSQL法

MySQL数据库分库分表_第8张图片

冗余法

MySQL数据库分库分表_第9张图片

非partition key跨库跨表分页查询问题

基于水平分库分表,拆分策略为常用的hash法。

注:用NoSQL法解决(ES等)。

扩容问题

基于水平分库分表,拆分策略为常用的hash法。

  • 水平扩容库(升级从库法),扩容是成倍的。
  • 水平扩容表(双写迁移法),双写是通用方案。

你可能感兴趣的:(微服务,数据库,mysql,分布式)