在开发信息管理系统中虽然这些系统很多人认为是没有什么并发量的,所以不用考虑关于并发的问题,担是有一个问题就是,当系统部署上线运行后,用户是在不同的地方通过网络访问的,有些用户网络不好会慢点,有些会快点,这样就会当一个用户正在做某个操作审核功能,由于网络原因显示正在执行,而另一个用户同时也在操作这些审核,由于网络好,一下子就审核完成,而另外那个用户最后可能还没有审核就出现已经审核的情况。因此,可以使用redis的key自增加过时的办法实现某个操作同时只能有一个用户操作。
代码示例:
public Object doSubmit(DoSubmitReq req, String userName) {
// 查询工单信息
AylWorkflow aylWorkflow = aylWorkflowRepository.findById(req.getId()).orElse(null);
if (aylWorkflow == null) {
throw new BadRequestException(90000, "工单信息不存在!");
}
final String redisKey = ConstantConfig.preRedisWorkflowProcessingKey + req.getId();
//redis自增方法
Long inc = redisTemplate.opsForValue().increment(redisKey);
if (inc == 1) {
// 获得锁,可以操作该工单。
redisTemplate.expire(redisKey, 3, TimeUnit.SECONDS);
// 根据操作结点及操作Id通过工厂模式生成对应策略
Submit submitStrategy = submitFactory.getSubmitStrategy(aylWorkflow.getWfNodeId(), req.getOperationId(), userName);
if(submitStrategy == null){
throw new BadRequestException(90000, "操作异常!");
}
// 使用策略模式,调用策略执行方法
return submitStrategy.doSubmit(aylWorkflow, req);
} else {
//如果自增不是等于1,而是-1时,短时间内频繁访问某个redis的key可能把它击穿,就是变成-1
Long ttl = redisTemplate.getExpire(redisKey);
if (ttl == -1) {
// 未设置过期时间,补设置。
redisTemplate.expire(redisKey, 3, TimeUnit.SECONDS);
}
}
throw new BadRequestException(90000, "该工单正被另一个用户审核,请刷新后操作!");
}