16-订单服务定时发送消息-乐观锁取任务

4.7 乐观锁取任务

考虑订单服务将来会集群部署,为了避免任务在1分钟内重复执行,这里使用乐观锁,实现思路如下:

  1. 每次取任务时判断当前版本及任务id是否匹配,如果匹配则执行任务,如果不匹配则取消执行。
  2. 如果当前版本和任务Id可以匹配到任务则更新当前版本加1.
    1、在Dao中增加校验当前版本及任务id的匹配方法
public interface XcTaskRepository extends JpaRepository<XcTask, String> {
//使用乐观锁方式校验任务id和版本号是否匹配,匹配则版本号加1
@Modifying
@Query("update XcTask t set t.version = :version+1 where t.id = :id and t.version =
:version")
public int updateTaskVersion(@Param(value = "id") String id,@Param(value = "version") int
version);
...

16-订单服务定时发送消息-乐观锁取任务_第1张图片

2、在service中增加方法,使用乐观锁方法校验任务

@Transactional
public int getTask(String taskId,int version){
int i = xcTaskRepository.updateTaskVersion(taskId, version);
return i;
}

16-订单服务定时发送消息-乐观锁取任务_第2张图片
报错
JPA事务问题Executing an update/delete query
如果JPA提示Executing an update/delete query,那是一定是因为Service层没有加@Transactional和再方法加@Modifying吧

16-订单服务定时发送消息-乐观锁取任务_第3张图片

3、执行任务类中修改

...
//任务id
String taskId = xcTask.getId();
//版本号
Integer version = xcTask.getVersion();
//调用乐观锁方法校验任务是否可以执行
if(taskService.getTask(taskId, version)>0){
//发送选课消息
taskService.publish(xcTask, xcTask.getMqExchange(),xcTask.getMqRoutingkey());
LOGGER.info("send choose course task id:{}",taskId);
}
...

16-订单服务定时发送消息-乐观锁取任务_第4张图片

测试(启动2个线程)

16-订单服务定时发送消息-乐观锁取任务_第5张图片
16-订单服务定时发送消息-乐观锁取任务_第6张图片
16-订单服务定时发送消息-乐观锁取任务_第7张图片
16-订单服务定时发送消息-乐观锁取任务_第8张图片
16-订单服务定时发送消息-乐观锁取任务_第9张图片
16-订单服务定时发送消息-乐观锁取任务_第10张图片
16-订单服务定时发送消息-乐观锁取任务_第11张图片
16-订单服务定时发送消息-乐观锁取任务_第12张图片
所以虽然2个进程,但是任务只能执行一次

你可能感兴趣的:(day19,分布式事务,java,测试工具)