城市直播房产教育博客汽车
投稿投诉
汽车报价
买车新车
博客专栏
专题精品
教育留学
高考读书
房产家居
彩票视频
直播黑猫
投资微博
城市上海
政务旅游

如何实现延迟队列(JDKmysqlredisRabbit)

3月11日 醉殇别投稿
  何为延迟队列
  队列,即先进先出的数据结构,就和食堂打饭一样,排在最前面的先打饭,打完饭就走;延迟队列即队列中的元素相比以往多了一个属性特征:延迟。延迟队列中的每个元素都指定了延迟时间,表示该元素到达指定时间之后将出队进行处理。其实从上述定义来看,与其说是延迟队列,不如说它是一个以时间为权重的最小堆结构。
  那么延迟队列有什么用呢?我们生活中其实平时接触到很多可以使用延迟队列来解决的例子:订单超时30分钟未付款将自动关闭会议系统中,会议开始前10分钟,发送会议提醒夏天晚上时,我们经常会给空调设置指定时长的时间,到时空调自动关闭再比如微波炉、烤箱、等等
  可以发现延迟队列想要实现的功能其实就是一个定时任务调度的一种。延迟队列实现方式
  延迟队列实现的方式有很多种,具体采用哪种去实现,和我们的业务背景、业务诉求都息息相关,不同的实现方式都有其适用的应用场景,我这里将延迟队列分为两类:单机延迟队列和分布式延迟队列。1。单机实现
  JDK提供了DelayedQueue可以实现延迟队列的目的。其类图如下:
  可以看到DelayedQueue是一个阻塞队列,其队列中的元素必须实现Delayed接口:publicinterfaceDelayedextendsComparableDelayed{longgetDelay(TimeUnitunit);}
  其中getDelay返回代表该元素的一个在队列中可存在的时间,通过这种方式来实现元素的延迟弹出。接下来看订单超时30秒将自动关闭的实际例子:publicclassJDKDelayQueueTest{privatestaticfinalDateTimeFormatterFORMATTERDateTimeFormatter。ofPattern(yyyyMMddHH:mm:ss);privatestaticfinalDelayQueueOrderDELAYQUEUEnewDelayQueue();privatestaticfinalExecutorServiceEXECUTORSERVICEExecutors。newFixedThreadPool(2);publicstaticvoidmain(String〔〕args)throwsException{EXECUTORSERVICE。submit((){while(true){if(!DELAYQUEUE。isEmpty()){OrderorderDELAYQUEUE。poll();if(order!null){System。out。println(order。getOrderId()超时关闭与:FORMATTER。format(LocalDateTime。now()));}}TimeUnit。MILLISECONDS。sleep(1000);}});EXECUTORSERVICE。submit((){try{DELAYQUEUE。add(newOrder(黄焖鸡订单));TimeUnit。SECONDS。sleep(5);DELAYQUEUE。add(newOrder(麻辣香锅订单));TimeUnit。SECONDS。sleep(10);DELAYQUEUE。add(newOrder(石锅拌饭订单));}catch(Exceptione){}});}publicstaticclassOrderimplementsDelayed{privatefinalLocalDateTimeexpireTprivatefinalStringorderId;publicOrder(StringorderId){this。expireTimeLocalDateTime。now()。plusSeconds(30);this。orderIdorderId;System。out。println(orderId创建于:FORMATTER。format(LocalDateTime。now()));}OverridepubliclonggetDelay(TimeUnitunit){returnLocalDateTime。now()。isAfter(expireTime)?1:1;}OverridepublicintcompareTo(DelayedtargetOrder){谁的过期时间最早谁就排最前面returnthis。expireTime。isBefore(((Order)targetOrder)。getExpireTime())?1:1;}publicStringgetOrderId(){returnorderId;}publicLocalDateTimegetExpireTime(){returnexpireT}}}
  输出:黄焖鸡订单创建于:2021082118:26:30麻辣香锅订单创建于:2021082118:26:35石锅拌饭订单创建于:2021082118:26:45黄焖鸡订单超时关闭与:2021082118:27:00麻辣香锅订单超时关闭与:2021082118:27:05石锅拌饭订单超时关闭与:2021082118:27:15DelayQueue实现方式小结
  这种方式的优点就是实现简单,不复杂,但是其缺点也比较多:不具备可扩展性,内存限制、无持久化机制,数据容易丢失。
  分布式实现2。数据库轮询
  数据库论询的方式相对而言也比较好理解,后台启动定时任务每隔一段时间扫描指定的数据库表每一行数据,获取出到达指定延迟时间的行进行处理,所以使用该方式重要的就三个要素:
  1)捞取任务
  扫描数据库的后台任务,可以使用分布式任务去扫,比如A任务扫描limit0,100满足条件的数据行,B任务扫描limit100,200满足条件的数据行
  2)执行任务
  一般来说讲究分工协作,第一步中的分布式线程任务专门用来捞取任务,那么捞取到的任务可以再次扔给另外专门用户处理任务的线程中
  3)数据库表设计
  可以在表中增加一个字段来表示延迟时间,比如针对上面的订单超时30秒关闭,我们可以增加一个字段timeout,可以是此时间的毫秒数来记录订单的超时时间,那么此时我们的SQL就可以是:selectfromorderwhere{now}timeoutlimit{start},100;
  数据库轮询实现方式小结
  采用这种方式可以看到首先我们需要查询数据库,那么查询数据库就意味着存在查询耗时,那么可能最终导致的就是实时性不高,但是它的优点在于天生满足任务持久化机制,不用担心延迟任务丢失。3。通过Redis实现
  Redis的五大数据类型中的zset数据类型中,包含一个称为score的属性,该数据类型中所有元素都会按照score进行排序,所以如果将score作为我们的延迟时间的时间戳,那么我们可以通过命令Zrangebyscore来获取满足条件的数据,然后交给我们的任务处理线程去处理,其实整个实现思想和数据库轮循是一样的,只不过数据存储结构由数据库转变成了redis,准确来说redis也是数据库,只不过不同的存储结构带来的影响就是适用场景的不同罢了。
  那么如果通过Redis来实现延迟队列,大概会有如下几步:
  1)增加任务zaddtasks{过期时间戳}{任务相关数据}
  2)捞取任务ZRANGEBYSCOREtasksinf{当前时间戳}WITHSCORES
  捞取过期时间早于当前时间的这部分任务
  3)执行任务接下来就是执行,这个就没什么好说的了
  关于rediszset数据结构以及命令可以看这里:https:www。runoob。comredisredissortedsets。html一些优化点
  1。在添加延迟任务时,可以通过对任务id进行hash分散至多个rediskey,可以避免所有任务存储在一个key中导致大key从而影响元素的添加和查找性能
  2。每个key独自拥有一个线程处理
  3。每个key的线程只负责拉取需要处理的数据,然后再转发至消息队列中,不做任何其他处理,可以提升处理速度,消息消费者可扩展性好,性能不够,机器来凑redis实现方式小结
  redis因为其都是内存中操作,所以查询插入速度和mysql来比都是非常快的,所以实时性会比mysql高,虽然redis也能满足任务数据的持久化,但是无法保证任务不丢失,所以这里持久性会比mysql稍弱一点
  4。使用消息队列
  我们可以采用rabbitMQ的延时队列。RabbitMQ具有以下两个特性,可以实现延迟队列RabbitMQ可以针对Queue和Message设置xmessagett,来控制消息的生存时间,如果超时,则消息变为deadletterlRabbitMQ的Queue可以配置xdeadletterexchange和xdeadletterroutingkey(可选)两个参数,用来控制队列内出现了deadletter,则按照这两个参数重新路由。结合以上两个特性,就可以模拟出延迟消息的功能。TimeToLiveExtensions
  RabbitMQ允许我们为消息或者队列设置TTL(timetolive),也就是过期时间。TTL表明了一条消息可在队列中存活的最大时间,单位为毫秒。也就是说,当某条消息被设置了TTL或者当某条消息进入了设置了TTL的队列时,这条消息会在经过TTL秒后死亡,成为DeadLetter。如果既配置了消息的TTL,又配置了队列的TTL,那么较小的那个值会被取用。更多资料请查阅官方文档。DeadLetterExchange
  刚才提到了,被设置了TTL的消息在过期后会成为DeadLetter。其实在RabbitMQ中,一共有三种消息的死亡形式:消息被拒绝。通过调用basic。reject或者basic。nack并且设置的requeue参数为false。消息因为设置了TTL而过期。消息进入了一条已经达到最大长度的队列。
  如果队列设置了DeadLetterExchange(DLX),那么这些DeadLetter就会被重新publish到DeadLetterExchange,通过DeadLetterExchange路由到其他队列。不同实现方式的对比
  实现方式
  复杂度
  数据量
  持久化,数据丢失
  扩展性
  实时性
  jdkDelayQueue
  简单
  由于程序内存限制,适用于少数据量
  无持久化
  差
  高
  mysql轮询
  稍微复杂
  可支持大数据量
  可保证持久化,保证任务不丢失
  可扩展
  由于查询开销,稍弱
  rediszet
  稍微复杂
  可支持大数据量
  可尽量保证持久化,不保证任务不丢失
  可扩展
  高
  RabbitMQ
  稍微复杂
  可支持大数据量
  可保证持久化,保证任务不丢失
  可扩展
  高结语
  除了以上实现方式,还有其他比如通过RabbitMQ的TTL和死信队列来实现:每一个消息带有TTL属性,该TTL即延迟任务的延迟时间,只要超过指定时间没被消费,此消息将被转至死信队列中,我们可以监听死信队列消费消息进而达到延迟任务的目的;还有时间轮转算法等,时间有限,日后再学,日后再讲。
投诉 评论 转载

中草药洗面奶有哪些洗面奶中部分游离态表面活性剂具有润湿、分散、发泡、去污、乳化五大作用,是洁面品的主要活性物。在洗面过程中,协同油相物与水相物共同除去污垢、油彩、脂粉、美容化妆品残迹等。若在洗面……蓝军代理主帅考虑过去的事没用,我们需专注接下来的比赛切尔西此前官宣波特下课,布鲁诺萨尔托日前接受了采访。他谈到了自己带领球队的感受以及未来的展望。布鲁诺表示:这并非是我的决定,这是俱乐部做出的决定,俱乐部要求我在这个时刻展……回顾长影经典电影男儿要远行男人岛上的动人故事《男儿要远行》是由广布道尔基执导的剧情片,由长春电影制片厂出品,马昌钰、林强、梁同裕主演。影片讲述了几个海上石油勘探工人,为找油甘愿牺牲了青春、爱情与生命的故事。在远离陆……小脸精华成分olay小脸精华成分近几年新出了一个词叫小奶狗指的是和比自己年纪小的男生谈恋爱可是如果是肌肤松弛、没有弹性注定得不到小奶狗心所以做好面部保养尤为重……英媒狼队对签下塞巴略斯很感兴趣,并在准备一份足以考虑的报价直播吧4月5日讯塞巴略斯与皇马的合同将在6月30日结束,到目前为止,他还没有续约。据《每日体育报》援引英媒90min报道,狼队对签下塞巴略斯非常感兴趣,并正在准备一份足以让球员……闭目造句用闭目造句大全91、一路上刘建新与袁奇志唧唧哝哝地,浑然把老孟杨陆顺当不存在,杨陆顺也就闭目假寐,迷糊间听老孟说:“刘总,前面有人在挥手,我看着象老全呀?”。92、这些年轻的和尚一个个……比特币跌破20000美元,硅谷银行连累了加密市场?切勿急着抄底。最近一周,或许是加密市场自FTX崩溃以来最糟糕的一周。在拜登的最新预算案和Silvergate的倒闭风波之后,硅谷银行为加密市场再次带来重磅冲击。在不……二十年后回故乡转眼间,我三十岁生日了。大学毕业后,我考上国家公务员,一直在官场上奋斗,现在的我官至国家副主席。由于我每天日理万机,已经有许多年没有回到阔别已久的故乡了,我决定这一次回家看看父……官方MVP榜约基奇连续10期榜首,恩比德第二NBA官网公布了最新一期的MVP榜单:尼克拉约基奇连续10期占据榜首,本赛季他场均得到24。3分、11。8个篮板、10次助攻。乔尔恩比德从第四升至第二,本赛季场均得……网络时代的隐忧你的思想已被悄悄控制了吗?网络是如何一步步控制人类的?随着互联网的不断发展,网络已经渗透到了我们生活的方方面面,无论是工作、学习还是娱乐都已经离不开它。然而,网络作为一种技术手段,也在逐渐地控制着……如何实现延迟队列(JDKmysqlredisRabbit)何为延迟队列队列,即先进先出的数据结构,就和食堂打饭一样,排在最前面的先打饭,打完饭就走;延迟队列即队列中的元素相比以往多了一个属性特征:延迟。延迟队列中的每个元素都指定……小田鼠的背带裤小田鼠穿着背带裤出门了,他对朋友们说:妈妈给我做的背带裤,挺好看吧?一只野兔走过来,扯着小田鼠的背带裤说:背带裤真漂亮,让我穿一下好吗?好的。小田鼠快乐地答应了。……
黄维恢复自由后到香港买了一本书,视若珍宝,每天晚上都要读一读陶瓷背板颜值超高,小米13Pro上手体验高成长企业论达晨财智肖冰科技安全是当下最受关注的投资主题认识药品风热感冒,咽喉肿痛药清凉喉片杨紫好像有一张娃娃脸,都快30岁了,却看着还像个女大学生Epic圣诞喜加一!Remedy佳作Control一键入库为什么要在申时约茶?贝克汉姆晒一家六口圣诞照女儿可爱像爸爸,3个儿子全像妈民营火箭首次实现一箭多星发射郭士强开局打的好,但个人单打独斗过多科学家用第三种方法测量出中子寿命887秒苹果开创ARM处理器性能新高,华为跟随开发PC处理器清晨背着书包,牵着小手,迎着朝阳向世界道一声早安理财没到期急用钱怎么办微信摇一摇王者荣耀皮肤永久英雄免费得绿萝观察记气质灯笼泡泡马尾辫低马尾编发扎发教程图解看病顺安辞呈赵使君二首新生儿败血症的后遗症有哪些俯瞰黄河小,高悬白雪清。意思翻译、赏析老人的穿衣会影响老人的心情吗用独当一面造句大全攻克光子芯片制程中多项核心工艺陕西先进光子器件工程创新平台全

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找