Spring Data Redis
来源:互联网 发布:网络利大于弊辩论会 编辑:程序博客网 时间:2024/06/05 00:36
5.9. Redis Messaging/PubSub
Spring Data 提供 dedicated messaging 整合 for Redis, very similar in functionality and naming to the JMS integration in Spring Framework; 事实上, 用户熟悉 the JMS support in Spring should feel right at home.
Redis 消息 can be roughly 分成 two areas of functionality, namely the production or publication and consumption or subscription of messages, 因此简称为pubsub (Publish/Subscribe). RedisTemplate类 is used for message production. 对于异步的接收如同 Java EE’s message-driven bean style, Spring Data provides a dedicated message listener container that is used to create Message-Driven POJOs (MDPs) and for synchronous reception, the RedisConnection contract.
The package org.springframework.data.redis.connection and org.springframework.data.redis.listener provide the core functionality for using Redis messaging.
5.9.1. Sending/Publishing messages
要发布一个消息, one can use, as with the other operations, 要么使用低级别的RedisConnection
要么使用高级的RedisTemplate
. Both entities offer the publish method that accepts as an argument the message that needs to be sent as well as the destination channel. While RedisConnection requires raw-data (array of bytes), the RedisTemplate allow arbitrary objects to be passed in as messages:
// 1.send message through connection RedisConnection con = ...byte[] msg = ...byte[] channel = ...con.publish(msg, channel);// 2.send message through RedisTemplateRedisTemplate template = ...template.convertAndSend("hello!", "world");
5.9.2. Receiving/Subscribing for messages
在接收端, 一端可以订阅一个或多个要么通过直接命名的方式,要么通过模式匹配的方式。The latter approach is quite useful as it not only allows multiple subscriptions to be created with one command but to also listen on channels not yet created at subscription time (只要他们匹配模式).
在低级别中, RedisConnection
提供 subscribe
and pSubscribe
方法,匹配Redis命令行中的订阅命令 that map the Redis commands for subscribing by channel respectively by pattern. 注意,多样的频道和模式 can be used as arguments. To change the subscription of a connection or simply query whether it is listening or not, RedisConnection
provides getSubscription
and isSubscribed
方法.
Subscription命令在Spring Data Redis中是阻塞的. That is, calling subscribe on a connection will cause the current thread to block as it will start waiting for messages - the thread will be released only if the subscription is canceled, that is an additional thread invokes `unsubscribe` or `pUnsubscribe` on the same connection. See message listener container below for a solution to this problem.
上面说道的, 一旦订阅连接等待消息. No other commands can be invoked on it except for adding new subscriptions or modifying/canceling the existing ones. That is, invoking anything other then subscribe, pSubscribe, unsubscribe, or pUnsubscribe is illegal and will throw an exception.
为了订阅消息, 接收端需要实现接口MessageListener
回调: 每次一个新消息到达, 回调获得调用并且用户代码通过通过onMessage
方法执行. The interface gives access not only to the actual message but to the channel it has been received through and the pattern (if any) used by the subscription to match the channel. This information allows the callee to differentiate between various messages not just by content but also through data.
Message Listener Containers
由于它的阻塞类型, low-level subscription is not attractive as it requires connection and thread management for every single listener. To alleviate this problem, Spring Data offers RedisMessageListenerContainer
which does all the heavy lifting on behalf of the user - users familiar with EJB and JMS should find the concepts familiar as it is designed as close as possible to the support in Spring Framework and its message-driven POJOs (MDPs)
RedisMessageListenerContainer
作为一个消息监听容器执行; 它用来从一个Redis频道中接收消息并且drive the MessageListener
s that are injected into it. The listener container is responsible for all threading of message reception and dispatches into the listener for processing. A message listener container is the intermediary between an MDP and a messaging provider, and takes care of registering to receive messages, resource acquisition and release, exception conversion and the like. This allows you as an application developer to write the (possibly complex) business logic associated with receiving a message (and reacting to it), and delegates boilerplate Redis infrastructure concerns to the framework.
而且, to minimize the application 占用的空间, RedisMessageListenerContainer
allows one connection and one thread to be shared by multiple listeners even though they do not share a subscription. Thus no matter how many listeners or channels an application tracks, the runtime cost will remain the same through out its lifetime. Moreover, the container allows runtime configuration changes so one can add or remove listeners while an application is running without the need for restart. Additionally, the container uses a lazy subscription approach, using a RedisConnection only when needed - if all the listeners are unsubscribed, cleanup is automatically performed and the used thread released.
To help with the asynch manner of messages, the container requires a java.util.concurrent.Executor
( or Spring’s TaskExecutor
) for dispatching the messages. Depending on the load, the number of listeners or the runtime environment, one should change or tweak the executor to better serve her needs - in particular in managed environments (such as app servers), it is highly recommended to pick a a proper TaskExecutor to take advantage of its runtime.
The MessageListenerAdapter
MessageListenerAdapter
类是最终的部分 in Spring’s asynchronous messaging support: in a nutshell, it allows you to expose almost any class as a MDP (there are of course some constraints).
考虑下面的接口定义. 注意尽管这个接口没有继承MessageListener
接口, it can still be used as a MDP via the use of the MessageListenerAdapter
类. Notice also how the various message handling methods are strongly typed according to the contents of the various Message types that they can receive and handle. 另外, the channel or pattern to which a message is sent can be passed in to the method as the second argument of type String:
public interface MessageDelegate { void handleMessage(String message); void handleMessage(Map message); void handleMessage(byte[] message); void handleMessage(Serializable message); // pass the channel/pattern as well void handleMessage(Serializable message, String channel); }
public class DefaultMessageDelegate implements MessageDelegate { // implementation elided for clarity...}
尤其地, 注意上面的实现类是如何实现MessageDelegate
接口的 (上面的 DefaultMessageDelegate
类) 根本没有依赖Redis. It truly is a POJO that we will make into an MDP 通过下面的配置.
<?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:redis="http://www.springframework.org/schema/redis" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd"><!-- the default ConnectionFactory --><redis:listener-container> <!-- the method attribute can be skipped as the default method name is "handleMessage" --> <redis:listener ref="listener" method="handleMessage" topic="chatroom" /></redis:listener-container><bean id="listener" class="redisexample.DefaultMessageDelegate"/> ...<beans>
主题监听器可以是一个频道 (e.g. topic="chatroom") or a pattern (e.g. topic="*room")
上面的例子使用Redis 命名空间来声明消息监听容器并且自动注册 the POJOs作为监听器. The full blown, bean的定义展示如下:
<bean id="messageListener" class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter"> <constructor-arg> <bean class="redisexample.DefaultMessageDelegate"/> </constructor-arg></bean><bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <property name="messageListeners"> <map> <entry key-ref="messageListener"> <bean class="org.springframework.data.redis.listener.ChannelTopic"> <constructor-arg value="chatroom"> </bean> </entry> </map> </property></bean>
每次接收一个消息, 适配器自动地执行转换 (using the configured RedisSerializer) between the low-level format and the required object type transparently. Any exception caused by the method invocation is caught and handled by the container (by default, being logged).
- redis:spring-data-redis
- redis Jredis spring-data-redis
- spring data redis 操作redis
- Spring Data Redis (Redis Support)
- Spring Data Redis(Redis Transactions)
- Spring Data Redis(Redis Scripting)
- Spring Data Redis(Redis Cluster)
- Spring Data Redis(Redis Repositories)
- spring data redis 操作redis
- SPRING DATA - REDIS配置
- spring data redis试用
- SPRING DATA - REDIS配置
- SPRING DATA - REDIS配置
- Spring-Data-Redis特性
- Spring Data Redis
- spring-data-redis 使用
- spring-data集成redis
- spring-data-redis 使用
- Ceil和Floor函数
- TOP命令解析
- Bug导致的 enq: DX - contention等…
- dagger2 一 引入dagger2注解
- Rman 0级和2级增量备份的恢复测试(…
- Spring Data Redis
- UE4-静态加载蓝图类的方式
- Standby Database归档空间满的故障
- ORA-609 : TNS-12537: TNS:connect…
- GitHub上star超过2k的安卓项目和代码风格指南(绝对干货)
- How to recreate the index fnd_lo…
- Standby Database的配置,做个记录
- EBS: How to clone?
- 一些后台进程的Description