当前位置:首页 > 科技  > 软件

数十万定时任务,如何高效触发定时和超时

来源: 责编: 时间:2023-11-07 09:14:10 402观看
导读项目产品中,大家都会有"定时任务"和"定时超时"的需求,初始阶段,我们基本都是用少数的一些timer,即使是任务量越来越大的时候,我们就难免维护着大量的timer,或者进行了大量低效的扫描。定时任务使用场景:当订单一直处于未支付

项目产品中,大家都会有"定时任务"和"定时超时"的需求,初始阶段,我们基本都是用少数的一些timer,即使是任务量越来越大的时候,我们就难免维护着大量的timer,或者进行了大量低效的扫描。kuC28资讯网——每日最新资讯28at.com

kuC28资讯网——每日最新资讯28at.com

定时任务使用场景:当订单一直处于未支付状态时,如何及时的关闭订单(已经使用)kuC28资讯网——每日最新资讯28at.com

如何定期检查处于退款状态的订单是否已经退款成功(后期重构使用)kuC28资讯网——每日最新资讯28at.com

kuC28资讯网——每日最新资讯28at.com

设计方案:kuC28资讯网——每日最新资讯28at.com

  • 整个Redis当做消息池,以KV形式存储消息
  • 使用ZSET做优先队列,按照Score维持优先级
  • 使用LIST结构,以先进先出的方式消费
  • ZSET和LIST存储消息地址(对应消息池的每个KEY)
  • 使用定时器维护路由
  • 根据TTL规则实现消息延迟

kuC28资讯网——每日最新资讯28at.com

咱们公司现阶段就是使用的这套方法:kuC28资讯网——每日最新资讯28at.com

1.新增一个job,会job_pool中插入一条数据,记录了业务方消费方。也会在bucket插入一条记录,记录执行的时间戳kuC28资讯网——每日最新资讯28at.com

2.搬运线程会去bucket中查找哪些执行时间戳的RunTimeMillis比现在的时间小,将这些记录全部删除;同时会解析出每个任务的Topic是什么,然后将这些任务PUSH到TOPIC对应的列表queue中kuC28资讯网——每日最新资讯28at.com

3每个topic的list都会有一个监听线程去批量获取list中的待消费数据,获取到的数据全部扔给这个topic的消费线程池kuC28资讯网——每日最新资讯28at.com

4.消费线程池执行会去job_pool查找数据结构,返回给回调结构,执行回调方法。kuC28资讯网——每日最新资讯28at.com

kuC28资讯网——每日最新资讯28at.com

图片图片kuC28资讯网——每日最新资讯28at.com

待优化的内容:kuC28资讯网——每日最新资讯28at.com

  1. 目前只有一个Queue队列存放消息,当需要消费的消息大量堆积后,会影响消息通知的时效。改进的办法是,开启多个Queue,进行消息路由,再开启多个消费线程进行消费,提供吞吐量
  2. 消息没有进行持久化,存在风险,后续会将消息持久化到MongoDB中

一般来说还有什么其他方法实现这类需求呢?kuC28资讯网——每日最新资讯28at.com

“轮询扫描法”kuC28资讯网——每日最新资讯28at.com

1.用一个Map<uid, last_packet_time>来记录每一个uid最近一次请求时间last_packet_timekuC28资讯网——每日最新资讯28at.com

2.当某个用户uid有请求包来到,实时更新这个MapkuC28资讯网——每日最新资讯28at.com

3.启动一个timer,当Map中不为空时,轮询扫描这个Map,看每个uid的last_packet_time是否超过30s,如果超过则进行超时处理kuC28资讯网——每日最新资讯28at.com

kuC28资讯网——每日最新资讯28at.com

“多timer触发法”kuC28资讯网——每日最新资讯28at.com

1.用一个Map<uid, last_packet_time>来记录每一个uid最近一次请求时间last_packet_timekuC28资讯网——每日最新资讯28at.com

2.当某个用户uid有请求包来到,实时更新这个Map,并同时对这个uid请求包启动一个timer,30s之后触发kuC28资讯网——每日最新资讯28at.com

3.每个uid请求包对应的timer触发后,看Map中,查看这个uid的last_packet_time是否超过30s,如果超过则进行超时处理kuC28资讯网——每日最新资讯28at.com

方案一:只启动一个timer,但需要轮询,效率较低kuC28资讯网——每日最新资讯28at.com

方案二:不需要轮询,但每个请求包要启动一个timer,比较耗资源kuC28资讯网——每日最新资讯28at.com

kuC28资讯网——每日最新资讯28at.com

ZSet(有序集合)数据结构来实现kuC28资讯网——每日最新资讯28at.com

  1. 创建ZSet:首先,你需要创建一个ZSet数据结构,其中每个订单将作为一个成员,其分数将表示订单的创建时间戳。你可以使用Redis等支持ZSet的数据库来实现。
  2. 添加订单:每当用户创建新订单时,将订单添加到ZSet中,其中成员是订单ID,分数是订单的创建时间戳。
  3. 定时检查订单:定期(例如,每分钟)执行一个程序或定时任务来检查ZSet中的订单。你可以使用程序来查询ZSet,找到创建时间超过一定时间阈值的订单,表示它们长时间未支付。
  4. 取消订单:对于那些长时间未支付的订单,可以将其从ZSet中删除,并执行取消订单的操作(例如,将订单状态设置为"已取消")。

kuC28资讯网——每日最新资讯28at.com

import redis.clients.jedis.Jedis;import redis.clients.jedis.Tuple;import java.util.Set;public class OrderCancellationSystem {    public static void main(String[] args) {        Jedis jedis = new Jedis("localhost"); // 连接到本地Redis服务器        // 模拟添加订单        addOrder(jedis, "Order1");        addOrder(jedis, "Order2");        // 定时任务,每分钟检查订单并自动取消        while (true) {            cancelLongUnpaidOrders(jedis);            try {                Thread.sleep(60000); // 等待一分钟再次检查            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void addOrder(Jedis jedis, String orderId) {        long currentTime = System.currentTimeMillis();        jedis.zadd("orders", currentTime, orderId);    }    public static void cancelOrder(String orderId) {        // 执行取消订单操作,例如更新订单状态        System.out.println("Cancelling order: " + orderId);    }    public static void cancelLongUnpaidOrders(Jedis jedis) {        long expirationTime = System.currentTimeMillis() - 3600 * 1000; // 60分钟前的时间戳        Set<Tuple> longUnpaidOrders = jedis.zrangeByScoreWithScores("orders", "-inf", String.valueOf(expirationTime));        for (Tuple order : longUnpaidOrders) {            String orderId = order.getElement();            cancelOrder(orderId);            jedis.zrem("orders", orderId); // 从ZSet中删除已取消的订单        }    }}

kuC28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-17398-0.html数十万定时任务,如何高效触发定时和超时

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 了解 Go 中原子操作的重要性与使用方法

下一篇: Istio Envoy 配置解读,看这篇就够了

标签:
  • 热门焦点
  • K60 Pro官方停产 第三方瞬间涨价

    虽然没有官方宣布,但Redmi的一些高管也已经透露了,Redmi K60 Pro已经停产且不会补货,这一切都是为了即将到来的K60 Ultra铺路,属于厂家的正常操作。但有意思的是该机在停产之后
  • Redmi Pad评测:红米充满野心的一次尝试

    从Note系列到K系列,从蓝牙耳机到笔记本电脑,红米不知不觉之间也已经形成了自己颇有竞争力的产品体系,在中端和次旗舰市场上甚至要比小米新机的表现来得更好,正所谓“大丈夫生居
  • 一篇聊聊Go错误封装机制

    %w 是用于错误包装(Error Wrapping)的格式化动词。它是用于 fmt.Errorf 和 fmt.Sprintf 函数中的一个特殊格式化动词,用于将一个错误(或其他可打印的值)包装在一个新的错误中。使
  • 梁柱接棒两年,腾讯音乐闯出新路子

    文丨田静 出品丨牛刀财经(niudaocaijing)7月5日,企鹅FM发布官方公告称由于业务调整,将于9月6日正式停止运营,这意味着腾讯音乐长音频业务走向消亡。腾讯在长音频领域还在摸索。为
  • 华为将推出盘古数字人大模型 可帮助用户12小时完成数字人生成

    在今日举行的2023年华为云数字文娱AI创新峰会上,华为云全球Marketing与销售服务总裁石冀琳表示,华为云将在后续推出盘古数字人大模型,可帮助用户12小
  • OPPO K11搭载长寿版100W超级闪充:26分钟充满100%

    据此前官方宣布,OPPO将于7月25日也就是今天下午14:30举办新品发布会,届时全新的OPPO K11将正式与大家见面,将主打旗舰影像,和同档位竞品相比,其最大的卖
  • SN570 NVMe SSD固态硬盘 价格与性能兼具

    SN570 NVMe SSD固态硬盘是西部数据发布的最新一代WD Blue系列的固态硬盘,不仅闪存技术更为精进,性能也得到了进一步的跃升。WD Blue SN570 NVMe SSD的包装外
  • 世界人工智能大会国际日开幕式活动在世博展览馆开启

    30日上午,世界人工智能大会国际日开幕式活动在世博展览馆开启,聚集国际城市代表、重量级院士专家、国际创新企业代表,共同打造人工智能交流平台。上海市副市
  • “买真退假” 这种“羊毛”不能薅

    □ 法治日报 记者 王春   □ 本报通讯员 胡佳丽  2020年初,还在上大学的小东加入了一个大学生兼职QQ群。群主&ldquo;七王&rdquo;在群里介绍一些刷单赚
Top