3 redis实现一个消息中间件

使用list实现一个队列,可以从左侧入队,也可以从右侧入对
即可以从左侧读取,也可以从右侧读取

1、Lindex

Lindex 命令用于通过索引获取列表中的元素
也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二。

redis 127.0.0.1:6379> LINDEX KEY_NAME INDEX_POSITION 

列表中下标为指定索引值的元素。 如果指定索引值不在列表的区间范围内,返回 nil。
例如:

redis 127.0.0.1:6379> LPUSH mylist "World"
(integer) 1redis 127.0.0.1:6379> LPUSH mylist "Hello"
(integer) 2redis 127.0.0.1:6379> LINDEX mylist 0
"Hello"redis 127.0.0.1:6379> LINDEX mylist -1
"World"redis 127.0.0.1:6379> LINDEX mylist 3        # index不在 mylist 的区间范围内
(nil)
2、Rpush

Rpush 命令用于将一个或多个值插入到列表的尾部(最右边)
如果列表不存在,一个空列表会被创建并执行 RPUSH 操作。 当列表存在但不是列表类型时,返回一个错误。

redis 127.0.0.1:6379> RPUSH KEY_NAME VALUE1..VALUEN

返回值:是执行 RPUSH 操作后,列表的长度。
例如:

redis 127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
redis 127.0.0.1:6379> RPUSH mylist "foo"
(integer) 2
redis 127.0.0.1:6379> RPUSH mylist "bar"
(integer) 3
redis 127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "foo"
3) "bar"

set是做不了的,set没有顺序,无法满足FIFO

3、代码实现
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;import java.util.List;@Component
public class ListVer{public final static String RS_LIST_MQ_NS = "rlm:";@Autowiredprivate JedisPool jedisPool;/*消费者接受消息*/public List<String> get(String key) {Jedis jedis = null;try {jedis = jedisPool.getResource();//阻塞式的等待消息,如果队列中没有数据的话,就一直等//0:表示等待0s,没有数据就不等待了return jedis.brpop(0,RS_LIST_MQ_NS + key);} catch (Exception e) {throw new RuntimeException("接受消息失败!");} finally {jedis.close();}}/*生产者发送消息*/public void put(String key, String message) {Jedis jedis = null;try {jedis = jedisPool.getResource();jedis.lpush(RS_LIST_MQ_NS+key,message);} catch (Exception e) {throw new RuntimeException("发送消息失败!");} finally {jedis.close();}}
}

注意:保持key的一致性

延迟消息的场景:
比如已经加入购物车中,购买的电影票,还没有付款的时候锁定座位,进行延迟消息投递。
之后再启动另一个消费端去监控这个延迟消息,到了时间后还没有支付的话,则进行取消操作.

可以使用sorted set(有序集合)来实现延迟消息,实际生产中不建议使用,还是使用正经的MQ。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;@Component
public class ZSetVer {//标记是延迟消息的keypublic final static String RS_ZS_MQ_NS = "rzsm:";@Autowiredprivate JedisPool jedisPool;/*生产者,消息的发送,实际生产中,相关参数,比如订单信息,过期时间等应该传入,可以考虑将订单信息json化存入redis*/public void producer() {Jedis jedis = null;try {jedis = jedisPool.getResource();for (int i = 0; i < 5; i++) {//订单idString order_id = "000000000"+i;double score = System.currentTimeMillis()+(i*1000);jedis.zadd(RS_ZS_MQ_NS+"orderId",score, order_id);System.out.println("生产订单: " + order_id + " 当前时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));System.out.println((3 + i) + "秒后执行");}} catch (Exception e) {throw new RuntimeException("生产消息失败!");} finally {jedis.close();}}//消费者,取订单public void consumerDelayMessage() {Jedis jedis = null;try {jedis = jedisPool.getResource();while (true) {Set<String> order = jedis.zrangeByScore(RS_ZS_MQ_NS+"orderId", 0,System.currentTimeMillis(), 0,1);if (order == null || order.isEmpty()) {System.out.println("当前没有等待的任务");try {TimeUnit.MILLISECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}continue;}String s = order.iterator().next();if (jedis.zrem(RS_ZS_MQ_NS+"orderId", s)>0) {/*业务处理*/System.out.println(s);}}} catch (Exception e) {throw new RuntimeException("消费消息失败!");} finally {jedis.close();}}
}

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

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

相关文章

2023前端大厂高频面试题之CSS篇(2)

系列文章: 2023前端大厂高频面试题之JavaScript篇(1) 2023前端大厂高频面试题之JavaScript篇(2) 2023前端大厂高频面试题之JavaScript篇(3) 2023前端大厂高频面试题之JavaScript篇(4) 2023前端大厂高频面试题之HTML篇 2023前端大厂高频面试题之CSS篇(1) 2023前端大厂高频面试题…

new/delete 和malloc/free的区别

C中&#xff1a; 创建单个数据空间&#xff1a; char *ch new char; delete ch; ch NULL; 创建多个数据空间&#xff1a; char *ch new char[4]; delete [] ch; ch NULL; C语言中&#xff1a; 创建单个数据空间&#xff1a; char *ch malloc(sizeof(char)); fre…

BP神经网络原理与如何实现BP神经网络

本文部分图文来自《老饼讲解-BP神经网络》bp.bbbdata.com 目录 一、BP神经网络的背景生物学原理 二、BP神经网络模型 2.1 BP神经网络的结构 2.2 BP神经网络的激活函数 三、BP神经网络的误差函数 四、BP神经网络的训练 4.1 BP神经网络的训练流程 4.2 BP神经网络的训练流…

springboot(ssm大学生成绩管理系统 成绩管理平台Java(codeLW)

springboot(ssm大学生成绩管理系统 成绩管理平台Java(code&LW) 开发语言&#xff1a;Java 框架&#xff1a;ssm/springboot vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5.7&#xff08;或8.0&…

【运维篇】5.6 Redis server 主从复制配置

文章目录 0. 前言1. 配置方式步骤1: 准备硬件和网络步骤2: 安装Redis步骤3: 配置主服务器的Redis步骤4: 配置从服务器的Redis步骤5: 测试复制功能步骤6: 监控复制状态 2. 参考文档 0. 前言 在Redis运维篇的第5.6章节中&#xff0c;将讨论Redis服务器的主从复制配置。在开始之前…

如何实现MATLAB与Simulink的数据交互

参考链接&#xff1a;如何实现MATLAB与Simulink的数据交互 MATLAB是一款强大的数学计算软件&#xff0c;Simulink则是一种基于模型的多域仿真平台&#xff0c;常用于工程和科学领域中的系统设计、控制设计和信号处理等方面。MATLAB和Simulink都是MathWorks公司的产品&#xff0…

数据结构【DS】图的应用

图的连通性问题 最少边数 最多边数 无向图非连通 &#x1d48e;&#x1d7ce; &#x1d48e;&#x1d48f;−&#x1d7d0;∗(&#x1d48f;−&#x1d7cf;)/&#x1d7d0; 无向图连通 &#x1d48e;&#x1d48f;−&#x1d7cf; &#x1d48e;&#x1d48f;∗(&#…

在Sprinng Boot中使用Redis充当缓存

关于我们使用EhCache可以适应很多的应用场景了&#xff0c;但是因为EhCache是进程内的缓存框架&#xff0c;在集群模式下&#xff0c;我们在我们的应用服务器或者云服务器之间的缓存都是独立的。故而在不同的服务器之间的进程会存在缓存不一致的情况&#xff0c;就算我们的EhCa…

word批量图片导出wps office word 图片批量导出

word批量导出图片教程 背景 今天遇到了一个场景&#xff0c;因为word里的图片打开看太模糊了&#xff0c;如果一个一个导出来太麻烦。想批量将word中的图片全部导出 但是&#xff0c;wps导出的时候需要会员 教程开始&#xff1a; 将word保存为 .docx 格式&#xff0c;可以按F1…

Golang 协程、主线程

Go协程、Go主线程 原先的程序没有并发和并行的概念&#xff0c;没有多核的概念&#xff0c;就是一个进程打天下。后面发现这个效率太低了&#xff0c;就搞出了线程&#xff0c;这样极大的发挥CPU的效率&#xff0c;因为硬件总是比软件发展的快。 现在go考虑的是能不能让多核cp…

【数据结构】C语言实现队列

目录 前言 1. 队列 1.1 队列的概念 1.2 队列的结构 2. 队列的实现 2.1 队列的定义 2.2 队列的初始化 2.3 入队 2.4 出队 2.5 获取队头元素 2.6 获取队尾元素 2.7 判断空队列 2.8 队列的销毁 3. 队列完整源码 Queue.h Queue.c &#x1f388;个人主页&#xff1a…

Vue3新增加的css语法糖

一、deep <template><div class""><el-input /> </div> </template> <style scoped> /* 样式穿透 */ :deep input {background: red; } </style> 二、slotted 子组件修改插槽里面的样式 <template><div clas…

AI变现之Gpts搞流量+赚钱

文章目录 Gpts | 搞流量 + 赚钱1.项目介绍2.项目分析3.项目实操4.变现路径Gpts | 搞流量 + 赚钱 1.项目介绍 这两天 AI 圈最火的莫过于 OpenAI 开发者大会公布的一个爆炸产品 Gpts 了,大家都知道这个肯定是一个划时代的产品,也绝对是一个风口,虽然官方还没有公布到底怎么通…

【数据结构】树与二叉树(廿一):树和森林的遍历——先根遍历(递归算法PreOrder、非递归算法NPO)

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语 5.2 二叉树5.3 树5.3.1 树的存储结构1. 理论基础2. 典型实例3. Father链接结构4. 儿子链表链接结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法5.3.3 树和森林的遍历1. 先根遍历&#xff08;递归&am…

记一次通过REC获取服务器权限以及同服务器的网站权限

文章目录 一、漏洞原因二、漏洞利用三、漏洞进一步利用1、利用REC,获取服务器权限2、通过下载jar包进行代码审计3、获取数据库配置信息4、进行连接数据库5、访问后台网站6、成功登陆后台四、总结五、免责声明一、漏洞原因 XXL-JOB 默认 accessToken 身份绕过导致 RCE通过配置文…

<b><strong>,<i><em>标签的区别

1. b标签和strong标签 b标签&#xff1a;仅仅是UI层面的加粗样式&#xff0c;并不具备HTML语义 strong标签&#xff1a;不仅是在UI层面的加粗样式&#xff0c;具备HTML语义&#xff0c;表示强调 2. i标签和em标签 i 标签&#xff1a;仅仅是UI层面的斜体样式&#xff0c;并不…

HTML5学习系列之实用性标记

HTML5学习系列之实用性标记 前言实用性标记高亮显示进度刻度时间联系信息显示方向换行断点标注 总结 前言 学习记录 实用性标记 高亮显示 mark元素可以进行高亮显示。 <p><mark>我感冒了</mark></p>进度 progress指示某项任务的完成进度。 <p…

(c语言进阶)内存函数

一.memcpy(void* dest,void* src,int num) &#xff0c;操作单位为字节&#xff0c;完成复制且粘贴字符串 1.应用 #include <stdio.h> #include<string.h> int main() {int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] { 0 };memcpy(arr2, arr1, 20);//从…

Linux - 用户级缓冲区和系统缓冲区 - 初步理解Linux当中文件系统

前言 文件系统 我们先来看两个例子&#xff1a; 这个程序输出&#xff1a; 此时的输出也满足的我们预期。 我们也可以把 程序执行结果&#xff0c;输出重定向到 一个文件当中: 当我们在代码的结尾处&#xff0c;创建了子进程&#xff0c;那么输出应该还是和上述是一样的&…

Day35力扣打卡

打卡记录 相邻字符不同的最长路径&#xff08;树状DP&#xff09; 链接 若节点也存在父节点的情况下&#xff0c;传入父节点参数&#xff0c;若是遍历到父节点&#xff0c;直接循环里 continue。 class Solution:def longestPath(self, parent: List[int], s: str) -> in…