多线程MySql数据库中任务项的Java任务调度

多线程MySql数据库中任务项的Java任务调度,java,mysql,spring,scheduled-tasks,quartz-scheduler,Java,Mysql,Spring,Scheduled Tasks,Quartz Scheduler,我正在用JavaSpring编写一个任务调度模块来处理存储在Mysql数据库中的任务项 任务表的架构结构: 我想实现多个任务调度器工作程序,以便从任务表中获取要执行的任务。如何确保任务调度器不会同时执行相同的任务?有什么好的java框架我可以使用吗 编辑1: 任务执行模块设计为由不同的机器运行,因此同步方法可能无法工作 编辑2: 每台机器将获得随机或不规则数量的任务。因此,如果使用自动递增序列,索引的分配大小也应该是不规则的,否则将有一些任务永远无法处理 编辑3: 每台机器都使用Quartz调度

我正在用JavaSpring编写一个任务调度模块来处理存储在Mysql数据库中的任务项

任务表的架构结构:

我想实现多个任务调度器工作程序,以便从任务表中获取要执行的任务。如何确保任务调度器不会同时执行相同的任务?有什么好的java框架我可以使用吗

编辑1: 任务执行模块设计为由不同的机器运行,因此同步方法可能无法工作

编辑2: 每台机器将获得随机或不规则数量的任务。因此,如果使用自动递增序列,索引的分配大小也应该是不规则的,否则将有一些任务永远无法处理

编辑3:
每台机器都使用Quartz调度程序运行,配置了一个获取和执行作业的常量任务。每个作业之间的时间间隔约为10秒。因此,我的目标是确保每个计算机调度器在每个quartz作业运行中至少可以获取10个任务。

您可以将getTask方法创建为同步方法:

例如:

编辑1:
如果是这样,只需使用SELECT FOR UPDATE查询来阻止其他查询以访问同一任务。 例如:


您可以创建一个过程来包装查询。

您可以像这样解决原子性或事务问题


使用任务的id,假设它是增量的。如果有三台机器运行任务调度。然后只需将id修改为3,并将结果为0、1、2的任务分配给固定的机器。因此,不同的机器不会相互干扰或竞争条件

mysql是一种非常繁重的方法,所以我想知道它是在一个进程中运行,还是多台机器可以调度和/或执行任务?如果是这种情况,则无法与synchronized一起工作。@MrR您是对的。该模块将由多台机器或集群运行。因此@Kaguya说多台机器/集群-因此数据库是确保跨多台机器的多个用户不能获得相同任务的方法。使用查询更新下一个要运行的任务-返回详细信息,并设置为“正在运行”。@MrR如果两台计算机要将同一任务更新为“正在运行”,该怎么办?在这种情况下会有竞争条件吗?如果是,只需使用SELECT FOR UPDATE query来阻止其他查询以访问相同的任务。例如:从任务t中选择*,其中t.status=由t创建的新订单\u ts LIMIT 1进行更新;更新任务集状态=正在处理,其中id=。您可以创建一个过程来包装查询。使用数据库中事务的原子性。例如,添加一个任务调度器id列并将其设置为空(如果为空),就可以做到这一点。如果在事务中完成,那么@Erk建议添加另一列,该列实际上是标识任务正在处理的机器的ID…那么暂停/失败/机器处理失败/等等的任务呢。?你是怎么对付他们的?我问问题是为了帮助你回答/帮助我们所有人回答。@MrR,是的,可能还需要时间戳列和超时处理。@Kaguya除非你需要一个主控器,否则DB是你的定序器,所以任何机器都可以请求下一个任务,只有1个会得到它。这是个聪明的主意。当我们假设每台并行机都受到高可用性特性的保护时,您的方法就会起作用。它还充当任务处理的负载平衡器。
ID | TASK_UUID | TASK_CONTENT(VARCHAR) | CREATED_TS | UPDATED_TS | STATUS(NEW/PROCESSING/COMPLETE)
synchronized Task getTask() {
  // get NEW task from DB
  // update status to PROCESSING
  // return task
}
SELECT * FROM Task t WHERE t.status = NEW ORDER BY t.created_ts LIMIT 1 FOR UPDATE;
UPDATE Task SET status = PROCESSING WHERE id = <the task id> .