借助Spring的定时任务实现redis异步消息队列

应用场景

理论上任何需要消息队列的场景都可通过此方式实现,笔者的应用场景是一个服务完成一个任务需要经过两个不同的队列,任务经过了第一个队列后,需要重新配置入参放入第二个队列。完成第一个队列后的任务放入一个用redis List模拟的消息队列,由处理方法消费消息并处理后处理放入第二个队列。

实现方法

redis异步队列常见的实现方式主要有两种:

一,新消息rpush进入消息队列,每次lpop消息队列,如果没有信息则sleep一段时间然后再次lpop查询(如果没有间隔一直lpop会阻塞其他命令的执行,或直接搞崩redis服务,因为redis是单线程的)这里sleep可以通过spring的@Scheduled的cron定时任务实现,每隔几秒请求一次查看是否有可消费信息。

二,新消息rpush进入消息队列,blpop查看是否有可消费信息,blpop会阻塞队列,可以设置时间,0代表无限时。该命令会一直阻塞队列直到有新的值进入该队列,执行lpop并返回。注:虽然是阻塞,blpop并不影响其他redis命令执行,只不过只有lpop能返回东西时才被执行。具体可查看blpop的实现原理

注:@Scheduled定时任务如果上一次方法没有执行完,后面时间顺延,不会重复执行。具体测试

个人认为第二种方法更好,因为第一种方法会每隔几秒执行一次lpop,仍然会消耗比第二种更多的资源,而且实现上第二种更加简便。

为了防止lpop执行消息被消费后服务器突然挂掉导致该任务丢失的情况,可以采用这种方式避免:每次lpop后设置一个几十秒过期的键存储被消费的值,监听过期,如果过期则重新把该消息lpush进队列;在消息消费完成操作后再将此临时键删除,表示确认该消息成功消费。

注:要尽量保证lpop消费信息和设置临时键两部操作要不同时发生,要不都不发生,不然可能消费后还没有设置临时键就因为服务器崩掉之类的问题丢失消息了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Spring AMQP 和 Redis 消息队列可以实现分布式系统中的异步通信,提高系统的性能和可靠性。 首先,你需要在 Spring Boot 项目中添加 Spring AMQP 和 Redis 的依赖。在 pom.xml 文件中添加以下依赖: ```xml <dependencies> <!-- Spring AMQP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies> ``` 接下来,你需要配置 RabbitMQ 和 Redis 的连接信息。在 application.properties 文件中添加以下配置: ```properties # RabbitMQ spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest # Redis spring.redis.host=localhost spring.redis.port=6379 ``` 然后,你需要创建一个 RabbitMQ 的消息队列和一个 Redis消息队列。在 Spring Boot 项目中,你可以使用 @Bean 注解来创建这些队列。 ```java @Configuration public class QueueConfiguration { @Bean public Queue rabbitQueue() { return new Queue("rabbit.queue"); } @Bean public RedisQueue redisQueue() { return new RedisQueue("redis.queue"); } } ``` 在上面的代码中,我们创建了一个名为 "rabbit.queue" 的 RabbitMQ 队列和一个名为 "redis.queue" 的 Redis 队列。 接下来,你可以在你的代码中使用 RabbitTemplate 和 RedisTemplate 来发送消息。下面是一个简单的例子: ```java @Service public class MessageService { @Autowired private RabbitTemplate rabbitTemplate; @Autowired private RedisTemplate<String, String> redisTemplate; public void sendMessageToRabbit(String message) { rabbitTemplate.convertAndSend("rabbit.queue", message); } public void sendMessageToRedis(String message) { redisTemplate.convertAndSend("redis.queue", message); } } ``` 在上面的代码中,我们创建了一个 MessageService 类来发送消息。我们使用 rabbitTemplate.convertAndSend 方法来发送消息到 RabbitMQ 队列,使用 redisTemplate.convertAndSend 方法来发送消息到 Redis 队列。 最后,你需要在你的代码中使用 @RabbitListener 和 @RedisQueueListener 注解来接收消息。下面是一个简单的例子: ```java @Service public class MessageService { @Autowired private RabbitTemplate rabbitTemplate; @Autowired private RedisTemplate<String, String> redisTemplate; @RabbitListener(queues = "rabbit.queue") public void receiveMessageFromRabbit(String message) { System.out.println("Received message from RabbitMQ: " + message); } @RedisQueueListener(queues = "redis.queue") public void receiveMessageFromRedis(String message) { System.out.println("Received message from Redis: " + message); } } ``` 在上面的代码中,我们使用 @RabbitListener 注解来监听 RabbitMQ 队列中的消息,使用 @RedisQueueListener 注解来监听 Redis 队列中的消息。 总之,使用 Spring AMQP 和 Redis 消息队列可以方便地实现分布式系统中的异步通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值