7-1 介绍一下你们项目中的优惠券功能
我的项目中的优惠券功能主要包括优惠券管理,发放优惠券,查询优惠券,领取优惠券,兑换优惠券等功能
流程->创建-->发放优惠券-->学生端可以查询-->(手动领取、兑换优惠券)-->使用
首先需要后端创建优惠券,指定优惠券的推广方式,数量和类型等属性,保存优惠券信息,然后发放优惠券,在发放的时候需要指定发放规则,立即发放,用户可以直接在优惠券页面手动领取,定时发放需要等到固定时间,然后利用线程池实现异步生成兑换码,后台给优惠券生成N张兑换码,保存优惠券兑换码信息,由管理员发放给指定用户,用户可以领取或者根据兑换码兑换优惠券,领取优惠券的同时要注意高并发情况会发生的问题,sql语句保证原子性或者使用乐观锁和悲观锁来解决高并发问题,最后保存用户优惠券信息。兑换优惠券关键点在于使用redis的bitmap的setbit的方法返回值来判断是否已经兑换,从而避免重复兑换。
7-2 你们项目中是如何防止优惠券超领的
优惠卷超领,通常是发生在高并发情景和单人多次点击导致的问题。
首先,高并发情况下超领,是因为多线程在判断库存是否充足,库存剩余数据更新不及时导致的,解决办法就是保证sql语句的原子性,在更新优惠券 判断已发行数量是否小于总数量。这样,当线程不满足条件也不会执行发行数量+1操作了.。
然后是单人多次点击,在判断该用户是否超领业务中,存在多线程并发问题,当多个线程通过获得了count=0 就可能发生多次领取优惠券情况发生。解决办法就是使用Synchronized的同步代码块,锁用户id做对象来解决的,使其同一个用户的多个线程无法同时进入查询该优惠券用户数量和判断是否超领的方法中即可
7-3 事务失效的场景有哪些
①事务方法非public修饰。
原因Spring的事务是AOP实现的AOP底层又是动态代理,当方法为非public的时候,无法使用反射机制来做事物的代理的增强。
②非事务方法调用事务方法。
当非事务方法调用事务方法的时候,如若使用非事务方法所在类调用this.事务方法,事务方法的事物就会失效。解决这个问题想办法获取代理对象即可,
- 引入AspectJ依赖:
- 暴露代理对象:在启动类上添加注解,暴露代理对象:@EnableAspectJAutoProxy(exposeProxy = true)
- 使用代理对象 只要将这个方法改成接口的方法就行
③事务方法的异常被捕获。
事务被捕获(加了try catch),就会导致Spring无法感知事务异常,自然不会回滚,事务就失效了。
④事务异常类型不对。
Spring的事务管理默认感知的异常类型是`RuntimeException`,当事务方法内部抛出了一个`IOException`时,不会被Spring捕获,因此就不会触发事务回滚,事务就失效了。
⑤事务传播行为不对。
存在嵌套事务,导致无法回滚。
这就是我对事务失效场景的了解。