7-1 介绍一下你们项目中的优惠券功能
我们项目中的优惠卷功能大致分为发放优惠卷,查询优惠卷,和领取优惠卷,以及兑换优惠卷四个功能。
后台发放优惠卷可以发放时机来决定是否是立即发放还是定时发放,定时发放会使用延时任务来发放优惠卷,当优惠卷类型为指定发放时,会将优惠卷数量缓存到Redis中,然后根据第几张优惠卷生成兑换码,此过程需要线程池异步进行。
优惠卷查询需要一个用户和优惠卷中间表,当前端查询优惠卷时,先从这个中间表查询当前用户优惠卷,再判断用户已经领取优惠卷信息,再封装返回结果
领取优惠卷时,前端发送请求后,先查询优惠卷信息,再判断是否发放,判断库存是否充足,再在用户和优惠卷中间表查询是否超领,领取后更新优惠卷领取数量如果优惠卷有时间限制再更新时间保存到用户优惠卷中间表里面
兑换优惠卷时,前端发送请求到后端后先解析兑换码是否已经兑换,然后查询兑换码是否存在,过期,是否超出数量,最后修改优惠卷已发放数量加一,更新用户优惠卷中间表,更新解析码状态
7-2 你们项目中是如何防止优惠券超领的
优惠卷超领分为多人超领和单人超领、
首先给优惠卷领取动作加上开启事务注解
解决多人超领问题是给更新数据这个操作加上乐观锁
解决单人超领给查询判断新增这个操作加锁,锁的粒度为用户id
这样操作会出现事务边界和事务失效问题,
为解决事务边界,为此要把添加事务的方法抽取出来单独在这个方法开启事务,在优惠卷领取动作内调用这个方法 并为这个方法添加锁,
解决事务失效,要在启动类上添加注解来暴露代理对象,用代理对象调用事务方法
7-3 事务失效的场景有哪些
事务非public修饰, 非public修饰发方法是不能被spring动态代理的
非事务方法调用事务方法,因为在类中非事务方法调用事务方法时,是this调用就是调用原始类中的方法,解决方法是用代理对象来调用事务方法
事务方法异常被捕获,spring事务要感知业务中的异常 捕获异常后才会回滚事务
事务异常类型不对,spring默认回滚异常是RuntimeException,IOException不会回滚,为此要在
@Transactional
注解中的rollbackFor
属性来指定异常类型。
事务传播行为不对,当事务传播类型为必须新事务,而一个另一个子事务为默认 当一个事务调用这个两个子事务时 声明为必须新事务的方法在主事务出现异常时不会回滚