文章目录
【关于作者】
关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(https://0522-isniceday.top/)联系我
1.消息队列的存取需求
不过,消息队列在存取消息时,必须要满足三个需求,分别是消息保序、处理重复的消息和保证消息可靠性。
1.1.消息保序
虽然消费者是异步处理消息,但是,消费者仍然需要按照生产者发送消息的顺序来处理消息,避免后发送的消息被先处理了
1.2.处理重复的消息
消费者从消费消息时候,可能会由于网络堵塞而出现消息重复发送的情况,此时消费者可能会接收到多条重复的消息
1.3.保证消息可靠性
消费消息的过程中可能由于应用宕机或没有处理完成的消费失败的场景,能够做到应用重启后该消息不丢失并重新供给消费者消费
2.基于List的消息队列解决方案
(1)解决消息有序性:
List就是基于先进先出的特性实现消息队列,具体如下图:
Pop和Bpop
Pop:redis可以通过死循环一直执行pop的方式消费数据,但是这样会导致CPU负载提升
Bpop:阻塞式读取,当客户端没有读到队列数据时,直接阻塞,等有新消息入队再开始读取新的消息。
(2)处理重复消息:
消费程序本身需要对重复消息进行判断,例如消息id、或者唯一的业务id。
幂等性原则:对于同一消息,消费者收到一次和收到多次的处理结果是一致的
(3)如何保证消息可靠性
List提供了BRPOPLPUSH命令,让消费者从队列读取消息的同时,Redis将该条消息放入另外一个List(备份list)缓存。
如果消费者读取了消息但是没有正常处理,消费者重启后就可以从备份List读取消息并继续处理了,具体如下:
此时还可能出现的问题就是生产者发送消息很快,消费不过来导致消息积累在队列中,造成内存占用过高。但是List又不支持消费者组进行消费者组模式进行消费,因此Redis 5.0推出了Streams数据类型
2.基于Streams的消息队列解决方案
Streams就是专门为消息队列产生的数据类型,提供了丰富的消息队列的指令
- XADD:插入消息,保证有序,可以自动生成全局唯一ID;
- XREAD:用于读取消息,可以按ID读取数据;
- XREADGROUP:按消费组形式读取消息;
- XPENDING和XACK:XPENDING命令可以用来查询每个消费组内所有消费者已读取但尚未确认的消息,而XACK命令用于向消息队列确认消息处理已完成。
具体的内容后续学习etc…
3.两者比较
4.是否应该采取Redis作为消息队列使用
这个也是得区分场景,
redis的优点:轻量并且部署维护也很轻量,并且一般的业务系统都会使用redis。
redis的缺点:无法保住数据的强一致性,会存在丢数据的情形。
因此如果对于数据是否丢失不那么看着的场景,例如发短信、邮件等可以使用redis,但是对于支付等场景还是建议引入kafak、rockerMQ等专业的消息队列
参考链接:
https://mp.weixin.qq.com/s/KAPIQAOPcbwoxvZ5lZ4hLg