从零开始设计开发优惠券系统(四)

概述

本章节主要讲优惠券链路的黄金流程,喜闻乐见的领券。

领券是营销过程中用户参与度非常高的一种行为,领用的券可以作为现金或者打折的方式直接抵扣支付现金,实打实的能够得到优惠,在促活和拉新场景下作为常见的手段来使用。在成本cover住的情况下,能够实现平台和用户的双赢。

核心关键点

1.限制流量

请添加图片描述

1.1 限制刷子流量

设计领券的流程最先考虑的一定是限制流量,领券是直接能面对消费者的,也就是,任何一个人如果有基本的技术,都可以通过反编译或者解析调用链接来进行刷券请求,也就是我们常说的刷子流量,这部分流量是一定要阻拦住的,不然会给集群造成很大的压力,会影响正常用户下单

1.2 系统鉴权

其实针对于优惠券的调用方很多,但是也比较好分类,APP、PC、H5、小程序 ,我们针对每个业务调用方分配给独立的token,调用时发现token异常直接拒绝。

1.3 风控

对于一些黑产,会通过一些手段获取很多账号或者一些小号,这样的话,我们需要借助外部系统的能力,来识别到这些用户是否有风险,不能给他发放优惠券。

1.4 单用户领券限流

除了券包的形式发券的场景,用户点击领券的时间是有极限的,也就是说一个用户通过手点的方式,1s钟能领取的券一定是有限的。如果超过了这个范围,我们可以认为是异常流量,直接拒绝请求。

1.5 单活动场次限流

针对发放的比较超值的券,如满100-99这种券,优惠力度很大,会导致用户请求量非常大,有可能就是人均点一下,这单个活动流量的qps就轻松上万了,为了保护系统,针对不同的活动我们可以设置不同的限流阈值,来保护系统,快速返回。

2.前置校验

2.1 判断该批次是否在黑名单中

有些时候因为业务人员操作有误,出现券面额很高,但是无门槛,或者门槛很低,会造成很大的经济损失,这种批次数据通过动态黑名单的方式进行控制,可以及时止损。

2.2 验证批次的密文

前后端进行请求的时候,不能直接明文传输,使用加密的方式进行处理,到我们券系统进行解密,减少无效或者异常调用,同时也很大程度避免撞库的问题

2.3 验证批次的有效性
  • 有可能批次的可领取时间是昨天,但是今天用户点击领取,如果前端没有控制住的话,后端需要对时间等信息进行校验。
  • 有可能可领取的时间是今天的9点-11点,那么我们8点或者12点都不能领取,分时段的批次粒度要更细一些,同时,每个事件段都可以设置独立的库存。
2.4 验证批次的适用地区

到目前为止,此校验才会真正的对正常请求的用户有限制作用,基于坐标或者ip来确定用户能不能领取这张限制地域的优惠券。

2.5 验证批次的适用渠道

如果批次的领取场景限制在了小程序,那么就算用户根据链接从pc浏览器打开或者在App打开,都是不能领取的,也可以作为大型公司推广新业务的引流来使用。

2.6 验证批次能不能领多次

有些批次我们设置了一些领取限制,比如一天只能领一次,或者活动期间内只能领取一次等。避免出现一个人领了太多的优惠券,导致正常用户无法领取到的问题

2.7 验证库存信息

提前先从缓存中查询该批次还有没有剩余库存,如果没有的话不需要进行后续操作了,也就是需要我们在优惠券批次领取完成以后,对该活动打上标记,可以提前结束请求。

3.解决并发

3.1 幂等校验

针对两次一样的调用(请求Id一致),我们的返回结果应该一致,而不是发两次券。

3.2 分布式锁

锁的粒度为用户Id+活动Id+批次Id 的维度,防止出现一个用户点击多下同一批次券的时候出现数据不一致问题,不能简单的把粒度放到用户维度,因为我们实际的库存是放在了活动+批次维度下的,用户领取不同活动的券不会存在并发扣减库存的问题。出现被分布式锁限制住的情况,可以立刻返回文案,“活动火爆,请稍后再试” 等等。

3.2 redis事务

使用事务主要为了解决的是库存扣减与用户领取记录的一致性,不能够出现库存扣减成功,但是记录失败的问题。

对于分时段的库存,要同时扣减时段库存和批次总库存,也需要保证一致性

4.数据存储与补偿机制

首先数据存储的话我们使用jvm cache + redis + mysql ,首先我们的主流程是尽量少的使用mysql等关系型数据库,会导致我们的系统吞吐量很难提升到上w的水平。

4.1使用jvm缓存
  • 批次的名称和一些基本的限制信息,这些信息每次请求都会用的到
  • 批次的库存,这个库存数量可以不准,因为真正的库存扣减会以redis为准,我们可以作为前置的数据过滤的校验,秒级能一致,就可以接受
  • 批次分时段的库存,作用和第二个基本一致
4.2使用redis

redis是我们系统的核心中间件,扛住系统的主要流量,对于系统十分关键

首先,我们使用redis的部署要尽量使用cluster方式,保证集群的稳定性,方便后期的横向提升系统的配置方案

对于redis 的调用,保持最少调用原则,尽量避免出现一次前端调用 后边redis ops 几十倍的调用,这样等到流量来了,redis也很难扛得住。

使用多套集群,提升系统的吞吐量,很多没有必然关系的数据可以保存在多套集群里边,比如防重记录等和我们的批次库存没有关系,可以放到不同的集群实例里边去,针对不同的批次也可以在不同的集群里边记录。毕竟后边我们也会把数据持久化到mysql,不会出现不好统计的问题。目前我们库存相关的集群32套,保证日常调用的性能不会出现很大的瓶颈。

4.3使用 mysql

使用mysql主要是为了数据持久化和数据的分析,也可以做问题的分析用,实际的mysql写入可以在写完redis后异步写库,同步写的话问题也不大。

4.4数据补偿

任何一个系统都无法保证CAP,对于我们业务系统来说,我们一般可以保证999或者9999,那百分之一或者千分之一,我们也要做好补偿措施

  • 补偿一定不是在主流程补偿,可以异步发mq或者报警提示
  • 当出现未知异常,要以redis的值或者mysql的值为基准,算出来当前的库存是多少,做到不超卖,不少卖
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值