Spring Data Redis实现消息队列——发布/订阅模式
一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式。利用redis这两种场景的消息队列都能够实现。
定义:
生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列,谁先抢到消息谁就会从队列中取走消息;即对于每个消息只能被最多一个消费者拥有。
发布者订阅者模式:发布者生产消息放到队列里,多个监听队列的消费者都会收到同一份消息;即正常情况下每个消费者收到的消息应该都是一样的。
下面就以Spring Data Redis实现简单的消息“发布/订阅”服务。
spring-redis使用RedisMessageListenerContainer进行消息监听,客户程序需要自己实现MessageListener,并以指定的topic注册到RedisMessageListenerContainer,这样,在指定的topic上如果有消息,RedisMessageListenerContainer便会通知该MessageListener。
下面是在spring配置文件中配置spring-redis:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!-- 引入jedis配置文件 -->
<context:property-placeholder location="classpath*:resource/redis.properties" /> <context:component-scan base-package="com.ljq.durian" /> <!-- jedis pool配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
<property name="testOnReturn" value="${redis.testOnReturn}" />
</bean> <!-- spring data redis -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="poolConfig" ref="jedisPoolConfig"></property>
<property name="timeout" value="${redis.timeout}"></property>
<property name="usePool" value="true"></property>
</bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
<property name="defaultSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
</bean> <bean id="redisMessageListener" class="com.ljq.durian.common.listener.RedisMessageListener">
<property name="redisTemplate" ref="redisTemplate"/>
</bean> <bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="messageListeners">
<map>
<entry key-ref="redisMessageListener">
<list>
<!-- 普通订阅,订阅具体的频道 -->
<bean class="org.springframework.data.redis.listener.ChannelTopic">
<constructor-arg value="topic.channel" />
</bean>
<!-- 模式订阅,支持模式匹配订阅,*为模糊匹配符 -->
<bean class="org.springframework.data.redis.listener.PatternTopic">
<constructor-arg value="topic.*" />
</bean>
<!-- 匹配所有频道 -->
<bean class="org.springframework.data.redis.listener.PatternTopic">
<constructor-arg value="*" />
</bean>
</list>
</entry>
</map>
</property>
</bean> </beans>
上面例子中,最后三个bean的配置是实现发布/订阅服务的关键,RedisMessageListener是自己写的实现了org.springframework.data.redis.connection.MessageListener的业务类,并以“topic.channel” 这个topic注册到RedisMessageListenerContainer。RedisMessageListenerContainer在消息到达后负责通知MessageListener。
下面是RedisMessageListener的代码:
package com.ljq.durian.common.listener; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer; public class RedisMessageListener implements MessageListener {
@Autowired
private RedisTemplate<String, String> redisTemplate; @Override
public void onMessage(Message message, byte[] pattern) {
RedisSerializer<?> serializer = redisTemplate.getValueSerializer();
Object channel = serializer.deserialize(message.getChannel());
Object body = serializer.deserialize(message.getBody());
System.out.println("主题: " + channel);
System.out.println("消息内容: " + String.valueOf(body));
} public RedisTemplate<String, String> getRedisTemplate() {
return redisTemplate;
} public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
}
这样,应用启动时,消息的订阅方(subscriber)就注册好了。这时候只要使用一个简单的程序,模拟publisher,向指定topic发布消息,RedisMessageListener就可以接收到消息,spring-redis的写法是这样:
redisTemplate.convertAndSend("topic.channel", "hello world!");
Spring Data Redis实现消息队列——发布/订阅模式的更多相关文章
- redis实现消息队列&发布/订阅模式使用
在项目中用到了redis作为缓存,再学习了ActiveMq之后想着用redis实现简单的消息队列,下面做记录. Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易的实现一个高性 ...
- 【转】redis 消息队列发布订阅模式spring boot实现
最近做项目的时候写到一个事件推送的场景.之前的实现方式是起job一直查询数据库,看看有没有最新的消息.这种方式非常的不优雅,反正我是不能忍,由于羡慕本身就依赖redis,刚好redis 也有消息队列的 ...
- Spring源码之七registerListeners()及发布订阅模式
Spring源码之七registerListeners()及发布订阅模式 大家好,我是程序员田同学. 今天带大家解读refresh()方法中的registerListeners()方法,也就是我们经常 ...
- Spring Boot使用Redis进行消息的发布订阅
今天来学习如何利用Spring Data对Redis的支持来实现消息的发布订阅机制.发布订阅是一种典型的异步通信模型,可以让消息的发布者和订阅者充分解耦.在我们的例子中,我们将使用StringRedi ...
- redis消息通知(任务队列/优先级队列/发布订阅模式)
1.任务队列 对于发送邮件或者是复杂计算这样的操作,常常需要比较长的时间,为了不影响web应用的正常使用,避免页面显示被阻塞,常常会将此类任务存入任务队列交由专门的进程去处理. 队列最基础的方法如下: ...
- rabbitmq消息队列——"发布订阅"
三."发布订阅" 上一节的练习中我们创建了一个工作队列.队列中的每条消息都会被发送至一个工作进程.这节,我们将做些完全不同的事情--我们将发送单个消息发送至多个消费者.这种模式就是 ...
- Redis实现消息的发布/订阅
利用spring-boot结合redis进行消息的发布与订阅: 发布: class Publish { private static String topicName = “Topic:chat”; ...
- redis之mq实现发布订阅模式
示例代码-github 概述 Redis不仅可作为缓存服务器,还可用作消息队列,本示例演示如何使用redis实现发布/订阅消息队列. 在Redis中,发布者没有将消息发送给特定订阅者的程序.相反,发布 ...
- Redis进阶篇:发布订阅模式原理与运用
"65 哥,如果你交了个漂亮小姐姐做女朋友,你会通过什么方式将这个消息广而告之给你的微信好友?" "那不得拍点女朋友的美照 + 亲密照弄一个九宫格图文消息在朋友圈发布大肆 ...
随机推荐
- HBase Snapshot简介
一.简介 HBase 从0.95开始引入了Snapshot,可以对table进行Snapshot,也可以Restore到Snapshot.Snapshot可以在线做,也可以离线做.Snapshot的实 ...
- Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业
(a) 利用ford-fulkerson算法即可求出最大流和最小分割. (b) 剩余网络为 由S可达的顶点为A.B.可达T的顶点为C. (c) 瓶颈边有e(A,C),e(B,C). (d) 下图中不包 ...
- [C]内存管理、内存泄露、堆栈
原文地址:https://www.cnblogs.com/youthshouting/p/4280543.html,转载请注明源地址. 1.内存分配区间: 对于一个C语言程序而言,内存 ...
- scp命令:远程复制粘贴文件
文章链接:https://www.cnblogs.com/webnote/p/5877920.html scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有 ...
- 22)django-中间件
一:中间件介绍 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后, django会根据自己的规则在合适的时机执行中间件中相应的方法. 在dj ...
- python-面向对象入门
一.面向对象介绍 介绍面向对象之前,先来回顾一下以前学的面向过程的编程思想 面向过程编程: 核心是过程二字,过程指的是解决问题的步骤,即先干什么,再干什么后干什么,基于该思想编程就好比是在设计一条流水 ...
- thinkphp (tcms)
使用的是:3.2.3模板: js获取thinkphp数组时:var obj = {:json_encode($obj)}: 转成js对象:进而再处理: 创建公共控制器: thinkphp:ajax返回 ...
- Confluence 6 MBeans
你可以使用下面的 Confluence MBeans 来实时查看你 Confluence 实例运行的实时信息. CacheStatistics 这个 MBean 显示了 Confluence 有关的 ...
- Confluence 6 配置 Office 连接器选项
具有系统管理员权限的用户可以配置 Office 连接器的属性和相关表现. 希望设置 Office 连接器的配置属性: 进入 > 基本配置(General Configuration) > ...
- 【kafka】生产者速度测试
非常有用的参考博客:http://blog.csdn.net/qq_33160722/article/details/52903380 pykafka文档:http://pykafka.readthe ...