redis实现消息队列需要满足的三个点:
1 消息保序:虽然消息时异步处理的,消费者仍然需要消息按顺序消费,避免逻辑不通产生错误。
list数据结构是先进先出的方式操作数据。生产者把数据通过LPUSH将消息写入list。消费者通过RPOP从list的另一端获取数据并进行消费。
但是消费者获取数据并不是队列依赖数据就去获取,想要去获取数据一般都是通过不停的调用RPOP方法,比如while方法或者定时任务。没有消息也会一直执行,这样会消耗CPU资源。
为了解决这个问题,redis提供了BRPOP命令,被称为阻塞式读取,客户端在没有读到数据时进入阻塞状态,当有数据写入队列时再进行读取。
2 处理重复的消息:
生产者给消息生成一条全局位移的ID号,并通过队列发送给消费者,消费者存储。当再有消息过来时,会比对全局ID,判断消息是否被消费过,幂等性。
3 保证消息可靠性:
消费者程序出现故障,消费还没有消费时,那这条消息就丢失了。为了应对这周情况,list提供了BRPOPLPUSH命令,这个命令的作用是消费者获取了队列的消息,同时会把这个消息再插入到另一个队列中留存。这样就避免了消费者宕机数据丢失的问题,启动后可以从备用队列中去读取。
4 生产者消息生产很快,消费者来不及消费
redis从5.0开始提供stream数据类型。
stream是redis专门为消息队列设计的数据结构。
XADD 插入消息,保证有序,可以自动生成全局位移ID。 XADD mqstream * repo 5返回一个全局id。加一个*更加高效。
XREAD 读取消息可以按ID读取。 XREAD BLOCK 100 STREAM mysteam 1345452343543-0。如上的block阻塞,消息队列中没有消息则Xread会进入阻塞状态。
XREAD BLOCK 100 STREAM mysteam $ $是读取最新的消息。
XREADGROUP 按消费者组读取消息。
XPENDING:XPENDING来查询消费者里所有所有消费者已读取但还没有确认的消息。
XACK: 是确认消息处理完成。