目录
一、什么是分库分表?
分库:一个数据库分成多个数据库,部署到不同机器。
分表:一个数据库表拆分成多个表。
二、为什么需要分库分表?
(1)单个表数据量太大,会极大影响 sql 执行的性能。一般来说,单表到几百万的时候,性能就会相对差一些了,这时候就得考虑分表。
(2)单个数据库一般最多支撑到两千并发,如果并发量太大,数据库可能会出现性能瓶颈,这时候就得考虑分库。
三、如何实现分库分表?
1. 实现方法
分库分表的拆分方式,可以是垂直拆分,也可以是水平拆分。
垂直分库:将原来一个单数据库的压力分担到不同的数据库,可以很好应对高并发场景。比如拆分成用户库、订单库、积分库、商品库,把它们部署在不同的数据库服务器。
垂直分表:将一些不常用的、数据较大或者长度较长的列拆分到另外一张表。比如用户表可以拆分成用户基本信息表、用户详细信息表。
水平分库:将表的数据拆分到不同的数据库服务器上,每个服务器具有相同的库和表,只是表中的数据集合不一样。可以有效的缓解单机单库的性能瓶颈和压力。
水平分表:将一个表的数据按照某种规则按数据表行拆分成多个表。可以解决单表数据量过大的问题。
水平拆分只能解决单表数据量大的问题,为了提升性能,我们通常会选择将拆分后的多张表放在不同的数据库中。也就是说,水平分表通常和水平分库同时出现。
水平拆分一般有以下几种策略:
-
range范围:按照特性的范围区间(比如时间区间、ID区间)来分配数据,比如 将 id 为 1~299999 的记录分到第一个库或表,300000~599999的分到第二个库或表。适合需要经常进行范围查找的场景,不太适合随机读写的场景。优点是利于扩容,历史数据不需要迁移;缺点是数据未被分散,容易出现热点数据的问题。
-
hash取模:求指定 key(比如 id) 的哈希,然后根据哈希值确定数据应被放置在哪个库或表中。适合随机读写的场景,不太适合经常需要范围查询的场景。优点是不会存在明显的热点问题;缺点是扩容迁移数据比较困难,历史数据需要迁移,重新计算分配到哪个库或表。
-
range+hash取模混合:将range范围和hash取模组合。
2. 中间件
比较常见的分库分表中间件包括:
- ShardingSphere:当当开源的,提供了 client 层方案 Sharding-jdbc 和 proxy 层的方案 Sharding-Proxy,支持的功能完善,除了支持分库分表和读写分离,还提供分布式 id 生成、分布式事务、数据库治理等功能。目前生态体系完善,社区活跃,文档完善,更新和发布比较频繁,使用的公司比较多,是当前分库分表的首选方案。
- Mycat:国内一批开源软件爱好者基于 Cobar 改造的,属于 proxy 层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是确实相比于 Sharding jdbc 来说,年轻一些,经历的锤炼少一些,生产上不推荐使用个人开源产品,遇到问题不好解决。
- Cobar:阿里 b2b 团队开发和开源的,属于 proxy 层方案,就是介于应用服务器和数据库服务器之间。应用程序通过 JDBC 驱动访问 Cobar 集群,Cobar 根据 SQL 和分库规则对 SQL 做分解,然后分发到 MySQL 集群不同的数据库实例上执行。早些年还可以用,但是最近几年都没更新了,基本没啥人用,差不多算是被抛弃的状态吧。而且不支持读写分离、存储过程、跨库 join 和分页等操作。
- TDDL:淘宝团队开发的,属于 client 层方案。支持基本的 crud 语法和读写分离,但不支持 join、多表查询等语法。目前使用的也不多,因为还依赖淘宝的 diamond 配置管理系统。
- Atlas:360 开源的,属于 proxy 层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区最新的维护都在 5 年前了。所以,现在用的公司基本也很少了。