怎么让一个任务在发起后的第 6 个小时,自动执行? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
uiosun
V2EX    编程

怎么让一个任务在发起后的第 6 个小时,自动执行?

  •  
  •   uiosun 2021 年 7 月 6 日 3315 次点击
    这是一个创建于 1741 天前的主题,其中的信息可能已经有所发展或是发生改变。

    详细提问:

    1. 场景是游戏,日活跃用户 1.5 万。
    2. 每个用户会发起多个“X 小时后执行 Y 任务”,X 范围 1~72 ; Y 包含且不限于“种地”、“建房”、“赶路”等动作;
    3. 服务器性能有限。

    目前已启用的解决办法:

    Redis 开启 Key 失效 Event,服务以长连接监听事件推送。

    考虑到意外,DB 也构建了一张“任务表”,用于存储任务结束时间戳,玩家每次登录时,检测存在的时间戳数据,如果有,则自动执行并清理时间戳数据( Redis 回调时,也会清理时间戳数据)。

    16 条回复    2021-08-20 13:20:07 +08:00
    Jooooooooo
        1
    Jooooooooo  
       2021 年 7 月 6 日   1
    延迟任务就是有个系统在帮忙轮询

    一个简单的做法是把每一秒当成一个 key, 任务挂在这个 key 上, 然后弄个系统用比如 100ms 的速度去轮询这个 key, 发现上面有任务就用消息触发
    qq316107934
        2
    qq316107934  
       2021 年 7 月 6 日   1
    把任务按照时间顺序插入一个有序列表中,每隔 N 段时间扫描列表头,发现到了时间就出列读下一个。如果任务很多的话可以把任务按照时间段分块插入

    上述内容都可以用 redis 实现

    你用发布订阅的话,可能留坑
    uiosun
        3
    uiosun  
    OP
       2021 年 7 月 6 日
    @Jooooooooo 大佬,所有新增任务都挂在对应的 key 的已有 value 后面,用符号分割,每分钟查询对应 60 秒的任务,批量执行应该就可以?!我去试试

    @qq316107934 大佬,如果 Redis 宕机了,又没有开持久化,这部分数据是不是就没了?当前情况下,只能靠那个 DB 的方式去救火
    uiosun
        4
    uiosun  
    OP
       2021 年 7 月 6 日
    @Jooooooooo @qq316107934
    我都试试,哪种更适合就用哪种。实在是感谢两位大佬了。

    ( 10 铜币感谢,小小心意)
    Jooooooooo
        5
    Jooooooooo  
       2021 年 7 月 6 日   1
    @uiosun 比如 redis 的 list 结构, 你把任务都 append 进去

    至于稳定性相关的问题, 如果是一个完整的延迟任务系统, 确实是需要用 db 去搞的, 缓存只能是小打小闹的方案
    EscYezi
        6
    EscYezi  
       2021 年 7 月 6 日 via iPhone   1
    尝试一下延时队列?比如 rabbitmq (用的不多但是有这个功能)
    qq316107934
        7
    qq316107934  
       2021 年 7 月 6 日   1
    @uiosun #3 可以写日志,出了问题回扫日志;如果不想离线扫,需要加上 DB/Redis 双写,检测到 Redis 宕机数据源就切换到 DB,然后定时 where 开始执行时间戳 < 现在时间 + 扫描时间间隔,效果一样的,但要注意 Redis 和 DB 间的任务状态同步。
    CEBBCAT
        8
    CEBBCAT  
       2021 年 7 月 6 日
    也没有考虑过延时队列?比如楼上说的 rabbitmq 或者 beanstalk ?

    听起来这个 Y 任务也有一点意思,因为赶路是需要占据时间的吧?
    crystom
        9
    crystom  
       2021 年 7 月 6 日
    redis 专门搞个消费者取 zset,生产者则用 zset 分数存时间和任务
    akira
        10
    akira  
       2021 年 7 月 6 日   1
    dau 1.5w ,每个用户假设每天是 10 个任务,每日总任务数量大约是 15w

    做个数据表,待记录执行时间,任务编号,执行标记 以及其他必要信息,
    然后定时器一直扫就好了。

    再做个定期清理 足够了
    woolong800
        11
    woolong800  
       2021 年 7 月 6 日
    延迟队列吧,可以用 rabbitmq,或者自己基于 redis 的 sorted set 写一个
    triptipstop
        12
    triptipstop  
       2021 年 7 月 6 日
    时间轮
    Rocketer
        13
    Rocketer  
       2021 年 7 月 7 日   1
    标准做法是死信队列。

    具体来说就是,把队列的超时处理方式设为转移至另一个队列(这就是所谓的死信队列),然后任务入队时设置超时(就是需要的延时)。

    这样任务需要执行时就会因为超时而自动进入死信队列,你的任务执行程序从死信队列里取就行了。这样做的好处是纯异步,即使需要执行的任务突然来了很多也不怕,有死信队列帮你削峰呢。
    aguesuka
        14
    aguesuka  
       2021 年 7 月 7 日
    HashedWheelTimer 的算法可以在允许少量误差的情况下实现 O(1) 级别的定时任务的插入, 删除, 和弹出.
    Alexf4
        15
    Alexf4  
       2021 年 7 月 7 日
    用 celery 任务的 eta 参数,可以了解下
    cctrv
        16
    cctrv  
       2021 年 8 月 20 日 via iPhone
    Crontab 以每 1 小定行一指定本(你的程序)

    然後,程序可以取到之前的安排的任,判是否足行件,始理。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4227 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 05:22 PVG 13:22 LAX 22:22 JFK 01:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86