读写分离主要应对的是数据库读并发,没有解决数据库存储问题。
如果MySQL一张表的数据量过大怎么办?换而言之,我们如何解决MySQL的存储压力?
解决方案:分库分表
分库 就是将数据库中的数据分散到不同的数据库上。
下面这些操作都涉及到了分库:
分表 就是对单表的数据进行拆分,可以是垂直拆分,也可以是水平拆分。
简单来说,垂直拆分是对数据表列的拆分,把一张列比较多的表拆分为多张表。
举个例子:我们可以将用户信息表中的一些列单独抽出来作为一个表。
简单来说,水平拆分是对数据表行的拆分,把一张行比较多的表拆分为多张表。
举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。
《从零开始学架构》 (opens new window) 中的有一张图片对于垂直拆分和水平拆分的描述还挺直观的。
遇到下面几种场景可以考虑分库分表:
记住,你在公司做的任何技术决策,不光是要考虑这个技术能不能满足我们的要求,是否适合当前业务场景,还要重点考虑其带来的成本。
引入分库分表之后,会给系统带来什么挑战呢?
另外,引入分库分表之后,一般需要 DBA 的参与,同时还需要更多的数据库服务器,这些都属于成本。
ShardingSphere 项目(包括 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar)是当当捐入 Apache 的,目前主要由京东数科的一些巨佬维护。
ShardingSphere 绝对可以说是当前分库分表的首选!ShardingSphere 的功能完善,除了支持读写分离和分库分表,还提供分布式事务、数据库治理等功能。
另外,ShardingSphere 的生态体系完善,社区活跃,文档完善,更新和发布比较频繁。
艿艿之前写了一篇分库分表的实战文章,各位朋友可以看看:《芋道 Spring Boot 分库分表入门》 (opens new window) 。
分库分表之后,我们如何将老库(单库单表)的数据迁移到新库(分库分表后的数据库系统)呢?
比较简单同时也是非常常用的方案就是停机迁移,写个脚本老库的数据写到新库中。比如你在凌晨 2 点,系统使用的人数非常少的时候,挂一个公告说系统要维护升级预计 1 小时。然后,你写一个脚本将老库的数据都同步到新库中。
如果你不想停机迁移数据的话,也可以考虑双写方案。双写方案是针对那种不能停机迁移的场景,实现起来要稍微麻烦一些。具体原理是这样的:
想要在项目中实施双写还是比较麻烦的,很容易会出现问题。我们可以借助上面提到的数据库同步工具 Canal 做增量数据迁移(还是依赖 binlog,开发和维护成本较低)。