在实际开发中,数据库的扩容和不同的分库分表规则直接相关,今天我们从系统设计的角度,抽象了一个项目开发中出现的业务场景,从数据库设计、路由规则,以及数据迁移方案的角度进行讨论。
从业务场景出发进行讨论
假设这样一个业务场景,现在要设计电商网站的订单数据库模块,经过对业务增长的估算,预估三年后,数据规模可能达到 6000 万,每日订单数会超过 10 万。
首先选择 存储实现,订单作为电商业务的核心数据,应该尽量避免数据丢失,并且对数据一致性有强要求,肯定是选择支持事务的关系型数据库,比如使用 MySQL 及 InnoDB 存储引擎。
然后是 数据库的高可用,订单数据是典型读多写少的数据,不仅要面向消费者端的读请求,内部也有很多上下游关联的业务模块在调用,针对订单进行数据查询的调用量会非常大。基于这一点,我们在业务中配置基于主从复制的读写分离,并且设置多个从库,提高数据安全。
最后是 数据规模,6000 万的数据量,显然超出了单表的承受范围,参考《阿里巴巴 Java 开发手册》中「单表行数超过 500 万行」进行分表的建议,此时需要考虑进行分库分表,那么如何设计路由规则和拆分方案呢?接下来会对此展开讨论。
路由规则与扩容方案
现在我们考虑 3 种路由规则:对主键进行哈希取模、基于数据范围进行路由、结合哈希和数据范围的分库分表规则。
1. 哈希取模的方式
哈希取模是分库分表中最常见的一种方案,也就是根据不同的业务主键输入,对数据库进行取模,得到插入数据的位置。
6000 万的数据规模,我们按照单表承载百万数量级来拆分,拆分成 64 张表,进一步可以把 64 张表拆分到两个数据库中,每个库中配置 32 张表。当新订单创建时,首先生成订单 ID,对数据库个数取模,计算对应访问的数据库;接下来对数据表取模,计算路由到的数据表,当处理查询操作时,也通过同样的规则处理,这样就实现了通过订单 ID 定位到具体数据表