消息模型
1)队列模型
队列模型如图所示,它具有以下几个特点,就像我们用微信和好友(群聊除外)聊天一样,微信就是这个队列,我们可以和很多个好友聊天,但是每条消息只能发给一个好友。
- 只有一个消费者将获得消息
- 生产者不需要在接收者消费该消息期间处于运行状态,接收者也同样不需要在消息发送时处于运行状态。
- 每一个成功处理的消息都由接收者签收
2)发布/订阅模型
发布/订阅模型如图所示,不用说,和订阅公众号是一样的。
- 多个消费者可以获得消息
- 在发布者和订阅者之间存在时间依赖性。发布者需要建立一个topic,以便客户能够购订阅。订阅者必须保持持续的活动状态以接收消息,除非订阅者建立了持久的订阅。在那种情况下,在订阅者未连接时发布的消息将在订阅者重新连接时重新发布
Redis实现
- 对于队列模型,我们可以使用redis的list数据结构,通过LPUSH和RPOP来实现一个队列。
- 发布/订阅模型就更简单了,redis官方就支持,而且还可以使用PSUBSCRIBE支持模式匹配,使用如下命令,即可订阅所有f开头的订阅,具体可查看文档。
PSUBSCRIBE f*
3. keyspace notifications(键空间通知)
该功能是在redis2.8之后引入的,即客户端可以通过pub/sub机制,接收key的变更的消息。换句话说,就是redis官方提供了一些topic,帮助我们去监听redis数据库中的key,我曾经就使用其中的‘keyevent@0:expired’实现了定时任务。
和SpringBoot整合
首先得介绍一下spring-data-redis中的两种template的默认Serializer,当然Spring还提供其他的序列化器,具体可查看文档,也可以自己实现RedisSerializer接口,构建自己的序列化器。
template | default serializer | serialization |
---|---|---|
RedisTemplate | JdkSerializationRedisSerializer | 序列化String类型的key和value |
StringRedisTemplate | StringRedisSerializer | 使用Java序列化 |
消息队列模型
消息队列,这个就需要自己造轮子了,在Spring中使用redisTemlate操作数据库,而对于不同的数据类型则需要不同的操作方式,如下表格所示,具体还是请看官方文档。
实现队列选择list数据结构,redisTemplate.opsForList()使用起来非常简单,和redis命令基本一致。
数据类型 | 操作方式 |
---|---|
string | redisTemplate.opsForValue() |
hash | redisTemplate.opsForHash() |
list | redisTemplate.opsForList() |
set | redisTemplate.opsForSet() |
1.先定义一个消息的POJO(MessageEntity实体类)
2.配置spring data redis
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.johnfnash.learn.redis.queue.entity.MessageEntity;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, MessageEntity> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, MessageEntity> template = new RedisTemplate<String, MessageEntity>();