目录
1、业务背景
目前,**东商家有30W+,为了尽可能的更新上架新商品,这些商家会进行频繁页面操作。经统计,在所有的页面操作中,定时发布(立即发布)是深受商家喜爱的经典操作,特别是大促一结束,商家会进行高并发的发布操作,如在2020.11.12的0点,大量的商家就迫不及待的开始下架活动页面,并更新为常规页,这一波骚操作QPS竟高达2W。
2、面临的问题
由于页面发布关联的数据库之多,频繁的写库对数据库造成了非常大的压力。同时,调用上游接口也会相关的多,在大促期间,各兄弟部门稳字当头,一般也会对自己的接口进行自动限流,当超过一定的阈值时,就会限流甚至降级,从而导致发布失败。当然这也不是我们所期望的。
目前,30W+的商家的频繁操作已经让主库的CPU消耗疲于奔命,那接下来随着业务的扩展,商家数据将会呈现指数级增长,200W,2000W更不在话下。那么在如此高的并发下,如何让发布操作更加优雅,CPU利用率并不会因商家数量的增长而线性增长,满足商家骚操作『又快又稳』,这是值得思考的一个话题。
3、解决之道
下面给出两种已经落地的解决方案,并且都取得了一定的成效。
3.1 定时发布提前发布
定时发布,就是在指定的未来时间点进行发布。这一场景处理逻辑是比较简单的,即让定时任务提前执行,到点了仅仅执行轻量级的操作。
优点:操作简单,无需考虑过多的复杂场景,如数据同步。
缺点:其实缺点也是挺明显的,其一是数据库的轻量级操作,虽然轻量,但达到一定的量级,对数据库也是有伤害的。其二:当定时任务的TPS达到一定的量级,虽然是提前执行,但在执行阶段,同样会有大量的写操作,数据库也会有频繁的IO操作。其三:需要额外的存储空间,毕竟同一个商家的同一个页面可以设置多个定时点。
3.2 立即发布优先内存处理
立即发布,所谓立即发布,即是秒级甚至毫秒级的范围内看到效果。为了满足高并发的写操作,显然不能直接操作mysql等数据库,最直观的感受就是找一个替代品(即写的tps高一点的中件间),redis当仁不让。
下面是redis与mysql在性能测试。
redis的set操作 | mysql的update操作 |
|
|
如上图可知,redis的写性能是mysql的10倍左右,可以说性能虐爆mysql。方案其实也挺简单,相关的操作优先于redis操作,然后根据数据同步策略到mysql(此操作也是一个轻量级操作,基于一定的同步策略执行即可),通过最终一致性策略保证写入成功。
优点:按照一定的同步策略,可以减缓mysql的写压力,避免频繁的操作mysql库。
缺点: 缺点主要有两个:一是增加了数据同步策略,二是当同步策略不当时,有可能也会导致对mysql频繁的轻量级操作。
3.3 平滑执行
上面两种解决方案,最终都需要落实到数据库的操作,无论是多么轻量级的数据操作,当TPS超过了数据库的更新极限,无论是操作本身还是数据库都些许有些压力,为了彻底解决此问题,需要对任务的执行进行平滑处理——通俗的描述:以数据库能承载的能力执行CURD。任务的平滑执行可以借助很多中间件,如kafka的主动拉取broker数据进行消费,在此就不在累述。
————————————————————————————————————————————————————
附上一张整体的实现图: