电商网站设计公司皆选亿企邦dux5.0 WordPress

pingmian/2026/1/23 22:13:35/文章来源:
电商网站设计公司皆选亿企邦,dux5.0 WordPress,网站邮件推送,邯郸教育行业网站建设MQ 延迟队列 1. 前言 延迟队列是我们日常开发过程中#xff0c;经常接触并需要使用到的一种技术方案。前些时间在开发业务需求时#xff0c;我也遇到了一个需要使用到延迟消息队列的需求场景#xff0c;因此我也在网上调研了一系列不同的延迟队列的实现方案#xff0c;在…MQ 延迟队列 1. 前言 延迟队列是我们日常开发过程中经常接触并需要使用到的一种技术方案。前些时间在开发业务需求时我也遇到了一个需要使用到延迟消息队列的需求场景因此我也在网上调研了一系列不同的延迟队列的实现方案在此进行了一个总结并且给大家进行分享。 2. 延迟队列定义 首先队列这种数据结构相信大家都不陌生它是一种先进先出的数据结构。普通队列中的元素是有序的先进入队列中的元素会被优先取出进行消费 延时队列相比于普通队列最大的区别就体现在其延时的属性上普通队列的元素是先进先出按入队顺序进行处理而延时队列中的元素在入队时会指定一个延迟时间表示其希望能够在经过该指定时间后处理。从某种意义上来讲延迟队列的结构并不像一个队列而更像是一种以时间为权重的有序堆结构。 3. 应用场景 我在开发业务需求时遇到的使用场景是这样的用户可以在小程序中订阅不同的微信或者 QQ 的模板消息产品同学可以在小程序的管理端新建消息推送计划当到达指定的时间节点的时候给所有订阅模板消息的用户进行消息推送。 如果仅仅是服务单一的小程序那也许起个定时任务或者甚至人工的定时去执行能够最便捷最快速的去完成这项需求但我们希望能够抽象出一个消息订阅的模块服务出来给所有业务使用这时候就需要一种通用的系统的解决方案这时候便需要使用到延迟队列了。 除了上述我所遇到的这样的典型的需求以外延迟队列的应用场景其实也非常的广泛比如说以下的场景 新建的订单如果用户在 15 分钟内未支付则自动取消。公司的会议预定系统在会议预定成功后会在会议开始前半小时通知所有预定该会议的用户。安全工单超过 24 小时未处理则自动拉企业微信群提醒相关责任人。用户下单外卖以后距离超时时间还有 10 分钟时提醒外卖小哥即将超时。 对于数据量比较少并且时效性要求不那么高的场景一种比较简单的方式是轮询数据库比如每秒轮询一下数据库中所有数据处理所有到期的数据比如如果我是公司内部的会议预定系统的开发者我可能就会采用这种方案因为整个系统的数据量必然不会很大并且会议开始前提前 30 分钟提醒与提前 29 分钟提醒的差别并不大。 但是如果需要处理的数据量比较大实时性要求比较高比如淘宝每天的所有新建订单 15 分钟内未支付的自动超时数量级高达百万甚至千万这时候如果你还敢轮询数据库怕是要被你老板打死不被老板打死估计也要被运维同学打死。 这种场景下就需要使用到我们今天的主角 —— 延迟队列了。延迟队列为我们提供了一种高效的处理大量需要延迟消费消息的解决方案。那么话不多说下面我们就来看一下几种常见的延迟队列的解决方案以及他们各自的优缺点。 4. 实现方案 Redis ZSet 我们知道 Redis 有一个有序集合的数据结构 ZSetZSet 中每个元素都有一个对应 ScoreZSet 中所有元素是按照其 Score 进行排序的。 那么我们可以通过以下这几个操作使用 Redis 的 ZSet 来实现一个延迟队列 入队操作ZADD KEY timestamp task, 我们将需要处理的任务按其需要延迟处理时间作为 Score 加入到 ZSet 中。Redis 的 ZAdd 的时间复杂度是O(logN)N是 ZSet 中元素个数因此我们能相对比较高效的进行入队操作。 起一个进程定时比如每隔一秒通过ZREANGEBYSCORE方法查询 ZSet 中 Score 最小的元素具体操作为ZRANGEBYSCORE KEY -inf inf limit 0 1 WITHSCORES。查询结果有两种情况 a. 查询出的分数小于等于当前时间戳说明到这个任务需要执行的时间了则去异步处理该任务b. 查询出的分数大于当前时间戳由于刚刚的查询操作取出来的是分数最小的元素所以说明 ZSet 中所有的任务都还没有到需要执行的时间则休眠一秒后继续查询 同样的ZRANGEBYSCORE操作的时间复杂度为 O(logN M) 其中N为 ZSet 中元素个数M为查询的元素个数因此我们定时查询操作也是比较高效的。 这里从网上搬运了一套 Redis 实现延迟队列的后端架构其在原来 Redis 的 ZSet 实现上进行了一系列的优化使得整个系统更稳定、更健壮能够应对高并发场景并且具有更好的可扩展性是一个挺不错的架构设计其整体架构图如下 其核心设计思路 将延迟的消息任务通过 hash 算法路由至不同的 Redis Key 上这样做有两大好处 a. 避免了当一个 KEY 在存储了较多的延时消息后入队操作以及查询操作速度变慢的问题两个操作的时间复杂度均为O(logN)。b. 系统具有了更好的横向可扩展性当数据量激增时我们可以通过增加 Redis Key 的数量来快速的扩展整个系统来抗住数据量的增长。 每个 Redis Key 都对应建立一个处理进程称为 Event 进程通过上述步骤 2 中所述的 ZRANGEBYSCORE 方法轮询 Key查询是否有待处理的延迟消息。 所有的 Event 进程只负责分发消息具体的业务逻辑通过一个额外的消息队列异步处理这么做的好处也是显而易见的 a. 一方面Event 进程只负责分发消息那么其处理消息的速度就会非常快就不太会出现因为业务逻辑复杂而导致消息堆积的情况。b. 另一方面采用一个额外的消息队列后消息处理的可扩展性也会更好我们可以通过增加消费者进程数量来扩展整个系统的消息处理能力。 Event 进程采用 Zookeeper 选主单进程部署的方式避免 Event 进程宕机后Redis Key 中消息堆积的情况。一旦 Zookeeper 的 leader 主机宕机Zookeeper 会自动选择新的 leader 主机来处理 Redis Key 中的消息。 从上述的讨论中我们可以看到通过 Redis Zset 实现延迟队列是一种理解起来较为直观可以快速落地的方案。并且我们可以依赖 Redis 自身的持久化来实现持久化使用 Redis 集群来支持高并发和高可用是一种不错的延迟队列的实现方案。 5. 实现方案 RabbitMQ RabbitMQ 本身并不直接提供对延迟队列的支持我们依靠 RabbitMQ 的 TTL 以及 死信队列 功能来实现延迟队列的效果。那就让我们首先来了解一下RabbitMQ 的死信队列以及 TTL 功能。 5.1 死信队列 死信队列实际上是一种 RabbitMQ 的消息处理机制当 RabbmitMQ 在生产和消费消息的时候消息遇到如下的情况就会变成“死信” 消息被拒绝basic.reject/ basic.nack 并且不再重新投递 requeuefalse消息超时未消费也就是 TTL 过期了消息队列到达最大长度 消息一旦变成一条死信便会被重新投递到死信交换机Dead-Letter-Exchange然后死信交换机根据绑定规则转发到对应的死信队列上监听该队列就可以让消息被重新消费。 5.2 消息生存时间 TTL TTLTime-To-Live是 RabbitMQ 的一种高级特性表示了一条消息的最大生存时间单位为毫秒。如果一条消息在 TTL 设置的时间内没有被消费那么它就会变成一条死信进入我们上面所说的死信队列。 有两种不同的方式可以设置消息的 TTL 属性一种方式是直接在创建队列的时候设置整个队列的 TTL 过期时间所有进入队列的消息都被设置成了统一的过期时间一旦消息过期马上就会被丢弃进入死信队列参考代码如下 MapString, Object args new HashMapString, Object(); args.put(x-message-ttl, 6000); channel.queueDeclare(queueName, durable, exclusive, autoDelete, args);在延迟队列的延迟时间为固定值的时候比较适合使用这种方式。 另一种方式是针对单条消息设置参考代码如下该消息被设置了 6 秒的过期时间 AMQP.BasicProperties.Builder builder new AMQP.BasicProperties.Builder(); builder.expiration(6000); AMQP.BasicProperties properties builder.build(); channel.basicPublish(exchangeName, routingKey, mandatory, properties, msg content.getBytes());如果需要不同的消息设置不同的延迟时间上面针对队列的 TTL 设置便无法满足我们的需求需要使用这种针对单个消息的 TTL 设置。 不过需要注意的是使用这种方式设置的 TTL消息可能不会按时死亡因为 RabbitMQ 只会检查第一个消息是否过期。比如这种情况第一个消息设置了 20s 的 TTL第二个消息设置了 10s 的 TTL那么 RabbitMQ 会等到第一个消息过期之后才会让第二个消息过期。 解决这个问题的方法也很简单只需要安装 RabbitMQ 的一个插件即可 https://www.rabbitmq.com/community-plugins.html 安装好这个插件后所有的消息就都能按照被设置的 TTL 过期了。 5.3 RabbitMQ 实现延迟队列 好了介绍完 RabbitMQ 的死信队列以及 TTL 这两种特性之后我们离实现延迟队列就只差一步之遥了。 聪明的读者可能已经发现了TTL 不就是延迟队列中消息要延迟的时间么如果我们把需要延迟的消息将 TTL 设置为其延迟时间投递到 RabbitMQ 的普通队列中一直不去消费它那么经过 TTL 的时间后消息就会自动被投递到死信队列这时候我们使用消费者进程实时地去消费死信队列中的消息不就实现了延迟队列的效果。 从下图可以直观的看出使用 RabbitMQ 实现延迟队列的整体流程 使用 RabbitMQ 来实现延迟队列我们可以很好的利用一些 RabbitMQ 的特性比如消息可靠发送、消息可靠投递、死信队列来保障消息至少被消费一次以及未被正确处理的消息不会被丢弃。另外通过 RabbitMQ 集群的特性可以很好的解决单点故障问题不会因为单个节点挂掉导致延迟队列不可用或者消息丢失。 6. TimeWheel TimeWheel 时间轮算法是一种实现延迟队列的巧妙且高效的算法被应用在 NettyZookeeperKafka 等各种框架中。 6.1 时间轮 如上图所示时间轮是一个存储延迟消息的环形队列其底层采用数组实现可以高效循环遍历。这个环形队列中的每个元素对应一个延迟任务列表这个列表是一个双向环形链表链表中每一项都代表一个需要执行的延迟任务。 时间轮会有表盘指针表示时间轮当前所指时间随着时间推移该指针会不断前进并处理对应位置上的延迟任务列表。 6.2 添加延迟任务 由于时间轮的大小固定并且时间轮中每个元素都是一个双向环形链表我们可以在 O(1) 的时间复杂度下向时间轮中添加延迟任务。 如下图例如我们有一个这样的时间轮在表盘指针指向当前时间为 2 时我们需要新添加一个延迟 3 秒的任务我们可以快速计算出延迟任务在时间轮中所对应的位置为 5并添加到位置 5 上任务列表尾部。 6.3 多层时间轮 到现在为止一切都非常棒但是细心的同学可能发现了上面的时间轮的大小是固定的只有 12 秒。如果此时我们有一个需要延迟 200 秒的任务我们应该怎么处理呢直接扩充整个时间轮的大小吗这显然不可取因为这样做的话我们就需要维护一个非常非常大的时间轮内存是不可接受的而且底层数组大了之后寻址效率也会降低影响性能。 为此Kafka 引入了多层时间轮的概念。其实多层时间轮的概念和我们的机械表上时针、分针、秒针的概念非常类似当仅使用秒针无法表示当前时间时就使用分针结合秒针一起表示。同样的当任务的到期时间超过了当前时间轮所表示的时间范围时就会尝试添加到上层时间轮中如下图所示 第一层时间轮整个时间轮所表示时间范围是 0-12 秒第二层时间轮每格能表示的时间范围是整个第一层时间轮所表示的范围也就是 12 秒所以整个第二层时间轮能表示的时间范围即 12*12144 秒依次类推第三层时间轮能表示的范围是 1728 秒第四层为 20736 秒等等。 比如现在我们需要添加一个延时为 200 秒的延迟消息我们发现其已经超过了第一层时间轮能表示的时间范围我们就需要继续往上层时间轮看将其添加在第二层时间轮 200/12 17 的位置然后我们发现 17 也超过了第二次时间轮的表示范围那么我们就需要继续往上层看将其添加在第三层时间轮的 17/12 2 的位置。 Kafka 中时间轮算法添加延迟任务以及推动时间轮滚动的核心流程如下其中 Bucket 即时间轮中的延迟任务队列并且 Kafka 引入的 DelayQueue 解决了多数 Bucket 为空导致的时间轮滚动效率低下的问题 使用时间轮实现的延迟队列能够支持大量任务的高效触发。并且在 Kafka 的时间轮算法的实现方案中还引入了 DelayQueue使用 DelayQueue 来推送时间轮滚动而延迟任务的添加与删除操作都放在时间轮中这样的设计大幅提升了整个延迟队列的执行效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/86399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

项目管理软件开发案例如何优化搜索引擎的搜索功能

学习笔记-SQL语法系统性学习,关卡式进阶 笔记参考:作者鱼皮 关卡式Sql语句学习体验网站 ,网站开源代码 如果想本地体验语法:1.下载大佬开源代码,运行前端项目(推荐); 2.或是自己使…

城乡建设门户网站重庆建站模板代理

一、说明 计量经济学是使用统计方法来发展理论或测试经济学或金融学中的现有假设。计量经济学依赖于回归模型和零假设检验等技术。计量经济学也可以用来预测未来的经济或金融趋势。 图片来源:https://marketbusinessnews.com 二、 计量经济之简介 计量经济学是对经济…

海外网站怎么浏览做网站个体户执照

原文:Build a search engine, not a vector DB 作者: Panda Smith 在过去 12 个月中,我们见证了向量数据库(Vector DB)创业公司的迅猛增长。我此刻并不打算深入探讨它们各自的设计取舍。相反,我更想探讨和…

建设银行考试报名网站wordpress 渐变主题

一、初识python (一).Python起源 Python创始人为吉多范罗苏姆(荷兰),Python崇尚优美、清晰、简明的编辑风格。Python语言结构清晰简单、数据库丰富、运行成熟稳定,科学计算统计分析领先。目前广泛应用于云计算、Web开发、科学运算…

html5 网站开发定制手机制作app的软件免费

1、函数内部使用全局变量时,需要申明global 1 name 小明 # 定义一个全局变量name,并给它赋值小明2 stus [] # 定义一个空list3 # list、字典、集合4 5 def a():6 # 字符串、int、float、元组 需要声明global7 global name # 函数内部使用局部变量时&a…

扁平式网站模板郑州专业制作网站费用

LeetCode 39.组合总和 题目链接&#xff1a; LeetCode 39.组合总和 解题思路&#xff1a; 用回溯的方法&#xff0c;&#xff0c;注意这次回溯不是i1&#xff0c;而是i&#xff0c;是因为可用重复选取。 代码&#xff1a; class Solution { public:vector<vector<i…

开发门户网站前程无忧网广州网站建设类岗位

在Rust中&#xff0c;如果你想要对HashMap中特定键对应的值进行累加操作&#xff0c;你需要首先检查该键是否已存在。如果存在&#xff0c;则取出其值&#xff0c;进行累加&#xff0c;然后将结果存回HashMap。如果不存在&#xff0c;则可能需要插入一个新的键值对&#xff0c;…

做网站标配wordpress知更鸟破解

1&#xff0c;例行性工作 例行性工作 —— 在某一时刻&#xff0c;必须要做的事情 —— 定时任务 &#xff08;比如&#xff1a;闹钟&#xff09; 例行性工作分为两种&#xff1a;“单一的例行性工作 at”和“循环的例行性工作 crontab” 2&#xff0c;单一执行的例行性工作 …

企业网站搭建 网络活动策划做网站工作室名字

知识点 1、权限提升转移-分类&高低&场景 2、Web权限提升及转移-后台&数据库 3、后台权限及转移-转移对象&后台分类 章节点&#xff1a; 1、Web权限提升及转移 2、系统权限提升及转移 3、宿主权限提升及转移 4、域控权限提升及转移 基础点 0、为什么我们要学…

遂平网站建设网站服务器怎么查询

1、主机字节序介绍 不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机字节序,存储方式有2种 1)、大端模式 大端模式(Big-Endian)就是高位字节排放在内存的低地址端(即该值的起始地址),低位字节排放在内存的高地址端 2 ) 、小端模式 小端存储在…

网站开发工程师证书最大的网站开发公司

来源&#xff1a;http://home.eeworld.com.cn/my/space-uid-639749-blogid-267593.html 一般的&#xff0c;在Verilog中最常用的编码方式有二进制编码(Binary)、格雷码(Gray-code)编码、独热码(One-hot)编码。二进制码和格雷码是压缩状态编码。 若使用格雷编码&#xff0c;则相…

做cpa建什么网站好申请了域名怎么做网站

目录 1 核心概念 2 安装依赖库 3 实践 语音信号处理&#xff08;Speech Signal Processing&#xff09;简称语音处理。 语音识别&#xff08;ASR&#xff09;和自然语言处理&#xff08;NLP&#xff09;&#xff1a;语音识别就是将语音信号转化成文字文本&#xff0c;简单实…

太原网站建设推广服务如何做企业网站

cp [OPTION]... SOURCE... DEST参数解释如下&#xff1a; [OPTION]&#xff1a;可选参数&#xff0c;用于指定 cp 命令的不同选项。SOURCE&#xff1a;源文件或目录的路径。可以指定一个或多个文件或目录。DEST&#xff1a;目标文件或目录的路径。 选项参数包括&#xff1a; …

专业的会议网站建设西安二手房出售信息

本章会介绍的知识点如下图&#xff1a; 1&#xff1a; 顺序表的概念&#xff1a;顺序表是用一段物理地址连续的存储单元依次存储数据的线性结构&#xff0c;通常我们使用数组来表示&#xff0c;对数组进行增删查改。 顺序表的结构&#xff1a;逻辑结构与物理结构都是内存中一块…

微网站与微信的关系用vs做购物网站

resizeObserver.ts //对于对象的引用是弱引用&#xff0c;这意味着在没有其他引用存在时垃圾回收能正确进行。在取消引用时&#xff0c;不需要手动删除元素&#xff0c;因为它们会自动被垃圾回收。 const map new WeakMap();// ResizeObserver是一个构造函数&#xff0c;用于…

网站开发基于什么平台安徽省城乡建设网站

让我猜一下 – 你没有显示使用上面尝试获取lastName的扫描器的代码.在那次尝试中,你没有处理行尾令牌,所以它是悬空的,只是被你试图获取lastName的nextLine()调用吞噬.例如,如果你有这个&#xff1a;Scanner keyboard new Scanner(System.in);System.out.print("Enter a …

贵阳网站建设管理网站访问跳出率

1 param介绍 类似C编程中的全局变量&#xff0c;可以便于在多个程序中共享某些数据&#xff0c;参数是ROS机器人系统中的全局字典&#xff0c;可以运行多个节点中共享数据。 全局字典 在ROS系统中&#xff0c;参数是以全局字典的形态存在的&#xff0c;什么叫字典&#xff1f;…

青岛住房和城乡建设厅网站深圳精准网络营销推广

查看全局和本地 Git 配置 打开命令行终端&#xff08;如 Git Bash&#xff09;&#xff0c;分别执行以下命令查看全局和本地的 Git 配置信息&#xff1a; git config --global -l git config --local -l确保配置中没有任何与 SSH 相关的设置 移除全局和本地 SSH 相关配置&…

学校做网站方案wordpress仿站视频教程

一、NIO三大组件 NIO的三大组件分别是Channel&#xff0c;Buffer与Selector Java NIO系统的核心在于&#xff1a;通道(Channel)和缓冲区(Buffer)。通道表示打开到 IO 设备(例如&#xff1a;文件、套接字)的连接。若需要使用 NIO 系统&#xff0c;需要获取用于连接 IO 设备的通…

河南网站建设37518外贸局合并到哪个局

一、源码特点 JSP康养小镇管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&a…