From aec4b87b2a5bd077994d9916b53c7c7c8d6a5a4b Mon Sep 17 00:00:00 2001 From: jieyuu <645634619@qq.com> Date: Tue, 6 Aug 2024 01:02:13 +0800 Subject: [PATCH] =?UTF-8?q?git=E6=95=B4=E5=90=88redisson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/CouponServiceImpl.java | 80 +++++++++---------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/xdclass-coupon-service/src/main/java/net/jieyuu/service/impl/CouponServiceImpl.java b/xdclass-coupon-service/src/main/java/net/jieyuu/service/impl/CouponServiceImpl.java index fb304e0..321421f 100644 --- a/xdclass-coupon-service/src/main/java/net/jieyuu/service/impl/CouponServiceImpl.java +++ b/xdclass-coupon-service/src/main/java/net/jieyuu/service/impl/CouponServiceImpl.java @@ -20,6 +20,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import net.jieyuu.utils.CommonUtil; import net.jieyuu.utils.JsonData; import net.jieyuu.vo.CouponVO; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; @@ -55,6 +57,9 @@ public class CouponServiceImpl implements CouponService { @Autowired private StringRedisTemplate redisTemplate; + @Autowired + private RedissonClient redissonClient; + @Override public Map pageCouponActivity(int page, int size) { Page pageInfo = new Page<>(page, size); @@ -88,54 +93,43 @@ public class CouponServiceImpl implements CouponService { public JsonData addCoupon(long couponId, CouponCategoryEnum category) { LoginUser loginUser = LoginInterceptor.threadLocal.get(); - String uuid = CommonUtil.generateUUID(); String lockKey = "lock:coupon:" + couponId; - //避免锁被误删 - Boolean lockFlag = redisTemplate.opsForValue().setIfAbsent(lockKey, uuid, Duration.ofMinutes(10)); + RLock rlock = redissonClient.getLock(lockKey); + // 多个线程进入 会等待锁 + rlock.lock(); + log.info("领券接口加锁成功:{}", Thread.currentThread().getId()); - if (lockFlag) { - log.info("加锁成功:{}", couponId); - try { - // 执行业务逻辑 - CouponDO couponDO = couponMapper.selectOne(new QueryWrapper() - .eq("id", couponId) - .eq("category", category.name())); - //优惠券是否可以领取 - this.couponCheck(couponDO, loginUser.getId()); + try { + // 执行业务逻辑 + CouponDO couponDO = couponMapper.selectOne(new QueryWrapper() + .eq("id", couponId) + .eq("category", category.name())); + //优惠券是否可以领取 + this.couponCheck(couponDO, loginUser.getId()); - //构建领券记录 - CouponRecordDO couponRecordDO = new CouponRecordDO(); - BeanUtils.copyProperties(couponDO, couponRecordDO); - couponRecordDO.setCreateTime(new Date()); - couponRecordDO.setUseState(CouponStateEnum.NEW.name()); - couponRecordDO.setCouponId(couponId); - couponRecordDO.setUserName(loginUser.getName()); - couponRecordDO.setUserId(loginUser.getId()); - couponRecordDO.setId(null); + //构建领券记录 + CouponRecordDO couponRecordDO = new CouponRecordDO(); + BeanUtils.copyProperties(couponDO, couponRecordDO); + couponRecordDO.setCreateTime(new Date()); + couponRecordDO.setUseState(CouponStateEnum.NEW.name()); + couponRecordDO.setCouponId(couponId); + couponRecordDO.setUserName(loginUser.getName()); + couponRecordDO.setUserId(loginUser.getId()); + couponRecordDO.setId(null); - //扣减库存 todo - int rows = couponMapper.reduceStock(couponId); - if (rows == 1) { - //扣减库存成功才保存记录 - couponRecordMapper.insert(couponRecordDO); - } else { - log.warn("发放优惠券错误:{},用户:{}", couponDO, loginUser); - throw new BizException(BizCodeEnum.COUPON_NO_STOCK); - } - } finally { - // 释放锁 - // 使用lua脚本保证 查询和删除的原子性 - String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; - Integer result = redisTemplate.execute(new DefaultRedisScript<>(script, Integer.class), Arrays.asList(lockKey), uuid); - log.info("解锁{}", result); + //扣减库存 + int rows = couponMapper.reduceStock(couponId); + if (rows == 1) { + //扣减库存成功才保存记录 + couponRecordMapper.insert(couponRecordDO); + } else { + log.warn("发放优惠券错误:{},用户:{}", couponDO, loginUser); + throw new BizException(BizCodeEnum.COUPON_NO_STOCK); } - } else {//加锁失败 - try { - TimeUnit.SECONDS.sleep(1); - } catch (InterruptedException e) { - log.error("自旋失败"); - } - addCoupon(couponId, category); + } finally { + // 释放锁 + rlock.unlock(); + log.info("解锁成功"); } return JsonData.buildSuccess(); }