redis消息队列还有其他吗

如题所述

第1个回答  2017-12-27

基于Redis消息队列-实现短信服务化

1.Redis实现消息队列原理

常用的消息队列有RabbitMQ,ActiveMQ,个人觉得这种消息队列太大太重,本文介绍下基于Redis的轻量级消息队列服务。 
一般来说,消息队列有两种模式,一种是发布者订阅模式,另外一种是生产者和消费者模式。Redis的消息队列,也是基于这2种原理的实现。 
发布者和订阅者模式:发布者发送消息到队列,每个订阅者都能收到一样的消息。 
生产者和消费者模式:生产者将消息放入队列,多个消费者共同监听,谁先抢到资源,谁就从队列中取走消息去处理。注意,每个消息只能最多被一个消费者接收。

2.Redis消息队列使用场景

在我们的项目中,使用消息队列来实现短信的服务化,任何需要发送短信的模块,都可以直接调用短信服务来完成短信的发送。比如用户系统登录注册短信,订单系统的下单成功的短信等。

3.SpringMVC中实现Redis消息队列

因为我们短信只需要发送一次,所以我们使用的是消息队列的生产者和消费者模式。

3.1引入Maven依赖

引入Redis相应的maven依赖,这里需要spring-data-redis和jedis

//pom.xml    <dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.0.RELEASE</version>
</dependency>

<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.5.1</version>
</dependency>12345678910111213

3.2配置redis生成者消费者模式

//applicationContext-redis.xml    <?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:redis="http://www.springframework.org/schema/redis"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-34.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis-1.0.xsd">
<description>spring-data-redis配置</description>

<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"></property>
<property name="port" value="${redis.port}"></property>
<property name="usePool" value="true"></property>
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory"></property>
</bean>

<bean id="jdkSerializer"
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />

<bean id="smsMessageListener"
class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="smsMessageDelegateListener" />
<property name="serializer" ref="jdkSerializer" />
</bean>

<bean id="sendMessage" class="com.djt.common.cache.redis.queue.SendMessage">
<property name="redisTemplate" ref="redisTemplate"/>
</bean>

<redis:listener-container>
<redis:listener ref="smsMessageListener" method="handleMessage"
serializer="jdkSerializer" topic="sms_queue_web_online" />
</redis:listener-container>

<!-- jedis -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="300" /> <!-- 最大能够保持idel状态的对象数  -->
<property name="maxTotal" value="60000" /> <!-- 最大分配的对象数 -->
<property name="testOnBorrow" value="true" /> <!-- 当调用borrow Object方法时,是否进行有效性检查 -->
</bean>

<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="${redis.host}" />
<constructor-arg index="2" value="${redis.port}" type="int" />
</bean></beans>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960

主要的配置说明: 
1.序列化:一般我们向Redis发送一个消息定义的Java对象,这个对象需要序列化。这里使用JdkSerializationRedisSerializer:

<bean id="jdkSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />1

2.发送者:

<bean id="sendMessage" class="com.djt.common.cache.redis.queue.SendMessage">
<property name="redisTemplate" ref="redisTemplate"/>
</bean>123

3.监听者:

<bean id="smsMessageListener"
class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="smsMessageDelegateListener" />
<property name="serializer" ref="jdkSerializer" />
</bean>
<redis:listener-container>
<redis:listener ref="smsMessageListener" method="handleMessage"
serializer="jdkSerializer" topic="sms_queue_web_online" />
</redis:listener-container>123456789

smsMessageListener:消息监听器 
redis:listener-container:定义消息监听,method:监听消息执行的方法,serializer:序列化,topic:监听主题(可以理解为队列名称)

3.3代码实现

1.定义短信消息对象SmsMessageVo

public class SmsMessageVo implements Serializable {
//id
private Integer smsId;    //手机号
private String mobile;    //类型,1:验证码 2:订单通知
private Byte type;    //短信创建时间
private Date createDate;    //短信消息处理时间
private Date processTime;    //短信状态,1:未发送 2:发送成功 3:发送失败
private Byte status;    //短信内容
private String content;    //省略setter和getter方法
...123456789101112131415161718192021222324

2.定义消息队列发送对象SendMessage

//SendMessage.javapublic class SendMessage {    private RedisTemplate<String, Object> redisTemplate;    public RedisTemplate<String, Object> getRedisTemplate() {        return redisTemplate;
}    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {        this.redisTemplate = redisTemplate;
}    public void sendMessage(String channel, Serializable message) {
redisTemplate.convertAndSend(channel, message);
}
}12345678910111213141516171819202122

3.发送消息

String smsContent = templateToContent(template.getContent(),
regMsgCode);
SmsMessageVo smsMessageVo = new SmsMessageVo();
smsMessageVo.setMobile(mobile);
smsMessageVo.setType((byte) SmsType.VERIFICATION.getType());
smsMessageVo.setChannelId(1);
smsMessageVo.setContent(smsContent);
smsMessageVo.setCreateDate(new Date());
smsMessageVo.setStatus((byte) SmsSendStatus.TO_SEND.getType());
smsMessageVo.setTemplateId(1);

//先把待发送的短信存入数据库
SmsQueue smsQueue = new SmsQueue();
BeanUtils.copyProperties(smsQueue, smsMessageVo);
smsQueueService.addSmsQueue(smsQueue);

//异步发送短信到redis队列
sendMessage.sendMessage(Constants.REDIS_QUEUE_SMS_WEB, smsMessageVo);
//Constants.REDIS_QUEUE_SMS_WEB = "sms_queue_web_online",和applicationContext-redis中topic配置一样123456789101112131415161718192021

4.监听消息

//SmsMessageDelegateListener.java@Component("smsMessageDelegateListener")public class SmsMessageDelegateListener {

@Autowired
private SmsQueueService smsQueueService;    //监听Redis消息
public void handleMessage(Serializable message){        if(message instanceof SmsMessageVo){
SmsMessageVo messageVo = (SmsMessageVo) message;            //发送短信
SmsSender smsSender = SmsSenderFactory.buildEMaySender();
smsSender.setMobile(messageVo.getMobile());
smsSender.setContent(messageVo.getContent());            boolean sendSucc = false;            //判断短信类型
//验证码短信
if(messageVo.getType() == (byte)SmsType.VERIFICATION.getType()){
sendSucc = smsSender.send();
}            if(!sendSucc){                return;
}            // 异步更新短信表状态为发送成功
final Integer smsId = messageVo.getSmsId();
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {                public void run() {
SmsQueue smsQueue = new SmsQueue();
smsQueue.setSmsId(smsId);
smsQueue.setStatus((byte)SmsSendStatus.SEND.getType());
smsQueue.setProcessTime(new Date());
smsQueueService.updateSmsQueue(smsQueue);
}
});

}
}
}123456789101112131415161718192021222324252627282930313233343536373839404142434445

4.总结

下面使用一张流程图,来总结Redis消息队列和短信服务。 

阅读全文

Redis 消息队列的三种方案(List、Streams、Pub\/Sub)
然而,Pub\/Sub模式在消息持久化和可靠性方面存在限制,因此,Redis引入了Streams数据结构,提供了更强大、更安全的消息队列功能。总之,Redis提供的List、Streams和Pub\/Sub机制为实现高效、可靠、可扩展的消息队列提供了多种选择。在实际项目中,根据业务需求和场景特点,开发者可以灵活运用这些机制构建出满足各...

redis怎么做消息队列?
1.Redis实现消息队列原理,常用的消息队列有RabbitMQ,ActiveMQ,个人觉得这种消息队列太大太重,本文介绍下基于Redis的轻量级消息队列服务。 一般来说,消息队列有两种模式,一种是发布者订阅模式,另外一种是生产者和消费者模式。Redis的消息队列,也是基于这2种原理的实现。 发布者和订阅者模式:发布者发...

redis一般用来干嘛
消息队列、分布式锁。1、消息队列:Redis可以作为一种高性能的消息队列使用,实现异步处理和解耦。2、分布式锁:Redis可以作为一种分布式锁的存储层,通过缓存锁信息和锁状态,实现分布式锁和并发控制。

Redis 5 种基本数据结构(String、List、Hash、Set、Sorted Set)详解 |...
String,作为Redis最常用的数据结构,支持二进制安全存储,可用于存储各类数据,包括字符串、整数等,且Redis的SDS设计保证了高效和安全性。更多命令和使用指南可在官方文档中查阅。List,Redis的链表实现,适合做消息队列,具有双向查找特性。常用命令如RPUSH\/LPOP实现队列和栈,LRANGE支持高效分页查询。Hash,...

redis 常见数据结构以及使用场景分析?
2、Hash 哈希 在Redis中,哈希类型是指键值本身又是一个键值对 结构,形如value={{field1,value1},...{fieldN,valueN}},添加命令:hset key field value。哈希可以用来存放用户信息,比如实现购物车 3、List 列表 列表(list)类型是用来存储多个有序的字符串。可以做简单的消息队列的功能。

redis一般用来干嘛
用于消息队列和实时分析 Redis由于其数据操作的原子性和发布订阅模式,也常被用于实现消息队列。同时,由于其数据持久化的特性,Redis也被广泛应用于实时数据分析场景。例如,可以通过Redis的计数器进行实时数据统计,利用Redis的地理位置相关功能进行地理位置查询等。此外,Redis还支持分布式锁等功能,为构建高...

Redis 都有哪些应用场景?
共享Session:对于一些依赖 session 功能的服务来说,如果需要从单机变成集群的话,可以选择 redis 来统一管理 session。消息队列系统:消息队列系统可以说是一个大型网站的必备基础组件,因为其具有业务 解耦、非实时业务削峰等特性。Redis提供了发布订阅功能和阻塞队列的功 能,虽然和专业的消息队列比还不够...

redis是什么
2. 会话存储:Redis可以用作会话存储,保存用户的状态信息。3. 消息队列:Redis支持发布\/订阅模式,可以作为简单的消息队列使用。4. 计数器应用:由于其丰富的数据类型和原子操作特性,Redis也被广泛应用于计数器应用,如网页访问量统计等。总之,Redis是一种高性能的键值对数据库,具有快速读写、数据类型...

Redis的简单使用分享
Redis的简单使用分享Redis是一个功能强大的内存数据库,主要用于存储、缓存、消息队列和流处理,支持丰富的数据结构,如字符串、哈希、列表、集合等。官方文档定义它为内存数据结构存储,具有高可用性和自动分区机制。通俗来说,Redis基于C语言开发,提供多种数据类型以满足不同业务需求。例如,字符串可用于...

javaer为什么称redis、rabbitmq这些东西为中间件?
其中,Redis作为一款强大的缓存系统,同时具备消息队列功能,因此被视作中间件。RabbitMQ作为消息队列服务,同样属于中间件范畴。随着中间件概念的广泛运用,消息队列服务和缓存服务成为了开发过程中的既定范例。随着新一代开发者不再需要面对早期系统对接的复杂问题,提及中间件概念的频率已有所下降。

相似回答