Spring-data-redis: 分布式队列

别再搞混了!Redis、Jedis、Lettuce、Spring Data Redis、Redisson、Spring Session Redis 一次讲透 平时做Java开发,只要引入Redis做缓存,pom.xml里总会看到一堆名字相似的东西:一会儿是jedis,一会儿是lettuce,还有Spring Data Redis、Redisson、Spring Session Redis……刚接触的时候真的头大,甚至会把Redis服务端和Java客户端混为一谈,踩了不少坑。今天就把这些东西理清楚,分清谁是底层、谁是封装、谁是专门解决某个场景的。 阅读详情

Redis中list数据结构,具有“双端队列”的特性,同时redis具有持久数据的能力,因此redis实现分布式队列是非常安全可靠的。它类似于JMS中的“Queue”,只不过功能和可靠性(事务性)并没有JMS严格。

Redis中的队列阻塞时,整个connection都无法继续进行其他操作,因此在基于连接池设计是需要注意。

我们通过spring-data-redis,来实现“同步队列”,设计风格类似与JMS。

一.配置文件:

  1. <beans xmlns="http://www.springframework.org/schema/beans"   
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">  
  4.     <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">  
  5.         <property name="maxActive" value="32"></property>  
  6.         <property name="maxIdle" value="6"></property>  
  7.         <property name="maxWait" value="15000"></property>  
  8.         <property name="minEvictableIdleTimeMillis" value="300000"></property>  
  9.         <property name="numTestsPerEvictionRun" value="3"></property>  
  10.         <property name="timeBetweenEvictionRunsMillis" value="60000"></property>  
  11.         <property name="whenExhaustedAction" value="1"></property>  
  12.     </bean>  
  13.     <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">  
  14.         <property name="poolConfig" ref="jedisPoolConfig"></property>  
  15.         <property name="hostName" value="127.0.0.1"></property>  
  16.         <property name="port" value="6379"></property>  
  17.         <property name="password" value="0123456"></property>  
  18.         <property name="timeout" value="15000"></property>  
  19.         <property name="usePool" value="true"></property>  
  20.     </bean>  
  21.     <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
  22.         <property name="connectionFactory" ref="jedisConnectionFactory"></property>  
  23.         <property name="defaultSerializer">  
  24.             <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>  
  25.         </property>  
  26.     </bean>  
  27.     <bean id="jedisQueueListener" class="com.sample.redis.sdr.QueueListener"/>  
  28.     <bean id="jedisQueue" class="com.sample.redis.sdr.RedisQueue" destroy-method="destroy">  
  29.         <property name="redisTemplate" ref="jedisTemplate"></property>  
  30.         <property name="key" value="user:queue"></property>  
  31.         <property name="listener" ref="jedisQueueListener"></property>  
  32.     </bean>  
  33. </beans>  

二.程序实例:

1) QueueListener:当队列中有数据时,可以执行类似于JMS的回调操作。

  1. public interface RedisQueueListener<T> {  
  2.   
  3.     public void onMessage(T value);  
  4. }  
  1. public class QueueListener<String> implements RedisQueueListener<String> {  
  2.   
  3.     @Override  
  4.     public void onMessage(String value) {  
  5.         System.out.println(value);  
  6.           
  7.     }  
  8.   
  9. }  

2) RedisQueue:队列操作,内部封装redisTemplate实例;如果配置了“listener”,那么queue将采用“消息回调”的方式执行,listenerThread是一个后台线程,用来自动处理“队列信息”。如果不配置“listener”,那么你可以将redisQueue注入到其他spring bean中,手动去“take”数据即可。

  1. public class RedisQueue<T> implements InitializingBean,DisposableBean{  
  2.     private RedisTemplate redisTemplate;  
  3.     private String key;  
  4.     private int cap = Short.MAX_VALUE;//最大阻塞的容量,超过容量将会导致清空旧数据  
  5.     private byte[] rawKey;  
  6.     private RedisConnectionFactory factory;  
  7.     private RedisConnection connection;//for blocking  
  8.     private BoundListOperations<String, T> listOperations;//noblocking  
  9.       
  10.     private Lock lock = new ReentrantLock();//基于底层IO阻塞考虑  
  11.       
  12.     private RedisQueueListener listener;//异步回调  
  13.     private Thread listenerThread;  
  14.       
  15.     private boolean isClosed;  
  16.       
  17.     public void setRedisTemplate(RedisTemplate redisTemplate) {  
  18.         this.redisTemplate = redisTemplate;  
  19.     }  
  20.   
  21.     public void setListener(RedisQueueListener listener) {  
  22.         this.listener = listener;  
  23.     }  
  24.   
  25.     public void setKey(String key) {  
  26.         this.key = key;  
  27.     }  
  28.       
  29.   
  30.     @Override  
  31.     public void afterPropertiesSet() throws Exception {  
  32.         factory = redisTemplate.getConnectionFactory();  
  33.         connection = RedisConnectionUtils.getConnection(factory);  
  34.         rawKey = redisTemplate.getKeySerializer().serialize(key);  
  35.         listOperations = redisTemplate.boundListOps(key);  
  36.         if(listener != null){  
  37.             listenerThread = new ListenerThread();  
  38.             listenerThread.setDaemon(true);  
  39.             listenerThread.start();  
  40.         }  
  41.     }  
  42.       
  43.       
  44.     /** 
  45.      * blocking 
  46.      * remove and get last item from queue:BRPOP 
  47.      * @return 
  48.      */  
  49.     public T takeFromTail(int timeout) throws InterruptedException{   
  50.         lock.lockInterruptibly();  
  51.         try{  
  52.             List<byte[]> results = connection.bRPop(timeout, rawKey);  
  53.             if(CollectionUtils.isEmpty(results)){  
  54.                 return null;  
  55.             }  
  56.             return (T)redisTemplate.getValueSerializer().deserialize(results.get(1));  
  57.         }finally{  
  58.             lock.unlock();  
  59.         }  
  60.     }  
  61.       
  62.     public T takeFromTail() throws InterruptedException{  
  63.         return takeFromHead(0);  
  64.     }  
  65.       
  66.     /** 
  67.      * 从队列的头,插入 
  68.      */  
  69.     public void pushFromHead(T value){  
  70.         listOperations.leftPush(value);  
  71.     }  
  72.       
  73.     public void pushFromTail(T value){  
  74.         listOperations.rightPush(value);  
  75.     }  
  76.       
  77.     /** 
  78.      * noblocking 
  79.      * @return null if no item in queue 
  80.      */  
  81.     public T removeFromHead(){  
  82.         return listOperations.leftPop();  
  83.     }  
  84.       
  85.     public T removeFromTail(){  
  86.         return listOperations.rightPop();  
  87.     }  
  88.       
  89.     /** 
  90.      * blocking 
  91.      * remove and get first item from queue:BLPOP 
  92.      * @return 
  93.      */  
  94.     public T takeFromHead(int timeout) throws InterruptedException{  
  95.         lock.lockInterruptibly();  
  96.         try{  
  97.             List<byte[]> results = connection.bLPop(timeout, rawKey);  
  98.             if(CollectionUtils.isEmpty(results)){  
  99.                 return null;  
  100.             }  
  101.             return (T)redisTemplate.getValueSerializer().deserialize(results.get(1));  
  102.         }finally{  
  103.             lock.unlock();  
  104.         }  
  105.     }  
  106.       
  107.     public T takeFromHead() throws InterruptedException{  
  108.         return takeFromHead(0);  
  109.     }  
  110.   
  111.     @Override  
  112.     public void destroy() throws Exception {  
  113.         if(isClosed){  
  114.             return;  
  115.         }  
  116.         shutdown();  
  117.         RedisConnectionUtils.releaseConnection(connection, factory);  
  118.     }  
  119.       
  120.     private void shutdown(){  
  121.         try{  
  122.             listenerThread.interrupt();  
  123.         }catch(Exception e){  
  124.             //  
  125.         }  
  126.     }  
  127.       
  128.     class ListenerThread extends Thread {  
  129.           
  130.         @Override  
  131.         public void run(){  
  132.             try{  
  133.                 while(true){  
  134.                     T value = takeFromHead();//cast exceptionyou should check.  
  135.                     //逐个执行  
  136.                     if(value != null){  
  137.                         try{  
  138.                             listener.onMessage(value);  
  139.                         }catch(Exception e){  
  140.                             //  
  141.                         }  
  142.                     }  
  143.                 }  
  144.             }catch(InterruptedException e){  
  145.                 //  
  146.             }  
  147.         }  
  148.     }  
  149.       
  150. }  

3) 使用与测试:

  1. public static void main(String[] args) throws Exception{  
  2.     ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-redis-beans.xml");  
  3.     RedisQueue<String> redisQueue = (RedisQueue)context.getBean("jedisQueue");  
  4.     redisQueue.pushFromHead("test:app");  
  5.     Thread.sleep(15000);  
  6.     redisQueue.pushFromHead("test:app");  
  7.     Thread.sleep(15000);  
  8.     redisQueue.destroy();  
  9. }  

在程序运行期间,你可以通过redis-cli(客户端窗口)执行“lpush”,你会发现程序的控制台仍然能够正常打印队列信息。

Spring Data R2DBC 与 Spring Data Redis 的缓存策略 在使用 Spring Data R2DBC 和 Spring Data Redis 时,面临的问题主要包括如何选择合适的缓存策略以平衡数据一致性和性能、如何在不同场景下优化缓存命中率、如何处理缓存与数据库之间的同步等。缓存策略选择不当可能导致数据过时、缓存穿透、缓存雪崩等问题,影响系统的稳定性和性能。 阅读详情

相关推荐

EBSD数据转ABAQUS的inp文件实操指南

晶体塑性有限元模拟中,如何将材料微观组织表征数据转化为可计算的有限元模型,是连接实验与仿真的关键环节。EBSD技术能够获取材料表面的晶体取向、晶粒形貌和晶界分布信息,但这类数据需要经过格式解析、欧拉角转换、网格生成等步骤,才能被ABAQUS等有限元软件读取。通过将扫描点坐标映射为节点、按像素邻域生成单元,并将Bunge约定欧拉角变换为局部坐标系方向余弦,用户可以准确构建包含真实微观结构的inp文件模型。这一流程广泛应用于金属材料形变、织构演化及应力集中分析等研究场景,有效提升仿真结果与实验的一致性。围绕数据

weixin_42509513的博客 313

了解 Redis 并在 Spring Boot 项目中使用 Redis 缓存击穿、缓存穿透

在实际的开发过程中,多多少少都会涉及到缓存,而 Redis 通常来说是我们分布式缓存的最佳选择。Redis 也是我们熟知的 NoSQL(非关系性数据库)之一,虽然其不能完全的替代关系性数据库,但它可作为其良好的补充。本文就和大家一起了解一下 Redis,并实战在 Spring Boot 项目使用它。 Redis 简介 Redis 是一个开源(BSD 许可)、内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合等数据类型。内置复制、Lua 脚本、LRU

thlzjfefe的博客 402

数据结构实验1.2—高精度计算PI值(西工大)

这是数据结构第二题的题目,是让我们根据用户的需求来计算派的值 这是题目的详细描述,刚看到这道题的时候,我是真的头大,完全没有思路,于是查找了一些大佬的笔记后才开始编写 这是我在写这些代码是所运用到的数学反三角函数幂次展开式的知识。 下面是正确的代码以及我的一些见解,和需要注意的一些地方。希望能对你有所帮助。如有更加精简的算法,请在评论区留下你的算法!!!谢谢!!! #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdl

abcdef0623的博客 5831

Spring-data-redis+Jedis+Redis集群导致的阻塞问题

一、现象 1、项目上使用三个队列来缓存数据,发现其中有一个队列有很多数据,但是消费却非常慢 2、代码使用redisTemplate.opsForList().rightPop 来获取队列里面的数据,这个命令对应的Redis命令是bRPop 3、通过调用链查看,发现brpop命令执行的耗时非常长,最大响应时间达到2秒多 4、在Redis客户端直接使用BRPOP course 30获取数据,执行非常快,并没有感觉到阻塞 二、分析过程 1、BRPOP 是列表的阻塞式(blocking)弹出原语.

duzm200542901104的专栏 1567

Hierarchical Flow Partition(Top-down&&Bottom-up)

hierarchy flow是将设计切分成多个block,分别处理单个block,然后完成后,将它们进行拼接以完成最终的chip。一般划分为三个阶段:chip planning;physical budget就是pin assignmenthierarchy flow实现的方法有两种,一种是top-down,另一种是bottom-up,无论是哪种,都是都要通过flatten的方法分别全局范围进行优化实现。

qq_39493558的博客 3073

PT32F030与MT6826S SPI通讯实战:从硬件连接到数据交互全流程解析

本文详细解析了PT32F030与MT6826S通过SPI通讯的全流程,包括硬件连接、电路设计、SPI外设初始化配置以及数据交互协议实现。通过实战案例和代码示例,帮助开发者快速掌握PT32F030与MT6826S的SPI通讯技术,实现精准的角度和速度数据采集。

weixin_29189373的博客 420

利用Redis队列,如果需要处理大量的消息并且希望避免轮询的开销,使用BLPOP或BRPOP,Java代码实现

consumeMessage方法会阻塞地等待队列中的消息,直到有消息到来或者连接被关闭。当使用Redis来处理大量的消息并希望避免轮询的开销时,确实可以使用BLPOP或BRPOP命令。注意:在实际应用中,你可能需要考虑使用连接池来管理Redis连接,以避免频繁地创建和关闭连接。// result的第一个元素是被弹出消息的key(在这里是队列名),第二个元素是消息本身。// 关闭Jedis连接(通常在实际应用中会放在更合适的地方,如finally块或资源管理器中)// 如果没有消息,阻塞直到有消息到来。

Java程序员专栏 738

土壤数据库辅助工具SPAW计算土壤导水率

首先点击打开根据之前的1比100土壤数据查表得到各个组分含量其中Field Capacity是田间持水量Matric Bulk Density是基质粒密度。

所有专家都曾始于新手 3443

spring-data-redis队列

1、首先加入依赖 org.springframework.data spring-data-redis 1.6.4.RELEASE 2、编写MessageListener import org.springframework.data.redis.connection.Message; import or

Sampson的专栏 4527

2026华为OD机考新系统真题 + 双机位C卷 + 往年真题 - 题库目录分值说明 + 考点说明+在线OJ

2026年4月1日起,华为OD机试正式切换至新系统模式!采用力扣模式,无需自己写输入! 难度大幅度降低。正在备考华为OD机试的同学,优先刷新系统机试真题,可大幅提升通过率。 新系统考题考点与旧版一致,无需重新适应。本专栏所有算法题均配有详细思路解析,并提供C语言、JS、C++、Python、Go、Java多语言源码实现。订阅后私信即可开通专属OJ刷题权限,高效备考一次上岸!

算法大师! 45万+

第4.4节:保护轴承与安全系统

飞轮储能系统的保护轴承是磁悬浮失效时的最后安全屏障,其设计需满足非干涉性、高可靠性和有限寿命承载原则。转子跌落过程包括自由下落、碰撞、进动和滑行减速等复杂非线性阶段,产生远超常规工况的冲击载荷。保护轴承需具备极限冲击容量、高温耐受性和抗卡死能力。系统采用多层级安全架构,结合故障诊断与健康管理,通过监测振动、电流等参数实现预测性维护。安全停机序列有序结合主动制动与被动摩擦制动,确保系统在极端工况下的安全。保护轴承类型多样,需根据系统规模与可靠性要求合理选择。

技术工作者 229

java中Redisson ,jedis,Lettuce和Spring Data Redis的四种深度对比和优缺点详解

Redis Java客户端深度对比:Jedis适合简单场景,提供轻量级API但线程不安全;Lettuce基于Netty支持异步编程,线程安全且性能优异;Redisson提供分布式锁等高级功能;SpringDataRedis与Spring深度集成,简化操作。主流选择上,SpringBoot项目推荐SpringDataRedis+Lettuce组合,兼顾性能与开发效率;分布式系统首选Redisson;传统项目可考虑Jedis。各工具在连接模型、线程安全、适用场景等方面存在显著差异,需根据项目需求选择。

devilnumber的博客 454

SpringBoot+Vue+kkFileView实现文档管理(文档上传、下载、在线预览)

上面在使用OpenOffice实现doc、excel、ppt等文档的管理和预览。除此之外可用kkFileView实现包括且更多文档的预览。

BADAO_LIUMANG_QIZHI的博客 1万+

Java全栈工程师的面试实战:从基础到微服务

在这次面试中,李明展示了他对Java全栈技术的深入了解,包括后端框架如Spring Boot、Spring Security、Spring Data JPA,以及前端框架如Vue3、TypeScript、Pinia等。应聘者(李明): 你好,张工,我是李明,25岁,本科毕业,有4年Java开发经验。李明: 我们用的是Eureka Server,服务启动后会向Eureka注册自己的信息,其他服务可以通过Eureka获取服务地址。李明: 是的,JWT一旦签发,就无法中途撤销,除非设置较短的过期时间。

m0_74824865的博客 321

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【序列晋升】41 Spring Data Redis 进击用法:缓存、分布式锁与消息队列实战详解

Spring Data Redis作为Spring框架对Redis的高级抽象层,为Java开发者提供了便捷的Redis集成方案,通过统一的API简化了Redis操作,同时与Spring生态系统深度整合,支持事务、缓存等多种应用场景。它通过RedisTemplate等核心组件,实现了对不同Redis客户端(如Jedis、Lettuce)的统一抽象,使开发者无需关注底层实现细节,专注于业务逻辑。

愚者Turbo的博客 1612

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比

Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比

爱的叹息的专栏 1895

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Spring Data Redis流处理:Redis Streams在现代应用中的10个实战场景

Spring Data Redis是一个强大的Java开发框架,它提供了对Redis键值存储的全面支持,极大地提升了开发者在Java应用中使用Redis的生产力。Redis Streams作为Redis 5.0引入的重要数据结构,为实时数据流处理提供了强大的支持,而Spring Data Redis则让这一功能在Java应用中变得更加简单易用。本文将深入探讨Spring Data Redis流处理

gitblog_00245的博客 1079

Spring Data Redis本质

今天花半小时补一篇技术文章纯纯是因为早上发的那篇感悟随记很多人可能会认为不是技术文章。而一般这种文章的阅读量会远高于技术文章。为了不破坏公众号的基调,今天写篇技术文章明天一早发出去。大家上班路上看到的是:这还是一个技术公众号。但是我想说的是上篇文章我是在讲技术,如果对技术的理解过于狭隘,那在工作中会很容易进入瓶颈期。咱们宏观到微观来审视一下:业务的服务在技术上需要解决4个问题:分布式、通信、存储和服务治理。在存储方面,spring家族在使用时做了封装就是spring data。

m0_46995061的博客 858

Spring Data Redis + Redisson 学习笔记

适合基础操作和缓存Redisson适合分布式锁和高级功能结合使用可发挥各自优势缓存穿透/击穿/雪崩是必须防范的问题分布式锁必须设置超时时间并正确释放性能优化关注 Pipeline、Lua 脚本、连接池。

m0_56086190的博客 1332

从Spring Boot Redis迁移到Redisson:实现高效分布式数据操作

通过的引入,开发者不仅能简化分布式组件的实现,还能获得更优的性能表现。对于需要复杂分布式协作的场景,Redisson提供了开箱即用的解决方案。建议在微服务架构或高并发系统中优先考虑此方案。附录Redisson官方文档Spring Data Redis迁移示例代码仓库:[GitHub链接]

stay_love的博客 1907
上一篇: 网页中获取网络mp3文件的时常
下一篇: 导出Excel
杜引强
博客等级 码龄13年 806粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值