diff --git a/jsowell-admin/src/main/java/com/jsowell/service/MemberService.java b/jsowell-admin/src/main/java/com/jsowell/service/MemberService.java index 15950f0b0..98a49dec1 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/MemberService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/MemberService.java @@ -57,6 +57,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cglib.beans.BeanMap; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import java.math.BigDecimal; @@ -185,7 +186,8 @@ public class MemberService { throw new BusinessException(ReturnCodeEnum.CODE_OPEN_ID_IS_NULL_ERROR); } - String lockKey = CacheConstants.USER_APP_REGISTER + phoneNumber; + // 锁键包含手机号和运营商ID,确保同一运营商下的同一手机号串行处理,不同运营商互不影响 + String lockKey = CacheConstants.USER_APP_REGISTER + phoneNumber + ":" + firstLevelMerchantId; String requestId = IdUtils.fastUUID(); Boolean isLock = false; try { @@ -193,7 +195,7 @@ public class MemberService { isLock = redisCache.lock(lockKey, requestId, 60); if (!isLock) { // 获取锁失败,说明有其他请求正在处理,提示用户稍候 - log.warn("获取注册锁失败,可能有并发请求正在处理, phoneNumber:{}", phoneNumber); + log.warn("获取注册锁失败,可能有并发请求正在处理, phoneNumber:{}, merchantId:{}", phoneNumber, firstLevelMerchantId); throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_REGISTER_AND_LOGIN_PROCESSING); } @@ -226,7 +228,21 @@ public class MemberService { .build(); memberTransactionDTO.setMemberWalletInfo(memberWalletInfo); } - transactionService.createMember(memberTransactionDTO); + + try { + // 插入会员数据 + transactionService.createMember(memberTransactionDTO); + } catch (DuplicateKeyException e) { + // 捕获数据库唯一索引冲突异常(极端并发情况下的兜底机制) + // 说明该手机号在该运营商下已经被其他并发请求注册了,重新查询获取已存在的会员信息 + log.warn("会员注册时检测到唯一索引冲突,重新查询已存在的会员, phoneNumber:{}, merchantId:{}", phoneNumber, firstLevelMerchantId); + memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(phoneNumber, firstLevelMerchantId); + if (memberBasicInfo == null) { + // 理论上不应该走到这里,如果走到这里说明数据被删除了,抛出异常 + log.error("唯一索引冲突后重新查询会员信息为空, phoneNumber:{}, merchantId:", phoneNumber, firstLevelMerchantId); + throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_REGISTER_AND_LOGIN_ERROR); + } + } } else { boolean updateFlag = false; if (AdapayPayChannelEnum.WX_LITE.getValue().equals(dto.getRequestSource()) && !StringUtils.equals(memberBasicInfo.getOpenId(), openId)) { @@ -255,7 +271,7 @@ public class MemberService { redisCache.unLock(lockKey); } } catch (Exception e) { - log.error("释放注册锁失败, phoneNumber:{}, error:{}", phoneNumber, e.getMessage()); + log.error("释放注册锁失败, phoneNumber:{}, merchantId:{}, error:{}", phoneNumber, firstLevelMerchantId, e.getMessage()); } } }