小结:
1、
库存扣减使用redis,我们采取预扣库存的形式,每次从数据库申请固定步长的库存进行发放,发完再次申请
发券高并发库存扣减方案落地实践 https://mp.weixin.qq.com/s/emSihdGEocnks_-BUUjlUw
发券高并发库存扣减方案落地实践
dchl 拍码场 2022-08-26 15:12 发表于上海
前言
信也优惠券平台目前服务于主营,KOO,印尼,菲律宾等业务线,累计发券量超过1亿张,券种类有8种,分别是借款红包券,还款红包券,免息券,消费券,提额券,借不到就赔券,提前结清券,还款费免券,主要用于各种营销活动、权益兑换、商城消费、话费充值等场景。另外在助力小微发展中也有所应用,是提升用户粘性、提升转化率的重要营销方式。
背景
- 一直以来优惠券发券的流量较高,特别是在6.18,双11等大促活动中,发券量大时会出现热点key问题,发券量越大速度越慢,十分影响用户体验
- 年初市场部门与腾讯合作的春节营销活动,计划发券400万张,活动在春节期间不定期进行,QPS峰值预计会达到500左右,而我们当时的QPS是50,如果不解决热点key问题,不仅影响春节营销活动,流量的叠加也会影响现有业务。
方案
一. 业界库存扣减方案:
- 基于数据库方式扣减:
发券时每请求一次,进行一次库存扣减,库存扣减时实时查询、实时更新数据库,通过数据库行锁保证数据一致性,适用于并发量不大的库存扣减场景,并发量大时就会出现热点key问题,具体流程如下。
- 优点: 有mysql数据库事物强一致性保证,数据是一致的。
- 缺点: 频繁扣减库存造成数据库行锁等待,高并发场景下会出现热点key问题,而且量越大速度越慢,严重时系统可能雪崩。
- 基于redis方式扣减:
发券前先把全部库存初始化入redis,发券时会查询redis是否充足,充足的话再利用redis的incr特性来进行库存扣减,需要在数据库和redis之前做异步task进行数据同步,具体流程如下。
- 优点:突破了行锁等待的限制,速度快。
- 缺点:无法保证数据强一致性,完全依赖缓存一旦缓存丢失,库存将失效,会引出现超发等问题。数据库和redis之前做异步task进行数据同步逻辑比较复杂,实时性要求高。
二. 我们的方案:
redis+数据库库存扣减:
综合系统稳定性,高并发考虑,我们结合以上两种方式进行了升级,库存扣减使用redis,我们采取预扣库存的形式,每次从数据库申请固定步长的库存进行发放,发完再次申请,以此类推,具体流程如下。
- 优点:通过双重检查锁,保证数据一致性,速度也很快。
- 缺点:流程相对较复杂,当前步长是固定的,后续我们将综合发放量、QPS等因子实现步长动态化。
- redis+数据库库存扣减实施过程:
- 首次发券时从数据库申请固定步长库存,我们称为增加预扣库存,然后将预扣库存放入redis中。
- 后续每次请求都从redis扣减,直到扣完。由于在这个过程中存在并发,可能多扣,所以我们需要将多扣的库存进行归还。
- 扣完后再次增加预扣库存,同样再次申请时也会存在并发,所以我们增加了双重检查锁,来确保增加数据库和redis的量是原子的。
- 假设预扣库存量是1万,那么1万次请求我们只进行一次数据库库存扣减操作,400万次的话则只进行400次数据库库存扣减,这样就解决了热点key问题。
- 由于是和三方合作,为了防止瞬时流量暴增,影响现有业务,这时也需要做好自我防护,所以我们还引入了sentinel限流,做到接收流量可控。
验证
为了充分验证,我们在测试环境进行了5种不同场景压测,结果如下:
虽然测试环境机器和生产环境机器有一定差距,但可以看出发券速度最高在10k/min左右,性能有了很大提升。
结果
优化后上线继续监控观察,当天有两个活动:老客春节活动和春节红包活动同时进行,1天的发券量为110W+,发券速度为11698,较优化前提升了7倍,按照之前的发券速度则需要12个小时,现在不到2小时就发完了。数据如下:
上线前后发券速度比较:
总结
面对高并发的挑战,我们通过redis+数据库库存扣减方案的落地实践,解决了系统瓶颈,为支撑后续业务打下良好的基础,在保证系统稳定的前提下有效的提升了用户体验。未来我们将在发券、用券数据可视化,优惠券成本可监测性方面继续发力,同时也将不断丰富优惠券的券种类,让优惠券营销更加灵活,让用户感觉更加实惠。
作者
dchl,信也科技后端研发专家,主要负责信也科技优惠券平台,消息平台,混沌平台等系统的研发、维护和推广工作。