java,quartz和在特定时间触发的多个任务保存在数据库中

2022-09-04 22:04:53

我正在构建一个系统,用户可以在日历中设置未来的日期(减少到小时和分钟)。在该日期,触发器正在调用某个任务,该任务对于每个用户都是唯一的。

每个用户都可以设置不同的日期。系统从一开始就有10k+,用户可以创建多个触发器。

因此,假设我有 10000 个用户,每个用户平均创建 3 个触发器 = > 30k 个具有不同日期的 30k 触发器。

所有日期都保存在数据库中。

我是石英的新手,这能以更优化的方式完成吗?

我正在考虑让一个任务每分钟运行一次,该任务将获得假设在下一个小时内运行的任务,并将其从数据库中删除。

你有什么更好的想法吗?是否有人使用石英进行大量触发。


答案 1

数据库中已备份计划。如果我理解这个想法 - 您希望石英加载所有即将执行的任务,以便在将来执行它们。

这是有问题的方法:

  1. 同步问题:我假设用户可以编辑、删除新任务以及向数据库中添加新任务。您必须定期要求数据库刷新石英作业的状态,删除一些作业,编辑其他作业等。这可能不是微不足道的。程序的状态将是一个需要经常同步的长寿命缓存。

  2. 性能和可伸缩性问题:即使建议的解决方案对于30K任务可能没问题,但对于70k或700k任务也可能不行。在您的方法中,扩展并不容易 - 添加新计算机将需要额外的同步层 - 哪台计算机应该实际执行哪个作业(因为它们都有所有任务)。

我的建议是:

  • 将“阶段”添加到“任务”表中(新建、已排队、正在运行、已完成、失败)
  • 将解决方案划分为多个组件。(最初它们可以在一台计算机上运行,但很容易扩展)

组件:

  • 任务查找器:定期执行(每隔几秒钟执行一次)。扫描数据库中是否有“新”且即将到期的任务。将找到的任务发送到消息队列,并在数据库中将任务标记为“已排队”。标记为“排队”必须小心完成,因为可能有多个“任务查找器”。(作为补充,它可能会找到在N分钟前标记为“排队”或“正在运行”并且未“完成”或“取消”的任务 - 可能需要重新运行这些任务)

  • 消息队列Taks Finder任务执行器之间的连接器。

  • 任务执行器:侦听消息队列并处理它接收到的任务。最初将任务标记为“正在运行”,稍后标记为“已完成”或“失败”。

使用这种方法,您可以:

  • 多台计算机上的多个任务执行器
  • 多台计算机上的多个任务计划程序
  • 即使其中一个任务计划程序或执行程序将失败,它也不会是单点故障。一些任务将被延迟,但它将被拾取并在之后运行。

这可能无法解决所有情况,但将是一个很好的起点。


答案 2

我不明白为什么你在这里需要石英。据我所知,quartz最好用于调度后端内部进程,而不是从数据库获得的用户定义任务。

只需在创建触发器时对其进行处理,根据触发器将一行保存到表中,然后每秒选择所有未完成的任务,< sysdate。如果作业正在重复,请计算下一个执行时间并相应地插入新的任务行/更新上一个任务。tasksstart_datestart_date


推荐