你知道Redis可以实现延迟队列吗? redis zset 延迟队列
wptr33 2024-12-27 17:15 19 浏览
推荐阅读:
- 基于springboot、tio、oauth2.0前端vuede 超轻量级聊天软件分享
- 基于Spring Cloud微服务化开发脚手架平台源码免费分享
- 基于springboot2.0跟layui构建的前后端分离后台管理系统源码分享
最近,又重新学习了下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 查询最早的一条任务,来进行消费。
总的来说,你可以通过以下两种方式来实现((*^▽^*)如果你想到其他方法,也可以告诉我下呀~):
- 使用zrangebyscore来查询当前延时队列中所有任务,找出所有需要进行处理的延时任务,在依次进行操作。
- 查找当前最早的一条任务,通过score值来判断任务执行的时候是否大于了当前系统的时候,比如说:最早的任务执行时间在3点,系统时间在2点58分),表示这个应该需要立马被执行啦,时间快到了(冲冲冲,他来了他来了,他带着死神的步伐来了)。
我们可以想一想Redis来实现延时队列有何优势呢?
其实,Redis用来进行实现延时队列是具有这些优势的:
- Redis zset支持高性能的 score 排序。
- Redis是在内存上进行操作的,速度非常快。
- Redis可以搭建集群,当消息很多时候,我们可以用集群来提高消息处理的速度,提高可用性。
- Redis具有持久化机制,当出现故障的时候,可以通过AOF和RDB方式来对数据进行恢复,保证了数据的可靠性
这时候,会有小伙伴问了还有没有其他实现延时队列的方式呀!emmm....当然有的,只有想不到的没有做不到(O(∩_∩)O哈哈~,开玩笑)
一、用消息中间件实现延时队列
(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时间才允许从队列中取出。这种实现方式是数据保存在内存中,可能面临数据丢失的情况,同时它是无法支持分布式系统的。
相关推荐
- 【推荐】一款开源免费、美观实用的后台管理系统模版
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍...
- Android架构组件-App架构指南,你还不收藏嘛
-
本指南适用于那些已经拥有开发Android应用基础知识的开发人员,现在想了解能够开发出更加健壮、优质的应用程序架构。首先需要说明的是:AndroidArchitectureComponents翻...
- 高德地图经纬度坐标批量拾取(高德地图批量查询经纬度)
-
使用方法在桌面上新建一个index.txt文件,把下面的代码复制进去保存,再把文件名改成index.html保存,双击运行打开即可...
- flutter系列之:UI layout简介(flutter ui设计)
-
简介对于一个前端框架来说,除了各个组件之外,最重要的就是将这些组件进行连接的布局了。布局的英文名叫做layout,就是用来描述如何将组件进行摆放的一个约束。...
- Android开发基础入门(一):UI与基础控件
-
Android基础入门前言:...
- iOS的布局体系-流式布局MyFlowLayout
-
iOS布局体系的概览在我的CSDN博客中的几篇文章分别介绍MyLayout布局体系中的视图从一个方向依次排列的线性布局(MyLinearLayout)、视图层叠且停靠于父布局视图某个位置的框架布局(M...
- TDesign企业级开源设计系统越发成熟稳定,支持 Vue3 / 小程序
-
TDesing发展越来越好了,出了好几套组件库,很成熟稳定了,新项目完全可以考虑使用。...
- WinForm实现窗体自适应缩放(winform窗口缩放)
-
众所周知,...
- winform项目——仿QQ即时通讯程序03:搭建登录界面
-
上两篇文章已经对CIM仿QQ即时通讯项目进行了需求分析和数据库设计。winform项目——仿QQ即时通讯程序01:原理及项目分析...
- App自动化测试|原生app元素定位方法
-
元素定位方法介绍及应用Appium方法定位原生app元素...
- 61.C# TableLayoutPanel控件(c# tabcontrol)
-
摘要TableLayoutPanel在网格中排列内容,提供类似于HTML元素的功能。TableLayoutPanel控件允许你将控件放在网格布局中,而无需精确指定每个控件的位置。其单元格...
- 12个python数据处理常用内置函数(python 的内置函数)
-
在python数据分析中,经常需要对字符串进行各种处理,例如拼接字符串、检索字符串等。下面我将对python中常用的内置字符串操作函数进行介绍。1.计算字符串的长度-len()函数str1='我爱py...
- 如何用Python程序将几十个PDF文件合并成一个PDF?其实只要这四步
-
假定你有一个很无聊的任务,需要将几十个PDF文件合并成一个PDF文件。每一个文件都有一个封面作为第一页,但你不希望合并后的文件中重复出现这些封面。即使有许多免费的程序可以合并PDF,很多也只是简单的将...
- Python入门知识点总结,Python三大数据类型、数据结构、控制流
-
Python基础的重要性不言而喻,是每一个入门Python学习者所必备的知识点,作为Python入门,这部分知识点显得很庞杂,内容分支很多,大部分同学在刚刚学习时一头雾水。...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
面试官:git pull是哪两个指令的组合?
-
git pull命令使用实例 git pull--rebase
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mysql max (33)
- vba instr (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)