V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
kanhongj
V2EX  ›  问与答

定时发布任务技术的思考

  •  
  •   kanhongj · 2021-09-24 13:17:22 +08:00 · 1649 次点击
    这是一个创建于 916 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有这个问题主要描述如下:


    问题点:

    1. A 和 B 甚至更多用户, 在不同时间点需要执行一项任务,那么如何有效率的判断时间点已经到了, 然后执行任务(轮询判断?或者是信号量?还是定时器?)

    2. 如何记录[保存] 1 中的未执行任务(数据库?),以及需要执行的时间点


    场景举例:

    用户 A 希望在 1:00 1:43 ... 10:08 里各时间点发布一条消息,且每一条消息独立

    用户 B 希望在 1:06 2:08 ... 11:13 里各时间点发布一条消息,且每一条消息独立

    用户 C ......


    个人想法:

    1. 假如限制用户设定的定时任务数量(最多 10 条), 那么在数据库里就需要存储 10 条消息,以及其时间点,但是若用户数量增加,那么数据量也会变得很大
    2. 同时,若每个用户有一个(轮询)判断时间点是否符合的线程,那么用户数量增多也会使得系统负载过高,若使用信号量 /定时器(这个是对任务的), 那么一个用户下最多会产生 10 条定时器,这也会负载过高。

    希望有好的方法可以交流一下, 或者交流一下涉及的技术栈,谢谢浏览的各位

    14 条回复    2021-09-26 09:03:46 +08:00
    sqfphoenix
        1
    sqfphoenix  
       2021-09-24 15:20:07 +08:00
    延时消息?
    Jooooooooo
        2
    Jooooooooo  
       2021-09-24 15:24:36 +08:00
    事先生成好任务+轮询
    christopheredwar
        3
    christopheredwar  
       2021-09-24 15:29:13 +08:00
    airflow
    LemonK
        4
    LemonK  
       2021-09-24 16:39:09 +08:00   ❤️ 1
    每个用户 10 条,按 mysql 单表性能,你有百万用户才勉强算数据量大。
    定时时间是一次性,发过之后这条数据就不用了,那么可以按时间滚动分表,一天一张一月一张都行。
    发送就更简单,一个线程轮询,比如每分钟把下一分钟要发的消息拉回内存里,再秒级轮询从内存发就行了。
    这都用不着算负载,除非单条消息内容量特别大,不然每分钟发万条以上再考虑性能吧。
    ch2
        5
    ch2  
       2021-09-24 16:46:19 +08:00
    io 密集型任务还是 cpu 密集型?
    后者多机多线程,前者用协程,不行再上多机多进程+协程
    用一个表直接把任务全记下来,定期由 schedule 分发任务给 worker 执行
    kkkkkrua
        6
    kkkkkrua  
       2021-09-24 17:09:21 +08:00   ❤️ 1
    不建议只依赖轮询,精度可以轮询时间不好把控,可以用定时大轮询拿到一批执行信息后,用延迟消息处理
    cairnechen
        7
    cairnechen  
       2021-09-24 17:17:48 +08:00
    微博定时的限制是 20 条
    simbaCheng
        8
    simbaCheng  
       2021-09-24 17:27:35 +08:00
    存储(数据库、redis) 不是啥问题,主要是如何有效判断时间是否到达,那就试试时间轮。
    clf
        9
    clf  
       2021-09-24 17:32:07 +08:00
    消息队列延迟消息就行。中间要取消就把消息队列里的这条消息给去掉。
    guodong110
        10
    guodong110  
       2021-09-24 17:39:04 +08:00
    搞一个统一调度系统。先生成好任务给系统,让系统进行调度。调度系统原理就是轮询任务[![4Dej8H.jpg]( https://z3.ax1x.com/2021/09/24/4Dej8H.jpg)]( https://imgtu.com/i/4Dej8H)
    yufpga
        11
    yufpga  
       2021-09-24 18:43:47 +08:00
    redis sorted set (有序集合), 任务 id 作为集合的内容, 任务执行时间(时间戳)作为 score; 消费者从有序集合中拿最近需要执行的那个任务, 判断是否到期, 到期就执行, 没有到期继续等待
    Mystery0
        12
    Mystery0  
       2021-09-25 01:17:47 +08:00 via Android
    借贴请问有比较成熟的框架或者应用吗,目前这种需求是使用 redis 有序集合来做的,多副本情况下可能会把任务重复执行
    cyaki
        13
    cyaki  
       2021-09-25 08:27:15 +08:00 via Android
    ActiveMQ, RabbitMQ, Plusar,AWS 的 SQS 都支持延迟任务调度
    tedzhou1221
        14
    tedzhou1221  
       2021-09-26 09:03:46 +08:00 via iPhone
    我也做的是和 #4 一样

    我是半小时轮询拉数据,然后放到 netty 时间轮去秒级处理。
    小系统,数据量不大,半小时也没多少数据

    延时消息处理方案,美团技术团队网站、有赞的技术网站都有文章。

    再不行就去参考:
    RocketMQ, Dubbo RPC 模块 等源码
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3444 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 11:11 · PVG 19:11 · LAX 04:11 · JFK 07:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.