V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaohupro
V2EX  ›  Redis

Redis Stream 实现 MQ 的可行性

  •  
  •   xiaohupro ·
    hubianluanma · 33 天前 · 3957 次点击
    这是一个创建于 33 天前的主题,其中的信息可能已经有所发展或是发生改变。

    早在 4 年前,当我发现 Redis5 中增加了 Stream 类型后我就觉得它的这些特性完全可以实现一个完整的 MQ 中间件功能,当时我还在交控工作,当时的项目刚好涉及到大量数据入库的一个需求,当时这个项目不算很大,所以我就想把这个新的技术引入到项目中,实现一个轻量级的基于 Redis 的消息队列。

    最终基本上实现了这个功能,当时也做了一个基于 SpringBoot 的 Demo ,后来又改了一版基于 Jedis 版本的,因为可以自己定义和操作多线程,更加灵活自由的实现一些细节。

    最近提离职后正在交接期,自己的时间比较多,又翻出这个早起的 Demo ,想改造一下,用到我的心情记录员项目中,如果精力和时间有的话我更想将它完善为一个完整的、可复用的项目。

    心情记录员小程序为什么要用到这个?以及为什么不用其他成熟的 RabbitMQ ,首先不用其他成熟的原因是我不想搞太多中间件,一个项目中 Redis 安装是大多数情况,因此我想在保持单体应用的基础上实现一个 MQ ,另外的一个原因就是折腾,这也是我本人的一个“缺点”,什么都喜欢自己折腾一下,验证可行性。接下来说说应用场景吧,心情记录员这款小程序目前调用的 AI 是 Kimi 的平台,目前因为是前期,因此是免费版本,并发数限制到了 1 ,这就会导致一个问题,如果同时有两个或者多个(意淫一下,哈哈哈)同时点了记录的时候,这时候有一个肯定会报错,这时候就可以用到消息队列了,将请求的数据先放入队列,等前一个 AI 生成结束后再次调用,就这?……,一个队列不就搞定了吗?当然还有场景了,那就是目前 AI 生成我采用的是 Stream 流式返回,而我是在点击记录后就开始生成,点击记录后会跳转到结果页面,为了使用户跳过去立马就感觉到在生成,因此我就将调用 AI 接口的动作提前到跳转页面前点击记录按钮后,然后给一定到 Loading 延迟在跳转,跳转到结果页后建立 WebSocket 连接,根据 openId 标识接收消息,这时候这个消息其实已经在上一步中在生成了,这里就可以用到消息队列了,根据对应的 openId 到消息队列中取内容,服务端的 WebSocket 只需要根据标识从消息队列中缓存的生成结果进行返回即可,提升了响应速度。

    大概流程就像下图这样: 心情记录员.drawio.png

    4 年前这个项目的库和博客:

    Gitee-redismq (原谅我以前使用 Gitee 的行为,哈哈哈)

    CSDN 博客(如果对 CSDN 排斥可以访问下面我自己网站的文章)

    个人网站文章地址

    56 条回复    2025-02-28 21:02:10 +08:00
    maocat
        1
    maocat  
       33 天前 via Android   ❤️ 3
    我的评价是,专业的事交给专业的中间件去做
    Yukineko
        2
    Yukineko  
       33 天前
    可以用、不好用、没必要
    imokkkk
        3
    imokkkk  
       33 天前   ❤️ 1
    可以 但没必要
    adoal
        4
    adoal  
       33 天前   ❤️ 4
    如果为了部署架构简单,而选择用软件 A 做 功能 B 的事,那我可能会更倾向于 everything in PostgreSQL 😄
    gesse
        5
    gesse  
       33 天前
    交控,大量数据入库

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