从单库到分库分表:政策快报平台数据库的3次重构

政策快报平台上线第一天,数据库只有一台RDS,8核16G,存储500G。

政策数据量大约10万条,日请求量1万左右。一台RDS完全够用。

3年后,政策数据量超过1亿条,日请求量500万左右。

数据库从1台变成了:主库1台、从库4台、历史库1台、缓存集群1套。

这3年里,我们做了3次大的数据库重构。今天复盘每次重构的原因和选择。

3次重构

第一次:读写分离(日请求量10万→100万)

触发原因:某个工作日早上,数据库CPU突然飙升到100%,所有查询都超时,系统瘫了半小时。

查日志发现原因:爬虫在批量写入新数据,同时用户在大量读取。写入和读取抢同一个数据库连接池,谁也拿不到足够的连接。

当时的决定:读写分离。主库负责写入,从库负责读取,两个连接池分开,互不影响。

实施后效果:同样的问题再也没出现过。这个阶段持续了大约一年半。

第二次:缓存引入(日请求量100万→300万)

触发原因:读写分离之后,从库的压力也在持续增长。每天新增的政策数据让查询越来越慢,列表页和详情页的响应时间明显上升。

当时的决定:引入Redis缓存。热点数据缓存在Redis里,查询先走缓存,没命中再查数据库。

具体做法:政策详情按ID缓存,24小时失效。列表页缓存5分钟(政策更新频率不高,5分钟可以接受)。

实施后效果:缓存命中率稳定在70%以上,数据库查询量下降了60%以上。这个方案又撑了一段时间。

第三次:分库分表(日请求量300万→500万)

触发原因:主表数据量突破1亿条,即使走了索引,部分查询也开始变慢。特别是按地区、按时间范围筛选的查询,响应时间越来越长。

当时的决定:按年份分表。2023年之前的数据归档到历史表,2024年及之后的数据留在主表。分表之后,主表数据量从1亿降到了3000万左右,查询速度恢复正常。

这个方案解决了当前的问题,但不是长久之计。目前我们正在设计按省份分库的方案,把不同省份的数据分到不同的物理库,进一步分散读写压力。

选型决策的几个原则

回头看这3次重构,有几个决策原则是清晰的:

第一,不到万不得已不做大重构。读写分离撑了一年半,缓存又撑了一年,直到数据量过亿才开始考虑分库分表。早做没必要,晚做来不及。

第二,先用最简单的方案解决问题。按年份分表,这个方案技术含量不高,但它能解决当前80%的问题。做复杂的分库分表方案,可能解决90%的问题,但成本是前者的10倍。

第三,每一步都要考虑可回滚性。每次重构都预留了回滚方案,万一新方案出问题能快速切回去。

结尾

数据库架构没有"一步到位"这回事。数据量变了、请求量变了、业务场景变了,架构就得跟着变。

分库分表不是终点,未来可能还会有新的架构调整,到时候再说。