一、前言
好的方案是一步步演进出来的。当前最优的系统方案,可能在下一个月、三个月或半年后,就会遇到瓶颈,需要调整自身以便适应新的业务场景。系统的演进就是一个快进版的人类进化史。
我之前负责的一个系统,一开始基本没啥数据量,短短几个月数据量就达到了30w+/天,也就是1个月后核心业务表就接近1千万(MySQL数据库),为此对系统进行了从单个数据库到分片库的升级改造。
二、演进历程
该系统从20年5月初首次发版以来,由于业务量的增长,在数据存储层,经历过3个阶段的发展,如下图:
2.1、单库阶段:
20年5月,系统搭建初期,支持的用户并不多,因此初版只是完成了数据模型的确立和基本功能的实现,采用了1主2从的单库结构,2个从库部署在不同的机房,防止单点故障。数据库cpu/内存/磁盘配置:8C/12G/128G。
2.2、Redis + 读写分离:
20年9月,系统支持了实物+服务的业务场景,跟订单中心打通,打通后系统数据量开始稳步提升,增量数据大约在5万/天。系统流量的增长,一方面让大家看到了系统带来的价值,另一方面也意识到了,需要做些什么来保护数据库。具体措施:
①针对查询接口,增加了主动式缓存:在查询频率较高的场景下,提前把数据放入缓存进行预热,减少回表查询。
②读写分离+从库负载均衡:JED弹性库支持通过不同的账号,进行不同权限的数据库操作:rr账号支持读写,ro账号仅支持读。因此数据层增加了只有读权限的数据源配置,通过逻辑改造,实现读写分离。另外ro账号可以通过DBA调整配置,对读操作进行负载均衡(默认是不支持的),进一步提升数据库读操作的吞吐量。
③数据库配置升级:从原来8C/12G/128G升级到了16C/16G/256G,从库升级为3个。
2.3、ES + Redis + 数据库分片:
20年双11,业务进一步增加了推广力度,增量数据30万+/天,其中11.11当天突破百万。系统流量的再次增加,按照目前的方案,不到1个月单表数据量就会达到千万级别,到了这个级别后,很难保证MySQL的性能,可能原来某个正常在用的功能,第二天就会出现因为慢SQL导致的接口超时、操作无响应、页面白屏等。并且针对业务的发展来说,未来会投放更多的入口,系统会迎来更大的流量。因此在方案上又进行了优化,具体如下:
①排查慢SQL:梳理DAO层SQL,排查未走索引的查询,优化相关SQL语句。避免表的关联查询,统一调整为单表查询,数据的加工处理放在逻辑层,数据库只做存储和简单查询(这点在系统搭建初期贯彻的就比较好,基本没有关联查询)。
②数据库分库:从单库切为24个分片库,按照30万/天的增量规划,支持未来2年的发展。根据用户PIN的hash值做路由,由于面向的是整个京东的C端用户而非特定用户群体,因此可以避免数据倾斜。
③引入ElasticSearch:将数据在ElasticSearch中异构一份,对外提供查询服务,进一步降低对数据库的压力,同时支持更丰富的查询场景。MySQL跟ElasticSearch之间的数据同步,是通过binlog实现监听MySQL数据库变更的日志来完成的。
本文重点