背景
用于用户自主创建定时任务,规则存储到 Redis 或者 MySQL, 服务端根据规则定时处理
目前的想法
自己实现一个时间轮,秒为单位或 100 毫秒为单位
自己实现的主要疑问

如果单机的情况下,用户会集中在某个时刻执行任务,当前卡槽相对应的队列数据比较多,我将数据推送到队列中异步消费,队列繁忙时,时效性是个问题,用户体验不好。
极端的情况下,可能存在用户在每秒都重复执行某个任务,那么任务都存放每个卡槽中,我感觉不合理,有更优的解决办法吗?

了解过 xxl-job ,我觉得不适合我的场景,不知道理解是否有误,求指点。

根据你的 title ,从数据库/缓存里面拉最新的规则,解析成 cron 表达式,再去修改定时 job 的 cron ,xxl-job 可以满足啊。你觉的哪里不适合?

xxl-job 可以满足你的需求,可以仔细看看 xxl-job 调度中心的 JobScheduleHelper 的业务逻辑。里面有两个核心的线程,一个是用来调度的线程,会一直扫表,看表中哪些任务该执行了;还有一个是时间轮线程,主要是向触发器线程池提交触发任务的。

按照之前的经验来说,xxl-job 应该是可以满足需求的。我的理解是你这里的后端一共需要三个服务,①业务后端,②xxl-job 管理端,③任务执行器,大致如下。1. 部署好服务,在 [xxl-job 管理端] 配置好你的任务执行器,参考 xxl-job 的文档,用 Bean 运行模型就可以2. 用户通过 [业务后端] 创建任务,后端创建任务的逻辑中调用 [xxl-job 管理端] 创建对应的任务,并启动任务,返回任务 id 记录到 [业务后端] 中3. [xxl-job 管理端] 会根据任务的调度配置去触发 [任务执行器] 执行具体的业务。用 xxl-job 的好处就是你只需要实现你的业务逻辑,关于定时任务的管理和调度他都做好了。

主要还是每次去拉取数据库比较耗资源,这里的规则会非常多,加上可能需要更小单位定时任务。

非常感谢,那我研究研究 xxl-job

PowerJob

juejin.cn/post/7150156954394951694

temporal 的 schedule ,好像很适合

apscheduler

这个也不错,我看看文档,谢谢 robfig/cron 之前也用过,但是感觉普通的 cron 这种,满足不了我的需求,谢谢 谢谢,我了解了解。

抱歉,刚才没细看。“用户自主创建定时任务”,竟然允许用户创建自定义的定时任务?? 10W 个用户就完全可以出现 10W 个自定义的定时任务?看你们现在的用户量了,xxl-job 似乎有点不合适了。建议考虑下 RocketMQ 的延时任务,不断的消费再重投递,实现定时轮询的功能。Apache 开源的 4.8 以上,好像支持 14 小时内的任意延时了(如果有预算的话,直接买阿里云的 MQ 吧,延迟支持更全面)

是 24 小时

我们是用于物联网,他会有智能场景,设置定时任务。终端设备没有计算能力的话, 会依赖于服务端发送指令。

关于第二步,“后端创建任务的逻辑中调用 [xxl-job 管理端] 创建对应的任务”,xxl-job 我怎么看没有接口调用添加的,必须手动添加,是这样吗?

用 xxl-job 没遇到过类似你这样的场景。看需要服务端支持的设备数量了,xxl-job 的话,小几千应该可以搞定,上 W 我不清楚了,你可以试试。

支持 http 的添加的,你在 admin 页面可以拿到各个接口的 curl 的。干脆你直接读写 admin 的数据库吧,这样最方便。

#14其实看看 xxl-admin 的登录逻辑,做个爬虫也很简单的

使用 MQ 的延迟消息是否可行

你说的这个场景,小米就是这么做的,但是问题真的很多很多,你这个应该主要还是服务端多投入硬件资源了,市面上大部份解决方案应该都是可以满足的,我之前做过类似的场景,如果不想延时太大,就增加服务端硬件投入,增大服务端的并发能力,尽可能保证任务执行不会被耽误就好了不过你的任务应该都是比较恒定的,服务端只是生成指令下发,没有最终的任务执行,应该是比较好根据任务并发量来评估

最近遇到和你一样的场景,纠结调研了比较久。想法是:多个后端业务,负责管理用户不同业务下的定时,定时创建到定时服务,包括业务回调地址。定时服务管理 corn ,触发后直接 call 回调地址给业务后端处理。定时服务本身自己设计一个通用接口,后面的实现可以根据用户量阶段调整。目前了解了几个方案:1 是自己实现时间轮,根据时间轮大小定期轮询数据库,可以结合其他来源 job 处理分布式分片; 2 是 quartz ,小数据量性能还行,可以前期快速搭建业务; 3 是 elastic-job ,可以手动添加,背后基于 quartz 做的。4 是 xxl-job ,xxl-job 不能动态创建复杂的,新版本定时是时间轮实现,但是 xxl 可以动态创建 http 类型的 job ,可以把 cron 服务 http 回调放在 xxl 里面

之前看小米还是美团的一个实现,就是利用 mq 延迟队列做

是的,如果我自己实现时间轮,我的想法是,我当前卡槽的数据投递到队列,让队列进行消费,如果需要足够快,就需要增加消费能力。能说说大概会遇到的问题吗?

segmentfault.com/a/1190000022783535 看过这方案吗? 朋友他们公司的思路非常完整了。就是没有开源。关于 1, 我现在的理解,是不是不应该去轮训数据,启动服务的时候,直接维护这个卡槽的队列,可以维护在 redis 中,然后,到了时间时,直接新开启一个线程/协程去投递队列,然后消费的服务进行消费。你们这边确定方案了吗? 可以多交流交流

延时队列我感觉也可行,我找找看他们说的小米美团的方案。

多谢解惑

这个过程,可能产品设计上要注意,比如说时间粒度不能太细,最终任务的逻辑不能过于复杂,尽量不要出现相互依赖的任务等等,这些都会带来服务端或者设备端的各种问题,建议你们先做,遇到问题了再做一些修正就是了

好的。谢谢

生成任务和消费任务是两码事,不要混为一谈

1.异步队列基本不存在时效性问题,有的话是你使用不当造成的2.每秒都重复执行任务不适合大规模任务系统,需要采用其他方式3.时间轮太多任务导致效率低的话可以考虑层级时间轮4. xxl-job 本质是一个伪分布式,实质是单机的任务工具,对你的需求没有任何帮助

我这里也有这种场景,用户可以设置一段时间内的定时任务,量也不大,就用 go 的 channel 来做定时,每隔一段时间往 channel 发一个消息,调度器去数据库拉取这段时间需要执行的任务,然后交给 worker 执行因为我这里量不大而且对时间不用太敏感(允许有 1-2 分钟的偏差),所以就自己写了一个简单的 github.com/Mystery00/go-job

谢谢,很受用 谢谢,我参考参考。1-2 分钟对于我们来说可能有点接受不了。你现在时间偏差是因为消费不够及时的原因吗?