推荐学习书目
› 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 · 9358 views
    This topic created in 2275 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
    fdingiit
    Aug 11, 2020
    1
    为什么不选择专业的而选择二道贩子
    smallgoogle
    smallgoogle
    OP
    Aug 11, 2020
    2
    @fdingiit 我是不是应该在 A 服务里写一个频道通知? 然后 B 服务监听频道,收到频道通知 再去取 list ?
    WaldenHorizon
    WaldenHorizon
    Aug 11, 2020
    3
    blpop 换成 lpop 然后加一个取到空数据的小延迟
    xkeyideal
    xkeyideal
    Aug 11, 2020
    4
    redis 啥时候可以干数据变化推送的功能了
    FaceBug
    FaceBug
    Aug 11, 2020
    5
    B 服务 lpop,如果有数据就一直取数据,并进行相关业务

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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