早在 4 年前,当我发现 Redis5 中增加了 Stream 类型后我就觉得它的这些特性完全可以实现一个完整的 MQ 中间件功能,当时我还在交控工作,当时的项目刚好涉及到大量数据入库的一个需求,当时这个项目不算很大,所以我就想把这个新的技术引入到项目中,实现一个轻量级的基于 Redis 的消息队列。
最终基本上实现了这个功能,当时也做了一个基于 SpringBoot 的 Demo ,后来又改了一版基于 Jedis 版本的,因为可以自己定义和操作多线程,更加灵活自由的实现一些细节。
最近提离职后正在交接期,自己的时间比较多,又翻出这个早起的 Demo ,想改造一下,用到我的心情记录员项目中,如果精力和时间有的话我更想将它完善为一个完整的、可复用的项目。
心情记录员小程序为什么要用到这个?以及为什么不用其他成熟的 RabbitMQ ,首先不用其他成熟的原因是我不想搞太多中间件,一个项目中 Redis 安装是大多数情况,因此我想在保持单体应用的基础上实现一个 MQ ,另外的一个原因就是折腾,这也是我本人的一个“缺点”,什么都喜欢自己折腾一下,验证可行性。接下来说说应用场景吧,心情记录员这款小程序目前调用的 AI 是 Kimi 的平台,目前因为是前期,因此是免费版本,并发数限制到了 1 ,这就会导致一个问题,如果同时有两个或者多个(意淫一下,哈哈哈)同时点了记录的时候,这时候有一个肯定会报错,这时候就可以用到消息队列了,将请求的数据先放入队列,等前一个 AI 生成结束后再次调用,就这?……,一个队列不就搞定了吗?当然还有场景了,那就是目前 AI 生成我采用的是 Stream 流式返回,而我是在点击记录后就开始生成,点击记录后会跳转到结果页面,为了使用户跳过去立马就感觉到在生成,因此我就将调用 AI 接口的动作提前到跳转页面前点击记录按钮后,然后给一定到 Loading 延迟在跳转,跳转到结果页后建立 WebSocket 连接,根据 openId 标识接收消息,这时候这个消息其实已经在上一步中在生成了,这里就可以用到消息队列了,根据对应的 openId 到消息队列中取内容,服务端的 WebSocket 只需要根据标识从消息队列中缓存的生成结果进行返回即可,提升了响应速度。
大概流程就像下图这样:
4 年前这个项目的库和博客:
Gitee-redismq (原谅我以前使用 Gitee 的行为,哈哈哈)
![]() |
1
maocat 2 天前 via Android ![]() 我的评价是,专业的事交给专业的中间件去做
|
2
Yukineko 2 天前
可以用、不好用、没必要
|
3
imokkkk 2 天前 ![]() 可以 但没必要
|
![]() |
4
adoal 2 天前 ![]() 如果为了部署架构简单,而选择用软件 A 做 功能 B 的事,那我可能会更倾向于 everything in PostgreSQL 😄
|
![]() |
5
gesse 2 天前
交控,大量数据入库
是不是 mqtt+时序数据库好点? |
![]() |
6
xiaohupro OP @gesse 不是,你说的这个是信号系统里面的,当时其他项目组这个方面是用 C++开发的,我这个是工程数据 Excel 数据例如电子地图、各种其他表:VOBC 、联锁表等等,当时的这个数据平台设计的时候我才用了精确到单元格级别的存储,方便后面功能的扩展,所以数据量比较大,一个一个工程线路下来有一百万左右的数据入库
|
![]() |
7
Meld 2 天前
我现在就在用 RedisSteam 用来做简单的 MQ
|
8
spritecn 2 天前
个人觉得 list 的 right push + left pop 更靠谱
|
![]() |
10
starryin 2 天前 ![]() 可以,我就这么用过,而且看场景可能是完全是有必要的,说白了一切看需求和成本,尤其是给多个 B 端客户在硬件有限但是流量不小的交付场景,说“没必要”,“everything”就是项目做的少
|
![]() |
11
stephenxiaxy 2 天前
去年,我们也用 redis stream 做的 mq
|
![]() |
13
xiaohupro OP @stephenxiaxy 嗯嗯,这个 Demo 刚写完时就有一个老哥咨询,他最终是用到了他们网站短信发送功能了,用 Redis Stream 做的消息队列,性能还可以
|
![]() |
14
bronyakaka 2 天前
如果消息量很少没事,量大上 kafka ,几十亿几百亿消息
|
![]() |
15
xiaohupro OP @bronyakaka 嗯嗯,是的,这种只适合轻量应用,如果数据量那么大的话就不需要在乎多加额外中间件成文的问题了
|
![]() |
17
starryin 2 天前
@xiaohupro #15 实际上我们当时 Redis 和 Kafka 两个都上了,Redis 的原因是吞吐,限流,Kafka 是为了落盘持久化,而且硬盘的总 IO 有限,都留给 Kafka 了
|
![]() |
18
bronyakaka 2 天前
@starryin #17 那是没设计好,涉及分布式大数据不管啥组件都需要考虑这些问题。这种情况还用 redis 直接爆内存直接不可用
|
19
Ayanokouji 2 天前
可以,也可以用这个代替 redis 。https://nats.io
|
![]() |
21
starryin 2 天前 ![]() @bronyakaka #18 张嘴就来分布式大数据高可用?做 waf 防应用层攻击的时候给你额外落盘处理的时间?爆内存就加内存,redis stream 文档里的的 maxlen 参数看过吗? kafka 不均衡爆盘是不是只会找运维?一再说看需求看成本,你要是拿着八股文 chatgpt 干得更好
|
![]() |
22
simenet 2 天前
我的评价是,专业的事交给专业的中间件去做
|
23
ymy3232 2 天前
我们用 redis stream 好几年了,每天五六十亿数据是有的,我们业务对数据不敏感,数据差异小范围都可以接受,实际用起来也没发现多大差异,从成本上来看对比 kafka 便宜太多
|
![]() |
24
starryin 2 天前
@xiaohupro #20 打个比方说,小公司给客户交付的一台服务器连软件开发加硬件就五万块,你得算计硬盘多少钱,内存多大多少钱,是雇个光会打嘴炮懂个半吊子 MQ 的,还是 redis 和应用层能一把抓的,这种事情很要命,直接决定生死,但是大公司是另一回事,有专门的维护每个中间件的工程师(是不是真熟悉底层另一说),成本收不收回来那也是商业策略问题和员工没关系
|
![]() |
25
guanhui07 2 天前
专业的事交给专业的中间件去做 可以使用 kafka rabbitmq
|
![]() |
26
bronyakaka 2 天前
@starryin #21 你张嘴就拿 WAF 和实时性说事,Redis Stream 的吞吐和 maxlen 能撑小规模没错,但消息量一上来,内存爆炸是你加内存就能随便解决的? Kafka 不均衡、落盘慢是设计没做好,你拿运维当挡箭牌,原帖想做“完整项目”,扩展性是以后要考虑的事情,
更何况我提 Kafka 是给选项,你扣个八股文帽子以为自己懂需求懂成本?技术选型不是靠意气用事,Redis 做大数据场景就是自欺欺人,而且我也没让楼主这种小场景上 kafka ,这点数量级不用 redis 直接进程内异步处理都行,你非要瞎杠 |
![]() |
27
bronyakaka 2 天前
@starryin #21 我都说的很清楚了看数据量级,几十亿几百亿消息你还用 redis 脑子怕是有点问题
|
![]() |
28
bronyakaka 2 天前
@starryin #21 有脸说别人看八股文,我不知道你是读不懂我看数量级的意思还是觉得自己很牛逼,我生产维护的集群每天几十亿消息
|
![]() |
29
bronyakaka 2 天前
@starryin #21 你一说 maxlen 说我都想笑,消息高峰就把你老消息删了,怎么敢的,也就你这种日志场景无所谓是吧,坑别人
|
30
TGhoull 2 天前 ![]() 挺好的,我看国外好多用 redis 做消息队列的,甚至有看到数据库来做消息队列的😂,前提是吞吐量要求不是特别严苛的情况下,另外前两天看一篇技术博客分享 kafka 在低负载下表现很差,我觉得根据自己应用的场景来选择最合适的才是正解。
|
![]() |
31
xiaohupro OP 请大家友好讨论,没有绝对的对错,不要太有攻击性
|
![]() |
32
ppllss 2 天前
的确项目刚开始启动完全没有必要引入大量的中间件,除非就是上线就是高并发
|
33
mark2025 2 天前
一致性,持久性?
|
![]() |
34
DonaldY 2 天前
可以用的。IM 中离线消息就放 redis 队列里。
|
![]() |
35
likeme 2 天前
之前尝试过使用 redis key 过期做延迟任务,比如订单创建 30 分钟后自动触发取消订单,后面开发新项目的时候,有类似的需求,直接使用定时任务一把梭。小项目尽量避免使用更多的组件。当然这是我对“小项目”的理解~
|
36
dxddd 2 天前
我很久之前用 Redis List 去实现消息队列用于发短信,当时是一个小项目,但是突然涌入大良用户导致调用短信服务商 HTTP 请求阻塞。所以说当不想引入 MQ 中间件,这么做问题不大。
|
![]() |
37
starryin 2 天前 ![]() @xiaohupro #25 我挖了个坑,他没注意到,我就知道他什么水平了,已经 block 了
所有无脑劝你用大厂流行技术的回帖,都没有任何价值 有价值的贴子只有两种,一种是用了和你一样的技术,成功了,那他们是什么业务和压力场景,这里的业务当然包含数据价值,比如可不可以丢,延迟多少可以接受,另一种是用了和你一样的技术结果失败了,他们碰到了什么具体绕不过的问题 我在 V2 上并不喜欢发言,因为肉眼可见的菜鸟太多,没精力理会,恰好你这个场景我们以前做过而已,而一开始一水的大厂狗让你换中间件,显然会把人带歪,还好后边跟贴里有不少其他人的实际用例,就不多说了 |
![]() |
38
billbob 2 天前
消息不多用 event,大点 redis,集群才上 mq
|
![]() |
40
8355 2 天前
自己封装了啊 我也现在就在用好用的不得了,延迟极低,对于可靠性要求不是特别高的业务很好用,redis 本身很便宜。
|
![]() |
41
coderge 2 天前
黑马的 Redis 教程里有个小项目 《黑马点评》也用了 Stream 实现 MQ
|
![]() |
42
suifengba 2 天前
我们之前随便 lpush,rpop 都没事
|
![]() |
43
v2e0xAdmin2 2 天前
我用 mq 实现的
|
![]() |
44
v2e0xAdmin2 2 天前
说错了,我用 mysql 实现的 mq
|
![]() |
45
zeusho871 1 天前
交控我看到第一反应是不是干信号的,没想到真是。。。。用过卡斯柯/网新的东西 交控接触的少
|
![]() |
46
xiaohupro OP ![]() @zeusho871 是的轨道交通信号,CBTC 系统,不过我当时所在组主要是给工程数据人员开发数据平台和公司内部的一些系统,真正干信号的同时都是 C 或者 C++
|
![]() |
47
zeusho871 1 天前
@xiaohupro 信号系统底层这块接触的不多,我是使用者😂 卡斯柯这边用的 qt 写的 hmi ,前期 bug 也挺多。 感觉信号系统处理的数据量应该很大吧,各种车载 cc 那边的数据加上轨旁数据,回访日志啥的😂😂😂
|
49
macaodoll 1 天前 via Android
简单需求 Redis list 业务需求还是得上 mq
|
![]() |
50
wm5d8b 1 天前 via Android
消息队列有 n 种选择,甚至 redis4 也能做。对于缓存,redis 算不算垄断性的存在?有没有竞品或替代品
|
51
iamtuzi3333 1 天前
@suifengba 我也用的这个,但是有一个 bug ,就是入队的时候速度很快,然后我 websocket 每秒轮询读取整个 list 数据,会出现偶尔跳过或者重复数据。
|
![]() |
52
suifengba 1 天前
@iamtuzi3333 这个是因为你并发了吧
|
53
iamtuzi3333 1 天前
@suifengba 没并发吧,list 每秒队伍插入一条数据,然后每秒会自动取出 list 的所有数据,时不时就会出现跳过一条数据或者重复一条数据
|
![]() |
54
c332030 1 天前
|
55
noreplay 1 天前 via Android
我觉得可以,我都是这样做
|