V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
smallgoogle
V2EX  ›  Python

你们是如何使用 redis 来监听任务的?

  •  
  •   smallgoogle · Aug 11, 2020 · 8567 views
    This topic created in 2086 days ago, the information mentioned may be changed or developed.
    鄙人有个需求就是,A 服务把数据推到 redis,B 服务一直监听 redis list,如果有数据就弹出。
    我在 B 服务里用的是 blpop,可这个命令是阻塞的。意思是如果 redis 的 list 一直没有数据 这个位置就一直阻塞,直到监听到一个数据 然后弹出。。。
    那么问题就来了,先不说程序效率不效率的,或者是超时不超时的。因为目前我发现我还没等到超时呢,内存就溢出了。。或者说这个阻塞导致了系统自动结果了 B 服务的进程。因为我报错如下:
    ```
    OSError: [Errno 12] Cannot allocate memory
    ```

    那么问题来了,我如何可以优雅的监听 list 是否有新数据呢?
    Supplement 1  ·  Aug 11, 2020
    各位大佬,其实我用 redis 的原因 大部分是想兼顾其他数据的临时缓存,顺带把这个事情也做了。数据不重要,所以大家不需要考虑丢失的问题。我觉得大家让我用 mq 是没错的。只是我还达不到要用 mq 。。所以现在就在 redis 这个地方卡一下。。
    Supplement 2  ·  Aug 13, 2020
    好了。大家不要刚了。。溢出是我的多进程问题。。redis 确实没问题。。感谢大家呲醒。 还有刚 mq 的。其实业务不大,虽然也不小。但是可以使用 redis 解决大多数问题。就懒得上别的东西了。毕竟上的多了。管理起来也费劲。毕竟不只是一个业务板块在手上。
    56 replies    2020-08-12 13:40:44 +08:00
    fdingiit
        1
    fdingiit  
       Aug 11, 2020
    为什么不选择专业的而选择二道贩子
    smallgoogle
        2
    smallgoogle  
    OP
       Aug 11, 2020
    @fdingiit 我是不是应该在 A 服务里写一个频道通知? 然后 B 服务监听频道,收到频道通知 再去取 list ?
    wangritian
        3
    wangritian  
       Aug 11, 2020
    blpop 换成 lpop 然后加一个取到空数据的小延迟
    xkeyideal
        4
    xkeyideal  
       Aug 11, 2020
    redis 啥时候可以干数据变化推送的功能了
    FaceBug
        5
    FaceBug  
       Aug 11, 2020
    B 服务 lpop,如果有数据就一直取数据,并进行相关业务

    一旦再次取到空数据,就 sleep 几秒再检查

    如果业务量比较小,且 A 服务来数据没有什么规律

    通常连续几个 sleep (可能 3 、5 分钟)之后就把 B 服务结束了

    配合一个 15 分钟甚至更长的 crontab 再来唤醒 B 服务
    smallgoogle
        6
    smallgoogle  
    OP
       Aug 11, 2020
    @cepczkd 觉得你这是个好办法。但是如果我在 B 服务做个频道监听,让 A 推送数据的时候顺带发布一下频道,这样会不会更优?
    fdingiit
        7
    fdingiit  
       Aug 11, 2020
    @smallgoogle 我觉得你应该先考虑为什么选择 redis,以及 redis 的几个常见问题,比如灾备丢数据如何处理
    qiayue
        8
    qiayue  
    PRO
       Aug 11, 2020
    MQ
    soulzz
        9
    soulzz  
       Aug 11, 2020
    kafka 比较适合这个场景
    prenwang
        10
    prenwang  
       Aug 11, 2020   ❤️ 4
    redis 有 pubsub 可以试试.

    楼上不要抬杠, redis 做这类轻量级消息场景非常好用, API 简单, redis 的部署管理也很方便. 性能港港, 优势明显

    不大的项目动不动上卡夫卡等重量级消息队列找虐, 管理维护,api 易用性都不能和 redis 比.

    @smallgoogle 你也可以使用 beanstalkd 这个轻量级的消息队列, 易用性和 redis 差不多. 小型项目的话性能绰绰有余
    kiracyan
        11
    kiracyan  
       Aug 11, 2020
    lpop 加阻塞 然后 A 推送数据的时候打开 长时间没数据就继续阻塞?
    palmers
        12
    palmers  
       Aug 11, 2020
    为啥使用 redis 而不用 mq 呢?
    KallyDev
        13
    KallyDev  
       Aug 11, 2020
    这事应该让消息队列来做,可以试试 RabbitMQ 还是蛮好用的

    Redis 也不是不可以,但不适合去做这些,参考 https://cn.v2ex.com/t/562561
    话说 Redis 的作者也写过一个消息队列插件 https://github.com/antirez/disque-module,不过看样子是已经弃坑了
    wei745359223
        14
    wei745359223  
       Aug 11, 2020
    huntcool001
        15
    huntcool001  
       Aug 11, 2020   ❤️ 1
    如果是 Redis 5.0 版本以上,用 Stream, 里面的 XREAD 命令加上 BLOCK 参数. 这个不会丢失消息,比 pub sub 好.
    Redis 5.0 以下的版本就用 PUB -SUB 好了.

    B 服务的进程不应该终结吧,是不是你代码写法有问题. 一个线程不停等就好了,咋会内存溢出.

    实在有这个问题的话,业务又允许一定延迟,你就分布式 cronJob 一秒执行一次吧
    FaceBug
        16
    FaceBug  
       Aug 11, 2020
    @smallgoogle

    建议先解决内存溢出的问题

    这个和 blpop 还是别的什么 pop 应该没什么关系的

    既然你还要做一下监听,那么就说明 B 业务一直是运行的

    个人觉得和直接监听 list 有没有数据没什么差别

    另外如果你的数据如果是有顺序操作的

    你用监听+取数据的操作就要考虑到并发的问题
    huntcool001
        17
    huntcool001  
       Aug 11, 2020
    当然, RabbitMQ 之类的队列更适合. 专业的东西做专业的事. 除非你们业务真的很小,消息队列都没部署
    xuanbg
        18
    xuanbg  
       Aug 11, 2020
    MQ 是专业干这个的。放着专业的不用,为啥要用半吊子的 redis ?


    @prenwang RabbitMQ 一点都不重,用 docker 安装使用都十分简单,而且几乎不占 cpu 和内存。
    cocowind
        19
    cocowind  
       Aug 11, 2020
    0.0,kafka,rabbitmq,nsq....redis 是最后的选择,自己基于 redis 写一个 MQ..
    Immortal
        21
    Immortal  
       Aug 11, 2020
    我觉得内存溢出问题不是 redis 的队列引起的 再检查下
    blpop 就是这么用的 我不是很支持楼上说的 lpop 然后 sleep
    而且我也建议继续使用 redis 没必要动不动上 mq 服务架构越简单越好 不得不上的时候才会考虑加第三方组件
    berserk
        22
    berserk  
       Aug 11, 2020
    显然这个需求应该用 kafka.
    vissssa
        23
    vissssa  
       Aug 11, 2020
    明显不是 blpop 的问题,都歪楼成啥样了
    以前用 blpop 监听过任务,没出现过问题。
    Pythoner666666
        24
    Pythoner666666  
       Aug 11, 2020
    sleep 的操作建议别用 会阻塞 cpu 。 blpop 本身就是楼主这种用法 另外设置超时时间 没有数据就不会一直阻塞 会进入 sleep 状态 有新数据就会再次唤醒 这样比较合理 但是会有另外一个坑 就是 sleep 时间太久 redis 客户端会断开连接 所以得 catch 异常 然后假重连。
    wysnylc
        25
    wysnylc  
       Aug 11, 2020   ❤️ 1
    redis sub/pub
    jenlors
        26
    jenlors  
       Aug 11, 2020 via Android
    redis5.0 以上支持 stream,当做轻量级队列使用还是不错的。
    bigggge
        27
    bigggge  
       Aug 11, 2020
    借楼问下,Node.js 用 https://github.com/OptimalBits/bull/ 的时候,BRPOPLPUSH 导致写时延一直是 5s,触发监控报警咋办?
    tikazyq
        28
    tikazyq  
       Aug 11, 2020
    上代码
    tikazyq
        29
    tikazyq  
       Aug 11, 2020
    选 redis 没错,这个方案也可行,内存溢出一般是程序本身的问题,检查一下哪里写了 bug 了
    lenqu
        30
    lenqu  
       Aug 11, 2020
    轻量级,redis 我觉得很好用,消息队列并不适合单一的场景业务
    gemini767
        31
    gemini767  
       Aug 11, 2020
    思路有点绕,可以用 redis 的订阅
    也可以当前一个事务处理完直接调用下一个服务
    也可以 eventbus 之类的
    不知道手写 一边写一边读的意义
    lenqu
        32
    lenqu  
       Aug 11, 2020
    还有如果是一个在内网,一个在外网,我觉得消息队列在这种业务下是不合适的,因为队列服务器无法主动连接
    cnoder
        33
    cnoder  
       Aug 11, 2020
    大概率不是 redis 的问题,用法没错
    WayneCmd
        34
    WayneCmd  
       Aug 11, 2020
    lpush 把消息放到队列里,brpop 消费,这里面会有一个 timeout 当 timeout 过了之后,brpop 就结束了会返回 null, 需要进入下一个循环。

    内存溢出应该和这些方法没问题,建议检查一下逻辑代码。
    timidadonis
        35
    timidadonis  
       Aug 11, 2020
    消息队列他不香吗
    byzf
        36
    byzf  
       Aug 11, 2020
    和你需求基本相同, 用 lrange + ltrim, 每次取固定数量, 代码大概五十行吧, 跑了几年至今没遇到过超时和内存溢出.

    仿佛来到了卡巴, 20 块钱配置出的问题, 一堆人让买八路泰坦.
    ToBeHacker
        37
    ToBeHacker  
       Aug 11, 2020
    你这个内存溢出跟 redis 应该没啥关系吧
    dzdh
        38
    dzdh  
       Aug 11, 2020
    @KallyDev 并不是弃坑,而是作为一个 redis 扩展可选安装。不再默认整合在 redis 代码中。
    Leigg
        39
    Leigg  
       Aug 11, 2020 via Android
    出问题先检查自己代码
    robinlovemaggie
        40
    robinlovemaggie  
       Aug 11, 2020
    不太清楚你的 blpop 在做什么逻辑的阻塞,感觉像是出现了死锁
    simonlu9
        41
    simonlu9  
       Aug 11, 2020
    redis stream 你值得拥有
    ichou
        42
    ichou  
       Aug 11, 2020 via iPhone
    blpop/brpop 很可靠的哈,开源社区有不少队列项目都是基于这个实现的,比如 Sidekiq
    检查一下内存溢出的原因吧
    misaka19000
        43
    misaka19000  
       Aug 11, 2020
    @prenwang #10 redis 的 pubsub 太弱了
    MarioLuo
        44
    MarioLuo  
       Aug 12, 2020 via Android
    小项目中常用 redis 这么干,Java 语言用 brpop 没遇到过内存溢出,不过有一点就是全局配置的超时时间必须大于 brpop 阻塞时间,否则会出现消息丢失
    scnace
        45
    scnace  
       Aug 12, 2020 via Android
    Redis 有个 disque module (
    yuzo555
        46
    yuzo555  
       Aug 12, 2020
    Redis 的 Stream
    yc8332
        47
    yc8332  
       Aug 12, 2020
    内存溢出是你自己程序的问题。找找哪里一直申请内存
    atonku
        48
    atonku  
       Aug 12, 2020
    redis 做这个真的不好用
    edk24
        49
    edk24  
       Aug 12, 2020
    没有达不达的到, 我连个上传视频异步转码切片都用上了. 哈哈 除非你想折腾自己

    用适合的东西做适合的事情, 不然脑瓜疼
    raptor
        50
    raptor  
       Aug 12, 2020
    如果是 python 的话,直接用 celery,后端用 redis 即可
    encro
        51
    encro  
       Aug 12, 2020
    非常常规的用法,
    通常可能是取出太多了吧,
    或者采用了异步一堆协程去取阻塞类似?
    hxy91819
        52
    hxy91819  
       Aug 12, 2020
    刚看第一句话,感觉就应该用消息队列
    tairan2006
        53
    tairan2006  
       Aug 12, 2020
    pub/sub or xstream
    someonedeng
        54
    someonedeng  
       Aug 12, 2020
    其实重点是,B 服务会炸掉这个问题
    killerv
        55
    killerv  
       Aug 12, 2020
    很多人上来就是换 MQ,真是服了,内存溢出的原因大概率是楼主程序问题。把消费队列换成 MQ,还是会内存溢出。
    killerv
        56
    killerv  
       Aug 12, 2020
    小服务用 Redis 队列很好用的,我们 MQ 和 Redis 的 list 都有在用,说实话没发现 Redis 有你们说的那么不堪,作为消息队列很稳。不管是服务端还是客户端,Redis 配置比 MQ 简单多了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5955 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 210ms · UTC 02:13 · PVG 10:13 · LAX 19:13 · JFK 22:13
    ♥ Do have faith in what you're doing.