背景:
订单量快速增长及618大促的到来都将带来单量剧增,届时势必会对数据库容量和负载造成压力。
分析结果表明数据库很可能成为影响性能的瓶颈,并决定对数据库底层做分库分表改造,确保数据水平动态扩展能力,满足数据容量持续增长的需求,并提高下单效率。
通过技术改造,从整体上来说实现三个目标:
- 底层路由策略实现;
- 历史数据迁移;
- 业务改造。下面详细介绍本次改造的过程。
数据库容器预估:
分库分表最重要的是要先做容器预估,依据数据量和业务特性估算出容器/库/表的数量及分库分表规则。
底层路由策略选择及实现:
分库分表路由策略是基础,影响整个系统架构,后期业务需求是否满足和支持,使用是否方便都与此有关。路由策略设计合理,上层业务使用会很方便。一元抢宝项目的路由策略适配和实现是在DAO层实现,对上层业务层透明,可不用关心具体实现,并且路由策略不涉及结构上的改动,对上层不会产生影响。
分表策略有两种:
hash路由
优点:可实现数据分散,热点分散;
不足:增加数据库节点时,会影响路由策略,需做数据迁移;
分区路由(增量区间路由)
优点:策略支持动态扩容,理论上可无限扩展;
不足:存在数据热点问题,新产生的表,读写频率较高;每次查询需要经过路由策略表。
当然每种策略都不是完美的,只有最适合业务场景的策略才是好的。该项目采用的是两种方式的结合。
为什么使用这种策略?
抢宝项是业务上层维度,可以理解为商品,大部分表中都有这个字段;此id生成时是连续的,长期来看,hash分库后数据是均衡的。抢宝期是抢宝项下的一个维度,如一个项库存是100,不停售前提下,会生成100期,在售的期次只有一个。
为什么选择期id区间作为分表路由策略呢,有朋友会认为也可以选择订单id,从路由策略上来说,没有问题,但一元抢宝项目的业务场景,有根据项id和期id查询订单参与纪录的场景,所以要考虑通过这两个维度能查到订单。另外,使用区间作为分表策略,可以动态扩展,即使每次查询经过路由表,这点开销可以忽略,而且都是通过缓存加载。
那以上策略,可以路由的维度有哪些呢?
- 通过订单id路由:订单号按照一定规则生成,其存储了库和表的信息,可以根据订单号直接定位到相应的库和表;
- 通过抢宝项id和抢宝期id路由:抢宝项hash定位到库,抢宝期查询路由策略表定位到表
系统关键节点降级
降级主要有两点,一是canal同步延迟降级,一是ES不可用降级。
- 如果canal同步延迟,或者从库挂掉,开启开关,扫描主库数据(最近几小时)直接同步到ES、聚合表;这样,即使从库挂掉,也不影响业务数据
- ES降级,ES不可用时,关闭ES开关,直接查询聚合表。