记得上下班打卡 | git大法好,push需谨慎

Commit 71941971 authored by wangyifan's avatar wangyifan

福袋功能- 修复并发问题

parent 3abddaf0
...@@ -20,7 +20,7 @@ public class KylinBrands implements Serializable, Cloneable { ...@@ -20,7 +20,7 @@ public class KylinBrands implements Serializable, Cloneable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO) @TableId(value = "mid", type = IdType.AUTO)
private Integer mid; private Long mid;
/** /**
* 品牌ID * 品牌ID
......
...@@ -20,7 +20,7 @@ public class KylinLuckyBag implements Serializable, Cloneable{ ...@@ -20,7 +20,7 @@ public class KylinLuckyBag implements Serializable, Cloneable{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO) @TableId(value = "mid", type = IdType.AUTO)
private Integer mid; private Long mid;
/** /**
* 福袋ID * 福袋ID
......
...@@ -18,7 +18,7 @@ public class KylinLuckyBagActivity implements Serializable, Cloneable{ ...@@ -18,7 +18,7 @@ public class KylinLuckyBagActivity implements Serializable, Cloneable{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO) @TableId(value = "mid", type = IdType.AUTO)
private Integer mid; private Long mid;
/** /**
* 福袋活动ID * 福袋活动ID
......
...@@ -18,7 +18,7 @@ public class KylinRewardCode implements Serializable, Cloneable{ ...@@ -18,7 +18,7 @@ public class KylinRewardCode implements Serializable, Cloneable{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO) @TableId(value = "mid", type = IdType.AUTO)
private Integer mid; private Long mid;
/** /**
* 兑换码 * 兑换码
......
...@@ -19,7 +19,7 @@ public class KylinRewardUser implements Serializable, Cloneable{ ...@@ -19,7 +19,7 @@ public class KylinRewardUser implements Serializable, Cloneable{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO) @TableId(value = "mid", type = IdType.AUTO)
private Integer mid; private Long mid;
/** /**
* 用户ID * 用户ID
......
...@@ -2,6 +2,15 @@ package com.liquidnet.service.kylin.mapper; ...@@ -2,6 +2,15 @@ package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.entity.KylinRewardCode; import com.liquidnet.service.kylin.entity.KylinRewardCode;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface KylinRewardCodeMapper extends BaseMapper<KylinRewardCode> { public interface KylinRewardCodeMapper extends BaseMapper<KylinRewardCode> {
@Select("SELECT * FROM kylin_reward_code WHERE mid = #{mid}")
KylinRewardCode selectByMid(@Param("mid") Long mid);
@Update("update kylin_reward_code set state=#{state} where mid=#{mid}")
int updateByMid(@Param("mid") Long mid, @Param("state") int state);
} }
...@@ -152,60 +152,62 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -152,60 +152,62 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
* @return * @return
*/ */
private List<KylinRewardUser> getRandomRewardCode(OrderDetailsVo vo, String luckyBagId) { private List<KylinRewardUser> getRandomRewardCode(OrderDetailsVo vo, String luckyBagId) {
String lockKey = KylinRedisConst.LUCKY_BAG_CODE_LOCK + luckyBagId; final int limitTotal = vo.getOrderTicketVo().getNumber();
try { if (limitTotal <= 0) {
// 1. 获取分布式锁,防止并发问题 log.error("[getRandomRewardCode] 用户订单购买数量错误, orderId: {}.", vo.getOrderTicketVo().getOrderTicketsId());
boolean locked = redisUtil.lock(lockKey, 1, 30); return Collections.emptyList();
if (!locked) { }
log.info("[getRandomRewardCode] 未获取到分布式锁.");
return Collections.emptyList();
}
final int limitTotal = vo.getOrderTicketVo().getNumber(); final String lockKey = KylinRedisConst.LUCKY_BAG_CODE_LOCK + luckyBagId;
final KylinOrderTicketVo orderTicketVo = vo.getOrderTicketVo(); boolean locked = redisUtil.lock(lockKey, 1, 30);
if (!locked) {
log.info("[getRandomRewardCode] 未获取到分布式锁.");
return Collections.emptyList();
}
if (limitTotal <= 0) { LambdaQueryWrapper<KylinRewardCode> lambdaQueryWrapper = new QueryWrapper<KylinRewardCode>().lambda()
log.error("[getRandomRewardCode] 用户订单购买数量错误, orderId: {}.", orderTicketVo.getOrderTicketsId()); .eq(KylinRewardCode::getLuckyBagId, luckyBagId)
return Collections.emptyList(); .eq(KylinRewardCode::getState, 1)
} .last(true, " limit " + limitTotal);
//2. 搜索未分配的兑换码
List<KylinRewardCode> rewardCodes = kylinRewardCodeMapper.selectList(lambdaQueryWrapper);
LambdaQueryWrapper<KylinRewardCode> lambdaQueryWrapper = new QueryWrapper<KylinRewardCode>().lambda() if (rewardCodes.size() < limitTotal) {
.eq(KylinRewardCode::getLuckyBagId, luckyBagId) log.error("[getRandomRewardCode] 兑换码不足, luckyBagId: {}, need total: {}.", luckyBagId, limitTotal);
.eq(KylinRewardCode::getState, 1) // 报警
// .last(true, "ORDER BY RAND() limit " + limitTotal); // 随机搜索 String msg = String.format("福袋ID [%s] 兑换码不足,请及时补充.", luckyBagId);
.last(true, " limit " + limitTotal); iFeishuBotService.sendTextMessage(msg);
//2. 搜索兑换码 return Collections.emptyList();
List<KylinRewardCode> rewardCodes = kylinRewardCodeMapper.selectList(lambdaQueryWrapper); }
if (rewardCodes.isEmpty() || rewardCodes.size() < limitTotal) { //3. 写入
log.error("[getRandomRewardCode] 兑换码不足, luckyBagId: {}, need total: {}.", luckyBagId, limitTotal); final KylinOrderTicketVo orderTicketVo = vo.getOrderTicketVo();
// 报警 List<KylinRewardUser> rewardUsers = new ArrayList<>(limitTotal);
String msg = String.format("福袋ID [%s] 兑换码不足,请及时补充.", luckyBagId);
iFeishuBotService.sendTextMessage(msg);
return Collections.emptyList();
}
//3. 写入 try {
List<KylinRewardUser> rewardUsers = new ArrayList<>(limitTotal);
for (int i = 0; i < rewardCodes.size(); i++) { for (int i = 0; i < rewardCodes.size(); i++) {
KylinRewardCode rewardCode = rewardCodes.get(i); KylinRewardCode lockedRewardCode = rewardCodes.get(i);
rewardCode.setState(0); KylinRewardUser rewardUser = buildRewardUser(orderTicketVo.getUserId(),
int updateResult = kylinRewardCodeMapper.updateById(rewardCode); orderTicketVo.getOrderTicketsId(),
if (updateResult > 0) { luckyBagId,
KylinRewardUser user = buildRewardUser(orderTicketVo.getUserId(), orderTicketVo.getEntitiesVoList().get(i).getOrderTicketEntitiesId(),
orderTicketVo.getOrderTicketsId(), lockedRewardCode.getCode());
luckyBagId, int inserted = kylinRewardUserMapper.insert(rewardUser);
orderTicketVo.getEntitiesVoList().get(i).getOrderTicketEntitiesId(), if (inserted > 0) {
rewardCode.getCode()); // 将兑换码状态更新为已领取
kylinRewardUserMapper.insert(user); int updateResult = kylinRewardCodeMapper.updateByMid(lockedRewardCode.getMid(), 0);
rewardUsers.add(user); if (updateResult <= 0) {
log.info("[getRandomRewardCode] 兑换码分配成功, luckyBagId: {}, orderId: {}, code: {}.", luckyBagId, orderTicketVo.getOrderTicketsId(), rewardCode.getCode()); log.error("[getRandomRewardCode] 修改兑换码状态失败, luckyBagId: {}, orderId: {}, code: {}.",
} else { luckyBagId, orderTicketVo.getOrderTicketsId(), lockedRewardCode.getCode());
log.error("[getRandomRewardCode] 兑换码分配失败, luckyBagId: {}, orderId: {}.", luckyBagId, orderTicketVo.getOrderTicketsId()); // 报警
// 报警 String msg = String.format("修改兑换码状态失败:福袋ID: [%s], 用户ID: [%s], 订单ID: [%s], code: [%s]。",
String msg = String.format("福袋ID [%s] 分配兑换码失败:用户ID [%s] 的订单ID [%s] 已分配了 [%s] 个,应分配 [%s] 个。", luckyBagId, orderTicketVo.getUserId(), orderTicketVo.getOrderTicketsId(), lockedRewardCode.getCode());
luckyBagId, orderTicketVo.getUserId(), orderTicketVo.getOrderTicketsId(), rewardUsers.size(), limitTotal); iFeishuBotService.sendTextMessage(msg);
iFeishuBotService.sendTextMessage(msg); } else {
log.info("[getRandomRewardCode] 兑换码分配成功, luckyBagId: {}, orderId: {}, code: {}.",
luckyBagId, orderTicketVo.getOrderTicketsId(), lockedRewardCode.getCode());
rewardUsers.add(rewardUser);
}
} }
} }
return rewardUsers; return rewardUsers;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment