git整合redisson
This commit is contained in:
parent
55024f78c0
commit
aec4b87b2a
@ -20,6 +20,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import net.jieyuu.utils.CommonUtil;
|
import net.jieyuu.utils.CommonUtil;
|
||||||
import net.jieyuu.utils.JsonData;
|
import net.jieyuu.utils.JsonData;
|
||||||
import net.jieyuu.vo.CouponVO;
|
import net.jieyuu.vo.CouponVO;
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
@ -55,6 +57,9 @@ public class CouponServiceImpl implements CouponService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private StringRedisTemplate redisTemplate;
|
private StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedissonClient redissonClient;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> pageCouponActivity(int page, int size) {
|
public Map<String, Object> pageCouponActivity(int page, int size) {
|
||||||
Page<CouponDO> pageInfo = new Page<>(page, size);
|
Page<CouponDO> pageInfo = new Page<>(page, size);
|
||||||
@ -88,54 +93,43 @@ public class CouponServiceImpl implements CouponService {
|
|||||||
public JsonData addCoupon(long couponId, CouponCategoryEnum category) {
|
public JsonData addCoupon(long couponId, CouponCategoryEnum category) {
|
||||||
LoginUser loginUser = LoginInterceptor.threadLocal.get();
|
LoginUser loginUser = LoginInterceptor.threadLocal.get();
|
||||||
|
|
||||||
String uuid = CommonUtil.generateUUID();
|
|
||||||
String lockKey = "lock:coupon:" + couponId;
|
String lockKey = "lock:coupon:" + couponId;
|
||||||
//避免锁被误删
|
RLock rlock = redissonClient.getLock(lockKey);
|
||||||
Boolean lockFlag = redisTemplate.opsForValue().setIfAbsent(lockKey, uuid, Duration.ofMinutes(10));
|
// 多个线程进入 会等待锁
|
||||||
|
rlock.lock();
|
||||||
|
log.info("领券接口加锁成功:{}", Thread.currentThread().getId());
|
||||||
|
|
||||||
if (lockFlag) {
|
try {
|
||||||
log.info("加锁成功:{}", couponId);
|
// 执行业务逻辑
|
||||||
try {
|
CouponDO couponDO = couponMapper.selectOne(new QueryWrapper<CouponDO>()
|
||||||
// 执行业务逻辑
|
.eq("id", couponId)
|
||||||
CouponDO couponDO = couponMapper.selectOne(new QueryWrapper<CouponDO>()
|
.eq("category", category.name()));
|
||||||
.eq("id", couponId)
|
//优惠券是否可以领取
|
||||||
.eq("category", category.name()));
|
this.couponCheck(couponDO, loginUser.getId());
|
||||||
//优惠券是否可以领取
|
|
||||||
this.couponCheck(couponDO, loginUser.getId());
|
|
||||||
|
|
||||||
//构建领券记录
|
//构建领券记录
|
||||||
CouponRecordDO couponRecordDO = new CouponRecordDO();
|
CouponRecordDO couponRecordDO = new CouponRecordDO();
|
||||||
BeanUtils.copyProperties(couponDO, couponRecordDO);
|
BeanUtils.copyProperties(couponDO, couponRecordDO);
|
||||||
couponRecordDO.setCreateTime(new Date());
|
couponRecordDO.setCreateTime(new Date());
|
||||||
couponRecordDO.setUseState(CouponStateEnum.NEW.name());
|
couponRecordDO.setUseState(CouponStateEnum.NEW.name());
|
||||||
couponRecordDO.setCouponId(couponId);
|
couponRecordDO.setCouponId(couponId);
|
||||||
couponRecordDO.setUserName(loginUser.getName());
|
couponRecordDO.setUserName(loginUser.getName());
|
||||||
couponRecordDO.setUserId(loginUser.getId());
|
couponRecordDO.setUserId(loginUser.getId());
|
||||||
couponRecordDO.setId(null);
|
couponRecordDO.setId(null);
|
||||||
|
|
||||||
//扣减库存 todo
|
//扣减库存
|
||||||
int rows = couponMapper.reduceStock(couponId);
|
int rows = couponMapper.reduceStock(couponId);
|
||||||
if (rows == 1) {
|
if (rows == 1) {
|
||||||
//扣减库存成功才保存记录
|
//扣减库存成功才保存记录
|
||||||
couponRecordMapper.insert(couponRecordDO);
|
couponRecordMapper.insert(couponRecordDO);
|
||||||
} else {
|
} else {
|
||||||
log.warn("发放优惠券错误:{},用户:{}", couponDO, loginUser);
|
log.warn("发放优惠券错误:{},用户:{}", couponDO, loginUser);
|
||||||
throw new BizException(BizCodeEnum.COUPON_NO_STOCK);
|
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);
|
|
||||||
}
|
}
|
||||||
} else {//加锁失败
|
} finally {
|
||||||
try {
|
// 释放锁
|
||||||
TimeUnit.SECONDS.sleep(1);
|
rlock.unlock();
|
||||||
} catch (InterruptedException e) {
|
log.info("解锁成功");
|
||||||
log.error("自旋失败");
|
|
||||||
}
|
|
||||||
addCoupon(couponId, category);
|
|
||||||
}
|
}
|
||||||
return JsonData.buildSuccess();
|
return JsonData.buildSuccess();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user