作者:_BKing

地址:www.cnblogs.com/xiaowei123/p/13222710.html

最近,又重新学习了下Redis,深深被Redis的魅力所折服,Redis不仅能快还能慢(我想也这么优秀o(╥﹏╥)o),简直利器呀

咳咳咳,大家不要误会,本文很正经的啦!伙伴们跟我一起冲呀,我们一起去爬爬这座延时队列的山峰,探一探它究竟到底有高。

那接下来开始我们的旅行啦~,我们都知道Redis是一种基于内存的单进程单线程数据库(Redis6.0开始之后支持多线程啦!),处理速度都非常快。

那么为何Redis又能慢呢?原来,这里说的慢是指Redis可以设置一些参数达到慢处理的结果。(这就是为什么Redis既能快又能慢啦!)

那接下来开始讲讲我们的Redis在队列中如何实现延时的情况:

在我们日常生活中,我们可以发现:

  • 在淘宝、京东等购物平台上下单,超过一定时间未付款,订单会自动取消。

  • 打车的时候,在规定时间没有车主接单,平台会取消你的单并提醒你暂时没有车主接单。

  • 点外卖的时候,如果商家在10分钟还没接单,就会自动取消订单。

  • 收快递的时候,如果我们没有点确认收货,在一段时间后程序会自动完成订单。

  • 在平台完成订单后,如果我们没有在规定时间评论商品,会自动默认买家不评论。

  • .......

这时,我们可以想想为什么要这样做?

因为这样可以保证商品的库存可以释放给其他人购买,你可以不用一直等待打车却得不到回复,你可以及时换一家店点到外卖。

那么这些情况都是如何实现的呢?

这时我们可以看看这个图,来看看消息延迟是如何处理的:

当用户发送一个消息请求给服务器后台的时候,服务器会检测这条消息是否需要进行延时处理,如果需要就放入到延时队列中,由延时任务检测器进行检测和处理,对于不需要进行延时处理的任务,服务器会立马对消息进行处理,并把处理后的结果返会给用户。

对于在延时任务检测器内部的话,有查询延迟任务和执行延时任务两个职能,任务检测器会先去延时任务队列进行队列中信息读取,判断当前队列中哪些任务已经时间到期并将已经到期的任务输出执行(设置一个定时任务)。

这时,我们可以想一想在Redis的数据结构中有哪些能进行时间设置标志的命令?

是不是想到的 zset 这个命令,具有去重有序(分数排序)的功能。没错,你想对了呀!

我们可以使用 zset(sortedset)这个命令,用设置好的时间戳作为score进行排序,使用 zadd score1 value1 ....命令就可以一直往内存中生产消息。再利用 zrangebysocre 查询符合条件的所有待处理的任务,通过循环执行队列任务即可。也可以通过 zrangebyscore key min max withscores limit 0 1 查询最早的一条任务,来进行消费。

总的来说,你可以通过以下两种方式来实现((^▽^)如果你想到其他方法,也可以告诉我下呀~):

(1)使用zrangebyscore来查询当前延时队列中所有任务,找出所有需要进行处理的延时任务,在依次进行操作。

(2)查找当前最早的一条任务,通过score值来判断任务执行的时候是否大于了当前系统的时候,比如说:最早的任务执行时间在3点,系统时间在2点58分),表示这个应该需要立马被执行啦,时间快到了(冲冲冲,他来了他来了,他带着死神的步伐来了)。

我们可以想一想Redis来实现延时队列有何优势呢?

其实,Redis用来进行实现延时队列是具有这些优势的:

  1. Redis zset支持高性能的 score 排序。

  2. Redis是在内存上进行操作的,速度非常快。

  3. Redis可以搭建集群,当消息很多时候,我们可以用集群来提高消息处理的速度,提高可用性。

  4. Redis具有持久化机制,当出现故障的时候,可以通过AOF和RDB方式来对数据进行恢复,保证了数据的可靠性

这时候,会有小伙伴问了还有没有其他实现延时队列的方式呀!emmm....当然有的,只有想不到的没有做不到。关注公众号Java技术栈回复福利可以获取一份最新面试题资料。

一、用消息中间件实现延时队列

(1)通过 RabbitMQ 来实现延时队列

方法一:在MQ中我们可以对Queue设置 x-expires 过期时间或者对 Message设置超时时间x-message-ttl。

(这里要注意下:延时相同的消息我们要扔到同一个队列中,对于每一个延时要建立一个与之对应的队列—这是由于MQ的过期检测是惰性检测的。)

方法二:我们可以用RabbitMQ的插件rabbitmq-delayed-message-exchange插件来实现延时队列。达到可投递时间时并将其通过 x-delayed-type 类型标记的交换机类型投递至目标队列。

(2)RocketMQ实现延时队列

rocketmq在发送延时消息时,是先把消息按照延迟时间段发送到指定的队列中(把延时时间段相同的消息放到同一个队列中,保证了消息处理的顺序性,可以让同一个队列中消息延时时间是相同的,整个RocketMQ中延时消息时按照递增顺序排序,保证信息处理的先后顺序性。)。之后,通过一个定时器来轮询处理这些队列里的信息,判断是否到期。对于到期的消息会发送到相应的处理队列中,进行处理。

注意 :目前RocketMQ只支持特定的延时时间段,1s,5s,10s,...2h,不能支持任意时间段的延时设置。有兴趣的小伙伴可以去了解下它是相关知识呀~

二、Kafka实现延时队

Kafka基于时间轮自定义了一个用于实现延迟功能的定时器(SystemTimer),Kafka中的时间轮(TimingWheel)是一个存储定时任务的环形队列,可以进行相关的延时队列设置。

三、Netty实现延时队列

Netty也有基于时间轮算法来实现延时队列。Netty在构建延时队列主要用HashedWheelTimer,HashedWheelTimer底层数据结构是使用DelayedQueue,采用时间轮的算法来实现。

四、DelayQueue来实现延时队列

Java中有自带的DelayQueue数据类型,我们可以用这个来实现延时队列。DelayQueue是封装了一个PriorityQueue(优先队列),在向DelayQueue队列中添加元素时,会给元素一个Delay(延迟时间)作为排序条件,队列中最小的元素会优先放在队首,对于队列中的元素只有到了Delay时间才允许从队列中取出。这种实现方式是数据保存在内存中,可能面临数据丢失的情况,同时它是无法支持分布式系统的。

冲冲冲,小伙伴们!又是美好的一天。

Redis 实现延迟队列?深深被折服!!相关推荐

  1. 如何用 Redis 实现延迟队列?

    如何用 Redis 实现延迟队列? - 前言 - 我们都知道Redis是一种基于内存的单进程单线程数据库(Redis6.0开始之后支持多线程啦! ),处理速度都非常快. 那么为何Redis又能慢呢? ...

  2. 用redis实现延迟队列

    现在在用的redis实现延迟队列的主流程

  3. php redis zset 延迟队列_PHP + Redis 实现简单消息队列

    Redis做消息队列的好处在于它的轻量级,高并发,延迟敏感. 应用场景有即时数据分析.秒杀计数器.缓存等. Redis做消息队列待解决的问题: 1.消息的可靠性: 没有相应的机制保证消息的消费,当消费 ...

  4. Redis实现延迟队列

    有赞延迟队列设计 延迟队列,顾名思义它是一种带有延迟功能的消息队列. 那么,是在什么场景下我才需要这样的队列呢? 背景 我们先看看以下业务场景: 当订单一直处于未支付状态时,如何及时的关闭订单,并退还 ...

  5. Redis的延迟队列实现,我瞅一眼

    最近,又重新学习了下Redis,深深被Redis的魅力所折服,Redis不仅能快还能慢(我想也这么优秀o(╥﹏╥)o),简直利器呀 咳咳咳,大家不要误会,本文很正经的啦!伙伴们跟我一起冲呀,我们一起去 ...

  6. php redis zset 延迟队列_用PHP+Redis实现延迟任务,实现自动取消订单

    简单定时任务解决方案:使用redis的keyspace notifications(键失效后通知事件) 需要注意此功能是在redis 2.8版本以后推出的,因此你服务器上的reids最少要是2.8版本 ...

  7. Redis实现排行榜、延迟队列、LRU、消息已读未读(Redisson客户端实现)

    目录 序言 Redis客户端选型 Redis配置 Redis实现排行榜 Redis实现延迟队列 Redis LRU(Least Recently Used)使用 Redis实现消息已读未读 总结 序言 ...

  8. 你真的知道怎么实现一个延迟队列吗 ?

    作者:xiewang,腾讯 IEG 运营开发工程师 前言 延迟队列是我们日常开发过程中,经常接触并需要使用到的一种技术方案.前些时间在开发业务需求时,我也遇到了一个需要使用到延迟消息队列的需求场景,因 ...

  9. redis延迟队列 实现_灵感来袭,基于Redis的分布式延迟队列(续)

    背景 上一篇(灵感来袭,基于Redis的分布式延迟队列)讲述了基于Java DelayQueue和Redis实现了分布式延迟队列,这种方案实现比较简单,应用于延迟小,消息量不大的场景是没问题的,毕竟J ...

最新文章

  1. Get started with ros -- 1
  2. python if语句多个条件-python if条件判断语句
  3. 博客文章的置顶功能『博客帮助』
  4. 012_HttpServletResponse响应乱码
  5. 扩展内容(进程的通信方式)
  6. FineBI学习系列之FineBI的Windows里安装步骤(图文详解)
  7. 靖江机器人怎么样_铁饭碗不保?靖江可能消失的12大职业!快看有你的工作没?...
  8. MySQL实战—更新过程
  9. 17.立体匹配——匹配问题,好区域匹配 测验,窗口大小的影响,遮蔽(Occlusion),顺序约束_2
  10. 如何使用EasyRecovery的监控硬盘功能
  11. ZOJ 1010. Area 解题报告
  12. 8片74151扩展为64选1数据选择器
  13. 3步解决AS提示:Compilation is not supported for following modules
  14. oracle正则表达式匹配字母,oracle正则表达式函数 匹配
  15. Chrome(谷歌浏览器) 程序开发32个常用插件
  16. QT创建文件夹并在文件夹下创建文件
  17. Oracle将收购Sun公司
  18. 2012春节回乡见闻
  19. C语言--自定义字符串输入/输出函数
  20. fest3d_AssertJ Fest Hamcrest

热门文章

  1. Qt安装和QML HelloWord程序
  2. Stanford UFLDL教程 矢量化编程
  3. Flink开发环境搭建(maven)
  4. tp3.2.3运用phpexcel将excel文件导入mysql数据库
  5. HDU 5821 Ball
  6. 类成员指针和0x0地址转换
  7. 《火球——UML大战需求分析》(第2章 耗尽脑汁的需求分析工作)——2.3 给客户带来价值,需求分析之正路...
  8. 【腾讯第二届校园编程马拉松】HDU-4525,威威猫系列故事——吃鸡腿
  9. 通讯系统经验谈【一】TCP连接状态分析:SYNC_RECV,CLOSE_WAIT,TIME_WAIT
  10. TCP三次握手协议和SYN攻击以及DDOS简介