给业务加锁:
背景: 有些业务需要加锁,避免多个用户同时操作,比如10个用户同时点击修改某条数据。
方案:使用redis 进行加锁。redis缓存使用
步骤:
一:加锁
public boolean tryLock(String employeeId,String uuid) {
String judge=jedisUtil.setNX("PUSH_CONTRACT_BY_ID_"+employeeId,uuid,5000);
//获得锁成功
if("OK".equals(judge)) {
return true;
}
return false;
}
二:释放锁
public boolean releaseLock(String key, String value)
{
Jedis jedis = getJedis();
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(value));
jedis.close();
return RELEASE_SUCCESS.equals(result);
}
三:使用案例一
//合同推送的整个处理过程加锁处理
String uuid = UUID.randomUUID().toString();
if (tryLock(employeeId,uuid)){
EmployeeInformation employeeInformation = employeeInformationService.findById(employeeId);
//已推送的不再推送
if (employeeInformation == null || (PushStatus.PUSH_SUCCESS.getCode().equals(employeeInformation.getPushStatus()))){
return;
}
String validIdentityId = employeeInformation.getValidIdentityId();
UserIdentity userIdetity = userIdentityService.findByIdentityCardId(validIdentityId);
//员工未实名或当前员工信息为编辑中状态时推送失败
if (userIdetity == null || EditStatus.EDIT.getStatusCode().equals(employeeInformation.getEditStatus())) {
logger.error("员工[{}]还未在app端进行实名或合同处于编辑中状态无法推送,合同推送失败",employeeInformation.getName());
//员工还未实名认证时,把该条记录置为推送失败
employeeInformation.setPushStatus(PushStatus.PUSH_FAILED.getCode());
employeeInformationService.updateById(employeeInformation);
return;
}
//推送合同
boolean pushComplete;
List<Notification> list = new ArrayList<>();
User user = userService.findOne(userIdetity.getUserId());
if (EmployeeMatchAction.CUSTOMLAUNCH.equals(employeeInformation.getMatchAct())){
//自定义合同推送
pushComplete = customContractPushProcess(employeeInformation,userIdetity,user,list,jMePushMsgs);
}else {
//模板合同推送
pushComplete = templateContractPushProcess(employeeInformation,userIdetity,user,list,jMePushMsgs);
}
//推送完成后修改员工信息状态为已推送
if (pushComplete){
employeeInformation.setPushStatus(PushStatus.PUSH_SUCCESS.getCode());
employeeInformationService.updateById(employeeInformation);
//所有合同推送成功,批量插入站内通知
notificationService.batchAddAppNotice(list);
//成功推送的人数+1
successNum.getAndIncrement();
}else {
//推送失败的情况的下可能存在已经有推送成功的合同,所以需要删除该员工信息下推送成功的合同
deleteContractsByEmployeeId(employeeId);
}
//员工所属的分区与员工信息所属分区不一致时,需要更新员工的所属分区
if (!employeeInformation.getPartitionId().equals(user.getPartitionId())){
user.setPartitionId(employeeInformation.getPartitionId());
userService.update(user);
}
jedisUtil.releaseLock("PUSH_CONTRACT_BY_ID_"+employeeId,uuid);
}
四使用案例二
/**
* 跨区印章申请审核
* 1.加锁,审核信息id作为锁,同一条记录同时只能有一个人操作
* 2.包含一个跨区印章,其操作结果直接影响合同审核状态
* 3.包含两个及两个以上都是跨区印章
* 2.1 再加锁合同id锁,合同同时只能被一人更新
* 2.2 当所有审核均通过时,更新合同审核状态为通过
* 2.3 驳回操作只会影响本条记录及合同审核状态,其它已审核过的不受影响
*/
try{
boolean lock = jedisLockUtil.tryLock(RedisPreKey.EXAMINE_RECORD_ID_PRFIX + req.getId(), NumberEnum.ONE.getNumberStr(), 3000);
if(!lock){
throw new SSCSignException(BaseConstants.ALREADY_OTHERS_OPERATER_CODE,BaseConstants.ALREADY_OTHERS_OPERATER_MSG);
}
Examine examine = selectById(req.getId());
if(examine == null || !ExamineStatusEnum.WAIT_EXAMINE.getStatusCode().equals(examine.getExamineStatus())){
throw new SSCSignException(BaseConstants.ALREADY_OTHERS_OPERATER_CODE,BaseConstants.ALREADY_OTHERS_OPERATER_MSG);
}
Contract contract = contractService.selectById(examine.getContractId());
if(contract==null){
//当合同已被删除,该条待审批记录自动清除
examineMapper.deleteByPrimaryKey(examine.getId());
throw new SSCSignException(Constants.CONTRACT_ALREADY_DELETED_CODE,Constants.CONTRACT_ALREADY_DELETED_MSG);
}
if(contract.getSealNum()==1){
singleWaitSignSealExamineHandler(req,examine,contract,userInfo);
}
if(contract.getSealNum()>1){
String[] sealPartitionIdArr = contract.getSealPartitionIds().split(",");
String[] sealIdArr = contract.getSealIds().split(",");
ArrayList<String> crossPartitionSealIdList = new ArrayList<>();
for (int i=0;i<sealPartitionIdArr.length;i++) {
if(!contract.getPartitionId().equals(Integer.parseInt(sealPartitionIdArr[i]))){
crossPartitionSealIdList.add(sealIdArr[i]);
}
}
if(crossPartitionSealIdList.size()==1){
singleWaitSignSealExamineHandler(req,examine,contract,userInfo);
}else{
try{
//加合同id锁
lock = jedisLockUtil.tryLock(RedisPreKey.CROSS_SEAL_EXAMINE_CONTRACT_ID_PRFIX + contract.getId(), "1", 3000);
if(!lock){
throw new SSCSignException(BaseConstants.DOING_PROCESS_BY_OTHERS_CODE,BaseConstants.DOING_PROCESS_BY_OTHERS_MSG);
}
multipleWaitSignSealExamineHandler(req,examine,contract,userInfo,crossPartitionSealIdList);
}finally {
jedisLockUtil.releaseLock(RedisPreKey.CROSS_SEAL_EXAMINE_CONTRACT_ID_PRFIX + contract.getId(), NumberEnum.ONE.getNumberStr());
}
}
}
}finally {
jedisLockUtil.releaseLock(RedisPreKey.EXAMINE_RECORD_ID_PRFIX + req.getId(), NumberEnum.ONE.getNumberStr());
}