01-分库分表应用场景

在互联网时代,随着业务数量的暴增和应用规模的不断扩大,无论是oracle还是mysql这样子的关系型数据库,都会面临服务器CPU、磁盘IO和内存的各种瓶颈问题。基于此情况,各个业务团队迫切需要一种数据分片的方案将业务数据量存储成本分摊到成本可控的各个普通数据库服务器上,数据库切分的方案便应运而生。

分库分表用于应对当前互联网常见的两个场景:

  1. 大数据
  2. 大并发

数据的切分方式

一般,线上系统的业务量不是很大,比如说单库的数据量在百万级别以下,那么MySQL的单库即可完成任何增/删/改/查的业务操作。随着业务的发展,单个DB中保存的数据量(用户、订单、计费明细和权限规则等数据)呈现指数级增长,那么各种业务处理操作都会面临单DB的IO读写瓶颈带来的性能问题。

通常进行两种拆分:

  1. 垂直拆分
  2. 水平拆分

垂直拆分

这时候,我们会考虑使用对之前的整个单DB采用垂直数据切分的方案,根据不同的业务类型划分库表,比如订单相关若干表放在订单库,用户相关的表放在用户库,账务明细相关的表放在账务库等。这样就将数据分担到了不同的库上,达到专库专用的效果。

image

使用垂直切分方案的主要优点如下:

  • 拆分后业务清晰,符合微服务的总体设计理念;
  • 子系统之间的整合与扩展相对容易;
  • 按照不同的业务类型,将不同的库表放在不同的数据库服务器上,便于管理;
  • 根据业务数据的“冷”、“热”状态,采用不同的缓存和数据库模式设计方案;

垂直切分的缺点如下:

  • 跨库的Join查询,需要使用不同子系统的API接口读取后在内存中完成关联查询,提高系统复杂度;
  • 如果某一种类型的业务呈现爆发式地增长,该业务对应的库表还是会存在单DB的IO读写的瓶颈问题,从这一点来说垂直切分并未从根本解决单库单表数据量过大的问题;
  • 存在跨库事务的一致性问题,解决起来比较麻烦,当然也可以采用分布式事务来解决;

水平拆分

与垂直切分对比,这里讲的水平切分不是将库表根据业务类型进行分类存储,而是将其按照数据表中某个字段或某几个字段的某种规则切分存储至多个DB中,在每个库每个表中所包含的只是其中的一部分数据,所有库表加起来的才是全量的业务数据。
image

这种对数据的切分方式,基本可以保证经过水平切分后的单库单表存储的容量不会太大,从而保证了对单表的增/删/改/查的SQL执行效率和处理能力。其中,数据的分片规则也是需要重点考虑的,因为它会使得数据分片在多个库表中是否均匀分布存储。然而,数据水平切分方案为业务系统带来福音的同时也给系统构建带来了一些值得思考的问题。

使用水平切分方案的主要优点如下:

  • 单库单表的数据容量可以维持在一个量级,有助于提高业务SQL的执行效率和系统性能;
  • 不管是利用ShardingJdbc组件还是MyCat框架,业务系统的应用层涉及改造得都较少,只需要根据实际的业务情况来设计数据分片的路由规则即可;
  • 可以提高业务系统的稳定性和负载能力;

使用水平切分方案的主要缺点如下:

  • 数据水平切分后,分布在多库多表中,跨库Join查询比较复杂;
  • 分片数据的一致性较为难保证;
  • 对于历史数据的迁移和数据库的扩容需要较大的维护工作量;
  • 分库 or 分表?

    关系型数据库在大于一定数据量的情况下检索性能会急剧下降。在面对互联网海量数据情况时,所有数据都存于一张表,显然会轻易超过数据库表可承受的数据量阀值。这个单表可承受的数据量阀值,需根据数据库和并发量的差异,通过实际测试获得。

单纯的分表虽然可以解决数据量过大导致检索变慢的问题,但无法解决过多并发请求访问同一个库,导致数据库响应变慢的问题。所以通常水平拆分都至少要采用分库的方式,用于一并解决大数据量和高并发的问题。这也是部分开源的分片数据库中间件只支持分库的原因。

但分表也有不可替代的适用场景。最常见的分表需求是事务问题。同在一个库则不需考虑分布式事务,善于使用同库不同表可有效避免分布式事务带来的麻烦。目前强一致性的分布式事务由于性能问题,导致使用起来并不一定比不分库分表快。目前采用最终一致性的柔性事务居多。分表的另一个存在的理由是,过多的数据库实例不利于运维管理。综上所述,最佳实践是合理地配合使用分库+分表。

数据库中间件产品

  • Sharding-JDBC
  • Mycat

两者底层设计理念不同!

Mycat 是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库。

Sharding-JDBC目前是基于jdbc驱动,无需额外的proxy,因此也无需关注proxy本身的高可用,以后会开篇重点介绍。