7-1 介绍一下你们项目中的优惠券功能
我们项目中优惠券功能涉及到两个操作端口,管理员端口和学生端口。
管理员端口,管理员可以在后台优惠券管理页面查看优惠券列表信息,在这个列表中可以完成优惠券的增删改查功能。
其中优惠券有立即发放、定时发放两种发放方式。只有处于暂停状态或者待发放状态的优惠券,在优惠券列表中才会出现发放按钮,可以被发放,并且优惠券发放限制了使用期限,可以按固定天数算也可以按固定时间段算。发放优惠券的主要业务就是更新优惠券的领取时间范围和使用时间范围,并且在发放优惠券的时候,如果判断优惠券的领取方式为指定发放并且优惠券处于待发放状态,需要基于线程池异步生成相应的兑换码。
领取方式也有两种,一种是在前段页面直接手动领取,另一种是通过输入兑换码的方式指定发放领取。如果优惠券未领取或未达到领取上限,则可以立即领取。如果优惠券已经领完,则展示已领完。如果用户已经领取优惠券,则展示去使用。我们设计了一个用户券表,来保存了哪个用户领取了哪张优惠券,和领取优惠券的使用情况,来判断用户是否领取了这个优惠券。
最终通过优惠券是否存在、优惠券是否在优惠券发放时间内、库存是否充足、是否达到优惠券每人限额数量等一系列校验,修改用户与优惠券之间表中字段状态,完成用户领取优惠券功能。如果是兑换码领取,还需校验兑换码的有效性。
7-2 你们项目中是如何防止优惠券超领的
优惠券超领可分为多人超卖问题和单人超卖问题,主要是因为优惠券领取的过程中有大量的校验,这些校验逻辑在高并发的场景下共享资源但却不具备原子性。
遇到这种并发问题,方案就是加锁。我们项目在解决单人超卖问题上使用了乐观锁,即synchronized 锁锁上同步代码块
而对于多人超卖问题,使用了悲观锁思想,我们项目利用了sql语句的原子性每次提交事务前,判断优惠券已发行数量是否小于总数量,也就是在优惠券已发行数量的sql更新语句上添加优惠券已发行数量小于总数量的where条件即可。
7-3 事务失效的场景有哪些
1.事务方法非public修饰。
2.非事务方法调用事务方法。
3.事务方法的异常被捕获。
4.事务异常类型不对。
5.事务传播行为不对。