SpringBoot基于Redis快速实现消息队列
1.常用消息队列工具
目前常用的消息队列大概有三种类型,RabbitMQ等AMQP系列,kafka,Redis等key value系列,他们的使用场景分别是:
1,rabbitMq:相对重量级的并发的情况,比如数据的异步处理 任务的串行执行等。
2,kafka:基于Pull的模式来处理,集体很高的吞吐量,一般用来进行 日志的存储和收集。
3,redis:轻量级高并发,实时性要求高的情况,比如缓存,秒杀,及时的数据分析(ELK日志分析框架,使用的就是redis)
2.springBoot基于redis集成消息队列
实现:
1,maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2,redis的配置
spring:
redis:
database: 1 #索引(默认为0)
host: localhost #地址
port: 6379 #端口号
#password: #连接密码(默认空)
pool:
max-idle: 8 #连接池中的最大空闲连接
min-idle: 0 #连接池中的最小空闲连接
max-active: 8 #连接池最大连接数(使用负值表示没有限制)
max-wait: -1 #连接池最大阻塞等待时间(使用负值表示没有限制)
#sentinel:
#master: mymaster # 哨兵监听的Redis server的名称
#nodes:
127.0.0.1:26379,127.0.0.1:26479,127.0.0.1:26579 #哨兵的配置列表
timeout: 0 #连接超时时间(毫秒)
3,注册监听者和发送消息
1,一个连接工厂(connection factory)
2,一个消息监听者容器(message listener container)
3,一个redis的模版(redis template)
我们通过redis模版来发送消息,同时将receiver注册给消息监听者容器。连接工厂将两者连接起来,使得他们可以通过redis服务器通信,如何连接呢?我们将连接工厂实例分别注入监听者容器和redis模版中即可。
首先是连接工厂,使用springBoot默认的RedisConnectionFactory,是jedisRedis库提供的JedisConnectionFactory实现。
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat"));
return container;
也可以自己创建连接工厂:
首先创建一个jedis连接池:
@Bean
JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig JedisPoolConfig = new JedisPoolConfig();
JedisPoolConfig.setMaxTotal(maxTotal);
JedisPoolConfig.setMinIdle(minIdel);
JedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
JedisPoolConfig.setTestOnBorrow(testOnBorrow);
JedisPoolConfig.setTestOnReturn(testOnReturn);
JedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
JedisPoolConfig.setTestWhileIdle(testWhileIdle);
JedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
JedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
return JedisPoolConfig;
}
然后使用连接池来创建一个连接工厂:
@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.setHostName(hostName);
jedisConnectionFactory.setPort(port);
jedisConnectionFactory.setPassword(password);
jedisConnectionFactory.setUsePool(true);
jedisConnectionFactory.setDatabase(dbIndex);
return jedisConnectionFactory;
}
《对应的属性值都是从property配置文件中读取出来的》
然后是redisTemplate
@Bean
@Scope("prototype")
RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
return redisTemplate;
}
最后是redis的监听者
采用的方式为实现 MessageListener
public class RedisMessageListener implements MessageListener {
private GeneratorProcessor generatorProcessor;
public RedisMessageListener(GeneratorProcessor generatorProcessor) {
super();
this.generatorProcessor = generatorProcessor;
}
@Override
public void onMessage(final Message message, final byte[] pattern) {
String msg = message.toString();
if (msg.startsWith(RedisConstans.REDIS_TASK_ADD_SCORE)) {
//积分处理
String messageJson = msg.substring(RedisConstans.REDIS_TASK_ADD_SCORE.length(), msg.length());
generatorProcessor.calculate(messageJson);
}
}
}
消息的发布者 实现类
public class RedisPublisherImpl implements IRedisPublisher {
private RedisTemplate<String, Object> redisTemplate;
private String channel;
public RedisPublisherImpl(RedisTemplate<String, Object> redisTemplate, String channel) {
super();
this.redisTemplate = redisTemplate;
this.channel = channel;
}
@Override
public void sendMessage(String msg) {
redisTemplate.convertAndSend(channel, msg);
}
}
接口
public interface IRedisPublisher {
public void sendMessage(String msg);
}