7-1 介绍一下你们项目中的优惠券功能
优惠券功能在我们的项目中主要用于提升销售力度、吸引用户量,优惠券的主要功能如下:
1.优惠券发放:发放优惠券主要是更新优惠券领取时间范围和使用时间范围,优惠券状态,这里面只有开始领取时间需要判断是否立即发布,并生成兑换码;
2.优惠券查询:
在优惠券页面可以查看到手动领取,处于发放状态的优惠券
如果优惠券未领取或未达到领取上限则可以立即领取,如果优惠券已领完则展示已领完如果用户已领取优惠券,则展示去使用;
3.领取优惠券:
校验优惠券是否存在,存在才可以领取;校验当前领取时间是否在优惠券的发放时间范围内,在内才可以领取;校验优惠券的库存是否充足;校验优惠券的每人限领数量。全部校验通过后,可以领取优惠券,并且优惠券记录表中已领取数量字段也要更新
4.兑换优惠券:
解析兑换码,判断是否已经兑换,兑换了就返回异常结果,没兑换就查询兑换码数据,判断是否存在,不存在返回异常结果,存在的话在判断是否过期,是过期的话返回异常,若没过期判断是否超过限领的数量,超过了就返回异常,没超过就执行优惠券已发数量+1,生成用户券,更新会换吗的状态,结束;
以上就是我们项目中优惠券所实现的功能。
7-2 你们项目中是如何防止优惠券超领的
在我们的项目中会因为多并发问题导致两种超卖的可能,多人超卖,单人超卖。对于这种并发问题我们的解决一般为悲观锁、乐观锁,具体方案如下:
1.在多人超卖的情况下,我们采用乐观锁的方案,在这个项目中,我们会对sql语句中多加一个条件进行约束;
2.对于单人超卖的解决方案:可以使用悲观锁解决此问题,可以通过在领取优惠券代码块上加锁,锁用户id来解决此问题;
以上就是我们对于这两种情况的解决方案。
7-3 事务失效的场景有哪些
我在项目中遇到的事务失效的场景有以下几种:
1.事务的方法是非public修饰的:
因为Spring的事务是基于AOP的方式结合动态代理来实现的。因此事务方法一定要是public的,这样才能便于被Spring做事务的代理和增强。而且,在Spring内部也会有一个 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource
类,去检查事务方法的修饰符;
2.一个非事务的方法调用事务方法:
实现类中的方法添加了事务的注解,说明是一个事务方法,事务方法会被Spring事务管理,Spring会给实现类生成一个动态代理对象,对事务方法做增加,实现事务效果。在非事务方法中调用事务方法,这个调用中隐含了一个this.的前缀,相当于直接调用原始的实现类中的普通方法,而不是Spring代理对象的代理方法。那么事务就失效了。
3.事务中的异常被捕获:
在事务方法中,在其内部直接捕获异常,导致方法的执行过程中即便出现了异常也不会向外抛出,而Spring的事务管理是要感知业务方法中的异常,当捕获到异常后才会回滚事务。
4.事务异常类型不对:
Spring的事务管理默认感知的异常是运行时异常,当出先别的异常时,就不会被感知,导致无法回滚;因此,当我们的业务中会抛出RuntimeException以外的异常时,应该通过@Transactional
注解中的rollbackFor
属性来指定异常类型 @Transactional(rollbackFor = Exception.class)
5.事务传播行为不同:
在事务失效的场景中,事务传播行为不同指的是在不同的事务传播行为下,事务在面对特定情况时的处理方式和行为。例如:
1.假设有一个事务A正在执行,而在事务A中调用了一个新的方法B,而方法B中也包含了事务。在这种情况下,事务传播行为不同会导致方法B内部的事务如何与外部的事务进行交互。
2.如果使用REQUIRED的传播行为,那么方法B将会加入事务A,与事务A共同执行。而如果使用REQUIRES_NEW的传播行为,那么方法B将会创建一个新的事务,独立于事务A。
因此,不同的事务传播行为在事务失效的场景中指的是在嵌套事务或方法调用中,事务是如何传播和交互的。选择合适的事务传播行为可以确保事务在特定场景下的一致性和可靠性。