分享一个最近想到了一个很妙的设计:一个推模式下使用redis的消息队列实现消息已读未读状态的分离
省流:图就是完整想法
基本实现逻辑很简单,主要依靠redis stream流消息ack后仍可以通过range方法获取的原理。
使用padding来获取未读消息,range来获得所有消息,通过设定队列长度来实现近期消息,通过ack来确认消息,模拟已读,这样就基本实现了一个推模式消息下的状态分离,而且只用了一个数据结构!!!
消息状态
一条短信发送出去后包含有多种状态:未读,已读,已读不回QAQ,近期消息,全部消息。这种状态的区分实现,网上也有很多成熟的方案。
实现方案(为什么用Redis)
对于消息未读状态的实现方式,可以通过数据库中设置状态值,但是用户一多就会导致数据库读写压力太大。网上的一些常见的方法是存储消息,和存储状态分开。然而我就突然到想能不能用消息队列实现,因为消息队列可以read完就直接消费了嘛,这样剩下的不就是未读的了嘛,但是问题又出现了,像一些主流mq实现框架,比如rabbit好像是没办法通过正常手段读取已经消费后的消息的(我搜索后好像是这样),那么还是无法同时记录已读和未读的状态。但是Redis不一样,Redis Stream给人的感觉不像是消费了消息,而是进行了一种ack标记。即便我读了这个消息,我ack了,我查padding也没有了,但是只要一用range查又出来了。这就是选择Redis的原因。
一定需要是推模式吗?
我感觉不一定,如果是拉模式,那就存到发送者id的流中,然后接收者通过stream不同消费者组来消费不知道行不行,这只是我的猜想XD
问题
具体的用途可能大不,这个需要在一个用户量很大而且读多写少的情景下,而且我感觉可能redis的stream和存储状态表相比反而存储状态效率更高一些,你们有感兴趣的可以尝试一下,感觉挺有意思的,这里只提供一个使用消息队列的解决方案。
本人还是学生,知识有限,随笔写的分享,可能存在问题,欢迎大佬指正。