一、前言
最近在生产环境经常收到很多接口(涉及用户端和内部系统端)超时以及MySQL CPU 100%的告警。
经过排查发现,上述2个告警是同一个问题,都是因为有一张表(下文称为表A)的数据量太大(2200万)导致的。
二、系统现状
目前有两端的请求会使用到表A,首先外部用户会对表中7天内的数据进行大量的增改查,其次是公司内部人员偶尔会查询各种时间段的数据。数据不会删除,每天能新增20万左右,目前总量2200万,数据库为主从架构。
三、技术方案对比
方案1:冷热库分离
这种使用情况让人自然而然地想到使用冷热库分离,因为只有7天内的数据是高频使用,7天以外的只会存在低频查询。那么就把7天内的数据归为热数据存在原表,7天外的归为冷数据存到另一张表去,7天内的热数据顶多不会超过200万,如此一来是可以解决当下的问题。但是这种方案也有以下2个缺点,所以最终没有采用这个方案:
(1)不支持同时涉及冷热库的大时间范围的跨库查询
(2)冷库的表数据也会达到2000万以上,而且日益增多,迟早超过MySQL单表极限
方案2:MySQL + MongoDB + 双写
MongoDB集群是分片存储的,能够容纳海量数据,可以解决MySQL无法存储大数据量问题。同时提升查询性能,降低MySQL集群压力。
于是有了一个思路,MySQL表只存储7天内的热数据,MongoDB存储全量数据,增量数据双写到两个库里面去,双写通过监听binlog实现。公司内部人员的查询可以使用MongoDB,如此一来也解决了大时间范围的查询问题。
这个方案更加合适,所以我们选择了它。
四、方案实现
以下是方案2的具体实现过程:
(1)编写定时任务将A表存量数据同步到MongoDB(xxl-job半夜执行一次)
(2)新增数据实时同步服务 sync-data-service,通过监听binlog实时同步增量数据到MongoDB
(3)编写定时任务每天清理A表数据,使其只保存最近七天的数据
(4)公司内部人员的查询,数据库从MySQL改为MongoDB
五、结果
(1)MySQL数据库集群CPU使用率恢复正常
(2)接口访问性能恢复正常,不再出现因表A查询慢产生的接口超时情况,不再产生告警