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

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

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

相关文章

C++之std::pair<uint64_t, size_t>应用实例(一百七十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

PHP之Base64+php://filter绕过、disabled_function绕过

目录 一、Base64php://filter绕过 1.思路分析 2.实践验证 二、disabled_function绕过 一、Base64php://filter绕过 上课讲了这样一道题&#xff0c;一起来看下(以下代码适用于PHP7.x及以上&#xff0c;5的版本会报错) <?php function fun($var): bool{$blacklist …

野火i.mx 6ull上手

目录 屏幕驱动打印信息 实现触摸屏校验 开发板连接WIFI 连接操作 申请路由器动态IP和ping网络通断 WiFi信息保存位置 常用wifi操作&#xff08;wpa_cli工具&#xff09; NFS网络文件系统共享 虚拟机安装NFS服务器 开发板安装NFS客户端 控制开发板 找出硬件设备所对…

C语言实现贷款计算器

等额本金&#xff0c;等额本息数学推导:贷款 买房&#xff0c;利息怎么算&#xff1f;不要被忽悠了&#xff01;李永乐老师讲等额本金和等额本息 一个心血来潮的研究&#xff0c;避免以后买房被坑。 捣鼓了半天才发现原来支付宝的那个利率是年利率不是月利率&#xff0c;坑了…

驱动开发——字符设备

字符设备 Linux 将系统设备分为&#xff1a;字符设备、块设备、网络设备。工作原理 字符设备是 Linux 驱动中最基本的一类设备驱动&#xff0c;字符设备就是一个一个字节&#xff0c; 按照字节流进行读写操作的设备&#xff0c;读写数据是分先后顺序的。在Linux的世界里面一切…

如何修复损坏的DOC和DOCX格式Word文件?

我们日常办公中&#xff0c;经常用到Word文档。但是有时会遇到word文件损坏、无法打开的情况。这时该怎么办&#xff1f;接着往下看&#xff0c;小编在这里就给大家带来最简单的Word文件修复方法&#xff01; 很多时候DOC和DOCX Word文件会无缘无故的损坏无法打开&#xff0c;一…

AI 实力:利用 Docker 简化机器学习应用程序的部署和可扩展性

利用 Docker 的强大功能&#xff1a;简化部署解决方案、确保可扩展性并简化机器学习模型的 CI/CD 流程。 近年来&#xff0c;机器学习 (ML) 出现了爆炸性增长&#xff0c;导致对健壮、可扩展且高效的部署方法的需求不断增加。由于训练和服务环境之间的差异或扩展的困难等因素&a…

【福建事业单位-综合基础知识】03行政法

【福建事业单位-综合基础知识】03行政法 1.行政法概述&#xff08;原则重点&#xff09;行政主体范围 行政行为总结 二.行政处罚2.1行政处罚的种类总结 行政法框架 1.行政法概述&#xff08;原则重点&#xff09; 行政法的首要原则是合法&#xff1b;自由裁量——合理行政&…

SSM——用户、角色、权限操作

1. 数据库与表结构 1.1 用户表 1.1.1 用户表信息描述 users 1.1.2 sql语句 CREATE TABLE users( id varchar2(32) default SYS_GUID() PRIMARY KEY, email VARCHAR2(50) UNIQUE NOT NULL, username VARCHAR2(50), PASSWORD VARCHAR2(50), phoneNum VARCHAR2(20), STATUS INT…

i18n 配置vue项目中英文语言包(中英文转化)

一、实现效果 二、下载插件创建文件夹 2.1 下载cookie来存储 npm install --save js-cookienpm i vue-i18n -S 2.2 封装组件多页面应用 2.3 创建配置语言包字段 三、示例代码 3.1 main.js 引用 i18n.js import i18n from ./lang// 实现语言切换:i18n处理element&#xff0c…

Unity ARFoundation 配置工程 (Android)

注意&#xff1a; 1、AR Core是Google的产品&#xff0c;因为谷歌制裁华为&#xff0c;所以 有些 华为机可能不支持AR Core的软件&#xff1b; 2、手机在设置里搜索Google Play&#xff0c;看看是否已经安装上了&#xff0c;如果没有装此服务&#xff0c;去商城里搜索Google Pl…

互联网发展历程:跨越远方,路由器的启示

互联网的蓬勃发展&#xff0c;一直在追求更广阔的连接&#xff0c;更遥远的距离。然而&#xff0c;在早期的网络中&#xff0c;人们面临着连接距离有限的问题。一项重要的技术应运而生&#xff0c;那就是“路由器”。 连接受限的问题&#xff1a;距离有限 早期的网络受限于直接…

【Pandas】pd.concat和pd.merge的区别

前言 最近做了一个数据挖掘的项目&#xff0c;里面涉及到大量dataframe拼接的操作。在这个过程中&#xff0c;我主要使用过两种拼接方法&#xff1a;pd.merge和pd.concat。其中遇到过一些坑&#xff0c;在这里记录一下。 简介 首先给出pandas官方文档对于这两种方法的介绍&a…

Mysql基础2-多表查询和视图

约束 完整性约束 为防止不规范数据进入数据库中&#xff0c;在用户对数据进行插入&#xff0c;修改&#xff0c;删除操作时&#xff0c;MySQL提供了一种机制来检查数据库中的数据是否满足规定的条件 约束条件约束描述PRIMARY KEY主键约束NOT NULL非空约束&#xff0c;字段不…

解决oracle的em访问提示“使用不受支持的协议。”的bug

1. 设置oracle唯一名称 执行emctl时需要设置一个唯一的名称 否则提示 “Environment variable ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to database unique name. ”中文意思为“未定义环境变量ORACLE_UNQNAME。 请将ORACLE_UNQNAME设置为数据库唯一名称/服务…

微服务-Nacos(注册中心)

Nacos是SpringCloud的一个功能非常强大的组件&#xff0c;想比eureka的功能更加丰富 官方的nacos简介 Nacos&#xff08;全称&#xff1a;Naming and Configuration Service&#xff09;是一个开源的动态服务发现、配置管理和服务管理平台。它由阿里巴巴集团开发并贡献给开源…

tensorflow 模型计算中,预测错误;权重参数加载

tensorflow 模型计算中&#xff0c;预测错误&#xff1b;权重参数加载 tensorflow 模型计算主要代码&#xff08;正确代码&#xff09; linear1_kernel_initializer tf.constant_initializer(numpy.transpose(data["linear1.weight"])) linear1_bias_initializer …

【设计模式——学习笔记】23种设计模式——策略模式Strategy(原理讲解+应用场景介绍+案例介绍+Java代码实现)

文章目录 案例引入传统方案实现实现分析 介绍基本介绍登场角色 案例实现案例一类图实现 案例二类图实现问答 策略模式在JDK源码中的使用总结文章说明 案例引入 有各种鸭子&#xff0c;比如野鸭、北京鸭、水鸭等。 鸭子有各种行为&#xff0c;比如走路、叫、飞行等。不同鸭子的…

设置Linux 静态IP

LInux虚拟机默认的IP地址是动态获取的 作为服务器&#xff0c;我们一般还需要把IP地址设置为静态的 设置静态IP vim /etc/sysconfig/network-scripts/ifcfg-ens33 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno # BOOTPROTOdhcp 动态获取 BOOTPROTOstatic IPADDR"192.16…

vue 重写数组的七个方法

一、为什么要重写数组方法&#xff1f; Vue 为了实现响应式数据绑定&#xff0c;需要能够捕获到数据的变化&#xff0c;以便在数据发生改变时自动更新视图。JavaScript 中的数组是引用类型&#xff0c;所以常规的引用跟踪机制不能捕获数组内部的变化。因为Vue的响应式是通过 O…