当前位置: 首页 > news >正文

使用 Redis 实现异步队列

使用 Redis 实现异步队列

  • 一、简介
    • 1 异步队列
    • 2 异步队列与同步队列
  • 二、Redis 实现异步队列
    • 1 利用 Redis 的 List 数据类型实现异步队列
    • 2 利用 Redis 的 Pub/Sub 功能实现异步队列
    • 3 利用 Redis 的 Sorted Set 数据类型实现延迟队列
  • 三、Redis 异步队列的实际应用场景
    • 4.1 异步任务处理
      • 4.2 订单队列处理
      • 4.3 推送消息队列实现
  • 四、Redis 异步队列的优化及注意事项
      • 5.1 队列长度的控制
      • 5.2 将多个操作合并成一个事务
      • 5.3 内存优化及持久化配置
  • 五、小结回顾

一、简介

1 异步队列

异步队列是一种底层基于异步 I/O 模型的消息队列,用于在分布式系统中进行同步和异步的通讯和协作。通过异步队列,消费者可以随时请求生产者生产并发送消息,无需等待回应即可执行其他操作。异步队列在提高系统性能和吞吐量方面有很大的优势。

2 异步队列与同步队列

同步队列和异步队列是两种不同的消息队列模型。同步队列中,生产者在发送消息后需要等待消费者的回应,这会导致生产者发生阻塞,直到消费者接收并处理完消息。相反,异步队列中,生产者不需要等待直接发送消息,并不关心消费者是否接收到这些消息,因此生产者可以立即继续执行其他操作,从而提高了吞吐量。

二、Redis 实现异步队列

1 利用 Redis 的 List 数据类型实现异步队列

Redis 的 List 数据类型非常适合用于实现异步队列。生产者可以使用 LPUSH 命令将消息插入队列的头部。而消费者则可利用 BRPOP 命令从队列尾部“弹出”消息并进行处理。该命令会阻塞进程,直到 Redis 返回了一个 key 所对应的值。

以下是使用 List 实现异步队列示例

    public void pushMessageToRedis(String message) {try (Jedis jedis = jedisPool.getResource()) {jedis.lpush(redisListKey, message);}}public String popMessageFromRedis() {try (Jedis jedis = jedisPool.getResource()) {List<String> messages = jedis.brpop(0, redisListKey);if (messages != null && !messages.isEmpty()) {return messages.get(1);}return null;}}

2 利用 Redis 的 Pub/Sub 功能实现异步队列

Redis 的 Pub/Sub 功能也非常适合用于实现异步队列。生产者可以使用 PUBLISH 命令将消息发布到某个频道中。而消费者则可利用 SUBSCRIBE 命令订阅这些频道,并通过在回调函数中处理获取的消息。

以下是一个使用 Pub/Sub 实现异步队列:

    public void publishMessageToRedisChannel(String channel, String message) {try (Jedis jedis = jedisPool.getResource()) {jedis.publish(channel, message);}}public void subscribeAndHandleMessageFromRedisChannel(String channel, JedisPubSub jedisPubSub) {try (Jedis jedis = jedisPool.getResource()) {jedis.subscribe(jedisPubSub, channel);}}

3 利用 Redis 的 Sorted Set 数据类型实现延迟队列

Redis 的 Sorted Set 数据类型也非常适合用于实现延迟队列。生产者可以使用 ZADD 命令将消息加入有序集合中,同时设置该消息的过期时间。消费者则可利用 ZRANGEBYSCORE 命令查询有序集合中所有已经到期的消息并进行处理。

以下是一个使用 Sorted Set 实现延迟队列示例:

    public void addMessageToRedisZset(String zSetKey, double score, String message) {try (Jedis jedis = jedisPool.getResource()) {jedis.zadd(zSetKey, score, message);}}public List<String> popMessagesFromRedisZset(String zSetKey, double minScore, double maxScore, int count) {try (Jedis jedis = jedisPool.getResource()) {Set<String> messages = jedis.zrangeByScore(zSetKey, minScore, maxScore, 0, count);if (messages != null && !messages.isEmpty()) {jedis.zrem(zSetKey, messages.toArray(new String[0]));return new ArrayList<>(messages);}return null;}}

三、Redis 异步队列的实际应用场景

4.1 异步任务处理

Redis 异步队列可以用来处理一些需要异步执行的任务,比如发送邮件、短信等。我们可以把任务放入队列中,在后台有专门的程序不断地从队列中取出任务执行。

    // 将任务添加到队列中jedis.lpush("task_queue", "task1", "task2", "task3");// 后台程序获取任务并执行while (true) {String task = jedis.brpop(0, "task_queue").get(1); // 从队列中取出任务,如果队列为空则一直阻塞handleTask(task); // 处理任务}

4.2 订单队列处理

在订单系统中,我们经常需要对订单进行处理和状态改变。为了保证订单处理的顺序和可靠性,我们可以将订单信息放入 Redis 队列中,后台程序从队列中取出订单并更新订单状态。

    // 将订单添加到队列中jedis.lpush("order_queue", orderJsonStr);// 后台程序获取订单并更新订单状态while (true) {String orderJsonStr = jedis.brpop(0, "order_queue").get(1); // 从队列中取出订单,如果队列为空则一直阻塞Order order = parseOrder(orderJsonStr);updateOrderStatus(order); // 更新订单状态}

4.3 推送消息队列实现

在一些 IM 聊天系统中,我们需要将消息实时地发送给用户。如果使用同步方式,会严重降低系统的性能和并发量。因此我们可以通过 Redis 异步队列解决这个问题。

    // 将消息添加到队列中jedis.lpush("message_queue_" + userId, messageJsonStr);// 后台程序获取消息并发送while (true) {String messageJsonStr = jedis.brpop(0, "message_queue_" + userId).get(1); // 从队列中取出消息,如果队列为空则一直阻塞sendMessageToUser(userId, messageJsonStr); // 发送消息给用户}

四、Redis 异步队列的优化及注意事项

5.1 队列长度的控制

为了避免队列过长导致消费者一次性处理大量数据,我们需要控制队列的长度。可以通过设置最大队列长度或定期清理队列的方式来避免队列过长。

    // 设置最大队列长度jedis.ltrim("task_queue", 0, maxSize-1); // 只保留队列前maxSize个元素// 定期清理队列if (System.currentTimeMillis() % cleanInterval == 0) {jedis.ltrim("task_queue", -maxSize, -1); // 只保留队列后maxSize个元素jedis.del("expired_task"); // 删除队列中过期的任务}

5.2 将多个操作合并成一个事务

为了提升 Redis 的性能,我们可以将多个操作合并成一个事务。这样可以减少 Redis 的通信次数和网络传输时间。

    Transaction transaction = jedis.multi();for (Task task : taskList) {transaction.lpush("task_queue", task.toString());}transaction.exec(); // 提交事务

5.3 内存优化及持久化配置

为了保证 Redis 的性能和稳定性,我们需要注意一些内存优化和持久化配置。比如可以使用 Redis 的压缩功能、增加 Redis 的内存硬限制、选择正确的数据结构等。

    // 启用 LRU 或 LFU 算法config set maxmemory-policy lru// 增加内存硬限制config set maxmemory hard 256mb// 选择正确的数据结构使用 hash 存储对象

五、小结回顾

Redis 异步队列是一种高性能且可靠的消息队列,可以广泛应用于各种业务场景。在使用过程中,我们需要注意队列长度的控制、将多个操作合并成一个事务、内存优化及持久化配置等方面,以达到更好的性能和稳定性。

相关文章:

使用 Redis 实现异步队列

使用 Redis 实现异步队列 一、简介1 异步队列2 异步队列与同步队列 二、Redis 实现异步队列1 利用 Redis 的 List 数据类型实现异步队列2 利用 Redis 的 Pub/Sub 功能实现异步队列3 利用 Redis 的 Sorted Set 数据类型实现延迟队列 三、Redis 异步队列的实际应用场景4.1 异步任…...

RocketMQ、Dashboard部署以及安全设置

RocketMQ、dashboard部署以及安全设置 一、启动RocketMQ1.1 下载RocketMQ1.2 修改配置文件1.2.1 修改nameServer Jvm内存配置1.2.2 修改broker参数 1.3 启动1.3.1 启动NameServer1.3.2 启动Broker1.3.3 测试是否启动成功1.3.3.1 测试消息发送1.3.3.2 测试消息接收1.3.3.3 Java程…...

Android AlarmManager设置闹钟

官网镇楼&#xff1a;设置重复闹铃时间 闹钟具有以下特征&#xff1a; 它们可让您按设定的时间和/或间隔触发 intent。您可以将它们与广播接收器结合使用&#xff0c;以启动服务以及执行其他操作。它们在应用外部运行&#xff0c;因此即使应用未运行&#xff0c;或设备本身处…...

【C# 基础精讲】LINQ to XML查询

LINQ to XML 是 C# 中用于查询和操作 XML 数据的强大工具。它允许您使用 LINQ 查询语法对 XML 文档进行查询、过滤、投影等操作&#xff0c;从而更加方便地处理 XML 数据。本文将详细介绍 LINQ to XML 的基本概念、常见操作以及示例&#xff0c;帮助您了解如何在 C# 中使用 LIN…...

Java学习笔记——(20)标识符命名规则和规范

什么叫标识符 Java 对各种变量、方法和类等命名时使用的字符序列成为标识符凡是自己可以起名字的地方都叫标识符 标识符的命名规则&#xff08;必须遵守&#xff09; 由26个英文字母大小写&#xff0c;0-9&#xff0c;_ 或 $ 组成数字不可以开头不可以使用关键字和保留字Jav…...

过滤字符,绕过

构造不包含字母和数字的webshell <?phpecho "A"^""; ?>运行结果为! 代码中对字符"A"和字符”"进行了异或操作。在PHP中&#xff0c;两个变量进行异或时&#xff0c;先会将字符串转换成ASCII值&#xff0c;再将ASCII值转换成二进制…...

Apache Doris 入门教程32:物化视图

物化视图 物化视图是将预先计算&#xff08;根据定义好的 SELECT 语句&#xff09;好的数据集&#xff0c;存储在 Doris 中的一个特殊的表。 物化视图的出现主要是为了满足用户&#xff0c;既能对原始明细数据的任意维度分析&#xff0c;也能快速的对固定维度进行分析查询。 …...

PHP substr()函数详解,PHP截取字符串。

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 substr 一、截取字符串二、截取中文字符串三、leng…...

关于flink-sql-connector-phoenix的重写逻辑

目录 重写意义 代码结构 调用链路 POM文件配置 代码解析 一、PhoenixJdbcDynamicTableFactory...

Django进阶:DRF(Django REST framework)

什么是DRF&#xff1f; DRF即Django REST framework的缩写&#xff0c;官网上说&#xff1a;Django REST framework是一个强大而灵活的工具包&#xff0c;用于构建Web API。 简单来说&#xff1a;通过DRF创建API后&#xff0c;就可以通过HTTP请求来获取、创建、更新或删除数据(…...

Flink CDC系列之:Oracle CDC 导入 Elasticsearch

Flink CDC系列之&#xff1a;Oracle CDC 导入 Elasticsearch 一、深入理解Flink Oracle CDC Connector二、创建docker-compose.yml文件三、启动容器四、下载Flink Oracle CDC的jar包五、启动 Flink 集群&#xff0c;再启动 SQL CLI六、检查 ElasticSearch 中的结果七、在 Oracl…...

Linux忘记root密码解决方法

当我们忘记root密码进不去服务器怎么办&#xff1f;不要担心&#xff0c;可以进入到linux的救援模式修改root密码。 下面直接上干货&#xff0c;流程如下&#xff1a; 1.重启电脑&#xff0c;按上下键滑动&#xff0c;保证不进入开机流程&#xff0c;然后按e键 2.出现此页面…...

AR/VR眼镜转接器方案,实现同时传输视频快充方案

简介 虚拟现实头戴显示器设备&#xff0c;简称VR头显VR眼镜&#xff0c;是利用仿真技术与计算机图形学人机接口技术多媒体技术传感技术网络技术等多种技术集合的产品&#xff0c;是借助计算机及最新传感器技术创造的一种崭新的人机交互手段。VR头显VR眼镜是一个跨时代的产品。不…...

ASP.NET Core中路由规则匹配

RESTful约束&#xff0c;如果在一个控制器里面有多个Get、Post...的操作 1、在一个控制器里面可以定义多个API方法 2、通过路由规则来区分 /// <summary> /// 获取用户信息 /// </summary> /// <param name"user"></param> /// <returns…...

IDEA:Error running,Command line is too long. 解决方法

报错如下&#xff1a; Error running SendSmsUtil. Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun.原因是启动命令过长。 解决方法&#xff1a; 1、打开Edit Configurations 2、点击Modify options设置&#x…...

什么是反射机制?为什么反射慢?

目录 面试回答 知识扩展 反射常见的使用方式 反射和 Class 的关系 面试回答 反射指的是程序在运行时能够获取自身的信息。在 java 中&#xff0c;只要给定类的名字&#xff0c;那么就可以通过反射机制来获得类的所有属性和方法。 Java 的反射可以&#xff1a; 在运行时判断…...

list元素

列表元素 列表元素分为有序列表和无序列表 有序列表 ol – order list – 有序列表 li – list item – 列表元素 <ol type"1"><li>有序列表1</li><li>有序列表2</li><li>有序列表3</li> </ol>属性 type type属…...

OkHttp 源码浅析一

演进之路:原生Android框架不好用 ---- HttpUrlConnect 和 Apache HTTPClient 第一版 底层使用HTTPURLConnect 第二版 Square构建 从Android4.4开始 基本使用: val okhttp OkHttpClient()val request Request.Builder().url("http://www.baidu.com").buil…...

【解决问题】远程仓库GitHub/GitLab添加了SSH Key之后依然无法clone的解决办法

GitHub/GitLab添加了SSH Key之后依然无法clone的解决办法 问题现象解决办法 问题现象 在Git远程仓库添加了自己的ssh key到账户下&#xff0c;git clone时&#xff0c;依然报错clone失败&#xff0c;请检查是否没有权限进行clone操作。 解决办法 在git的安装目录下&#xff…...

回归预测 | MATLAB实现SA-SVM模拟退火算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SA-SVM模拟退火算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SA-SVM模拟退火算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...