我正在构建一个系统,用户可以在其中设置日历中的 future 日期(精确到小时和分钟)。在那个日期,触发器调用特定任务,对每个用户都是唯一的。
每个用户都可以设置不同的日期。系统一开始会有 10k+,用户可以创建多个触发器。
假设我有 1 万个用户,每个用户平均创建 3 个触发器 => 3 万个触发器,有 3 万个不同的日期。
所有日期都保存在数据库中。
我是 quartz 的新手,能否以更优化的方式完成此操作?
我正在考虑让任务每分钟运行一次,以获取假设在下一个小时运行的任务并将它们从数据库中删除。
你有更好的想法吗?是否有人将 quartz 用于大量触发器。
最佳答案
您已将时间表备份在数据库中。如果我理解这个想法 - 您希望 quartz 加载所有即将到来的任务以在将来执行它们。
这是有问题的方法:
同步问题:我假设用户可以编辑、删除和向数据库添加新任务。您将不得不定期要求数据库刷新 quartz 作业的状态、删除一些作业、编辑其他作业等。这可能不是微不足道的。程序的状态将是一个长期存在的缓存,需要经常同步。
性能和可扩展性问题:即使建议的解决方案可能适用于 30K 任务,但可能不适用于 70k 或 700k 任务。在您的方法中,扩展并不容易 - 添加新机器需要额外的同步层 - 哪台机器应该实际执行哪个作业(因为它们都有所有任务)。
我的建议:
- 将“阶段”添加到任务表(新的、排队的、运行的、完成的、失败的)
- 将您的解决方案分成几个部分。 (最初它们可以在一台机器上运行,但很容易扩展)
组件:
任务查找器:定期执行(每隔几秒执行一次)。扫描数据库以查找"new"且即将到期的任务。将找到的任务发送到 Message Queue,并在数据库中将任务标记为“已排队”。标记为“排队”必须小心,因为可能有多个“任务查找器”。 (此外,它可能会发现 N 分钟前标记为“排队”或“正在运行”且未“完成”或“取消”的任务 - 可能需要重新运行这些任务)
Message Queue:Taks Finder 和Task Executor 之间的连接器。
任务执行器:监听消息队列并处理它收到的任务。最初将任务标记为“正在运行”,稍后标记为“已完成”或“失败”。
通过这种方法,您可以:
- 多台机器上的多个任务执行器
- 多台机器上的多个任务计划程序
- 即使其中一个任务计划程序或执行程序失败,它也不会是单点故障。有些任务会被延迟,但会被拾起并在之后运行。
这可能无法解决所有情况,但会是一个很好的起点。
关于java, quartz 和特定时间触发的多个任务保存在数据库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39497667/