前言
首先要明确消息队列的作用:异步、解耦、削峰
就算平时开发中,没有大流量,解耦和异步几乎也是离不开的,这就体现了MQ的重要性
但是,总有公司不用啊,但是Redis总用吧,Redis的List结构非常适合用来作消息队列
使用Redis实现消息队列有两种方式
- Redis队列模式
- Redis发布订阅模式
原理
我们需要了解Redis的命令
Redis的List有两种命令方式,均满足先进先出的队列模式
lpush
rpop
:非阻塞式lpush
brpop
:阻塞式
lpush rpop
127.0.0.1:6379[2]> lpush testmq a b c //创建队列
(integer) 3
127.0.0.1:6379[2]> lrange testmq 0 -1 //查看value
1) "c"
2) "b"
3) "a"
127.0.0.1:6379[2]> rpop testmq //取值
"a"
127.0.0.1:6379[2]> rpop testmq //...
"b"
127.0.0.1:6379[2]> rpop testmq //...
"c"
127.0.0.1:6379[2]> lrange testmq 0 -1 //已经没有数据了
(empty list or set)
127.0.0.1:6379[2]> keys * //没有值时,队列会被删除
(empty list or set)
127.0.0.1:6379[2]> rpop testmq //但是还可以取值
(nil)
lpush brpop
127.0.0.1:6379[1]> brpop testmq 0 //执行brpop命令,但是并没有key=testmq的队列,陷入阻塞中
127.0.0.1:6379[1]> lpush testmq a b //这里打开了一个新的cli,并向testmq中插入数据a b
(integer) 2
127.0.0.1:6379[1]>
127.0.0.1:6379[1]> brpop testmq 0 //在看原来的cli,可以看出,已经取到值了,还可以看到等待了多久
1) "testmq"
2) "a"
(201.71s)
127.0.0.1:6379[1]> lrange testmq 0 -1 //查看testmq,可以看出a已经被取走
1) "b"
127.0.0.1:6379[1]> keys *
(empty list or set)
127.0.0.1:6379[1]> lpush testmq a //向testmq中添加a
(integer) 1
127.0.0.1:6379[1]> lpush testmq2 b //向testmq2中添加b
(integer) 1
127.0.0.1:6379[1]> lrange testmq 0 -1 //查看testmq
1) "a"
127.0.0.1:6379[1]> lrange testmq2 0 -1 //查看testmq2
1) "b"
127.0.0.1:6379[1]> brpop testmq2 testmq 0 //brpop可以接收多个key,会按照顺序读取,这里可以实现一个优先级的功能,这里可以看出接收了testmq2的value
1) "testmq2"
2) "b"
从命令中可以看出,brpop可以接收多个键,意义是同时检测多个键,如果所有键都没有元素,则阻塞,如果其中一个有元素则从该键中弹出该元素,只弹出一个消息.
(会按照key的顺序进行读取,可以实现具有优先级的队列)。
代码
消费者
并没有内置消费者监听器来实现,可以直接使用定时器实现
@Component
public class MsgTask {
@Resource
private RedisTemplate redisTemplate;
@Scheduled(cron="*/5 * * * * *")
public void sendMsg() {
Object listMQ = redisTemplate.opsForList().rightPop("listMQ", 0, TimeUnit.SECONDS);
System.out.println(listMQ.toString());
}
}
然后使用普通的添加方法就实现了这个简单的消息队列了
redisTemplate.opsForList().leftPush("listMQ","a");
参考
文章1:https://blog.csdn.net/qq_42175986/article/details/88417023
文章2:https://springboot.io/t/topic/1013