
详细提问:
目前已启用的解决办法:
Redis 开启 Key 失效 Event,服务以长连接监听事件推送。
考虑到意外,DB 也构建了一张“任务表”,用于存储任务结束时间戳,玩家每次登录时,检测存在的时间戳数据,如果有,则自动执行并清理时间戳数据( Redis 回调时,也会清理时间戳数据)。
1 Jooooooooo 2021 年 7 月 6 日 延迟任务就是有个系统在帮忙轮询 一个简单的做法是把每一秒当成一个 key, 任务挂在这个 key 上, 然后弄个系统用比如 100ms 的速度去轮询这个 key, 发现上面有任务就用消息触发 |
2 qq316107934 2021 年 7 月 6 日 把任务按照时间顺序插入一个有序列表中,每隔 N 段时间扫描列表头,发现到了时间就出列读下一个。如果任务很多的话可以把任务按照时间段分块插入 上述内容都可以用 redis 实现 你用发布订阅的话,可能留坑 |
3 uiosun OP @Jooooooooo 大佬,所有新增任务都挂在对应的 key 的已有 value 后面,用符号分割,每分钟查询对应 60 秒的任务,批量执行应该就可以?!我去试试 @qq316107934 大佬,如果 Redis 宕机了,又没有开持久化,这部分数据是不是就没了?当前情况下,只能靠那个 DB 的方式去救火 |
4 uiosun OP |
5 Jooooooooo 2021 年 7 月 6 日 |
6 EscYezi 2021 年 7 月 6 日 via iPhone 尝试一下延时队列?比如 rabbitmq (用的不多但是有这个功能) |
7 qq316107934 2021 年 7 月 6 日 @uiosun #3 可以写日志,出了问题回扫日志;如果不想离线扫,需要加上 DB/Redis 双写,检测到 Redis 宕机数据源就切换到 DB,然后定时 where 开始执行时间戳 < 现在时间 + 扫描时间间隔,效果一样的,但要注意 Redis 和 DB 间的任务状态同步。 |
8 CEBBCAT 2021 年 7 月 6 日 也没有考虑过延时队列?比如楼上说的 rabbitmq 或者 beanstalk ? 听起来这个 Y 任务也有一点意思,因为赶路是需要占据时间的吧? |
9 crystom 2021 年 7 月 6 日 redis 专门搞个消费者取 zset,生产者则用 zset 分数存时间和任务 |
10 akira 2021 年 7 月 6 日 dau 1.5w ,每个用户假设每天是 10 个任务,每日总任务数量大约是 15w 做个数据表,待记录执行时间,任务编号,执行标记 以及其他必要信息, 然后定时器一直扫就好了。 再做个定期清理 足够了 |
11 woolong800 2021 年 7 月 6 日 延迟队列吧,可以用 rabbitmq,或者自己基于 redis 的 sorted set 写一个 |
12 triptipstop 2021 年 7 月 6 日 时间轮 |
13 Rocketer 2021 年 7 月 7 日 标准做法是死信队列。 具体来说就是,把队列的超时处理方式设为转移至另一个队列(这就是所谓的死信队列),然后任务入队时设置超时(就是需要的延时)。 这样任务需要执行时就会因为超时而自动进入死信队列,你的任务执行程序从死信队列里取就行了。这样做的好处是纯异步,即使需要执行的任务突然来了很多也不怕,有死信队列帮你削峰呢。 |
14 aguesuka 2021 年 7 月 7 日 HashedWheelTimer 的算法可以在允许少量误差的情况下实现 O(1) 级别的定时任务的插入, 删除, 和弹出. |
15 Alexf4 2021 年 7 月 7 日 用 celery 任务的 eta 参数,可以了解下 |
16 cctrv 2021 年 8 月 20 日 via iPhone Crontab 以每 1 小定行一指定本(你的程序) 然後,程序可以取到之前的安排的任,判是否足行件,始理。 |