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

2020-08-11 10:32:46 +08:00
 smallgoogle
鄙人有个需求就是,A 服务把数据推到 redis,B 服务一直监听 redis list,如果有数据就弹出。
我在 B 服务里用的是 blpop,可这个命令是阻塞的。意思是如果 redis 的 list 一直没有数据 这个位置就一直阻塞,直到监听到一个数据 然后弹出。。。
那么问题就来了,先不说程序效率不效率的,或者是超时不超时的。因为目前我发现我还没等到超时呢,内存就溢出了。。或者说这个阻塞导致了系统自动结果了 B 服务的进程。因为我报错如下:
```
OSError: [Errno 12] Cannot allocate memory
```

那么问题来了,我如何可以优雅的监听 list 是否有新数据呢?
7583 次点击
所在节点    Python
56 条回复
fdingiit
2020-08-11 10:35:38 +08:00
为什么不选择专业的而选择二道贩子
smallgoogle
2020-08-11 10:46:32 +08:00
@fdingiit 我是不是应该在 A 服务里写一个频道通知? 然后 B 服务监听频道,收到频道通知 再去取 list ?
wangritian
2020-08-11 10:46:56 +08:00
blpop 换成 lpop 然后加一个取到空数据的小延迟
xkeyideal
2020-08-11 10:48:26 +08:00
redis 啥时候可以干数据变化推送的功能了
FaceBug
2020-08-11 10:51:21 +08:00
B 服务 lpop,如果有数据就一直取数据,并进行相关业务

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

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

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

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

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

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

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

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

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

实在有这个问题的话,业务又允许一定延迟,你就分布式 cronJob 一秒执行一次吧
FaceBug
2020-08-11 11:04:09 +08:00
@smallgoogle

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

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

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

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

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

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


@prenwang RabbitMQ 一点都不重,用 docker 安装使用都十分简单,而且几乎不占 cpu 和内存。
sss495088732
2020-08-11 11:07:48 +08:00
0.0,kafka,rabbitmq,nsq....redis 是最后的选择,自己基于 redis 写一个 MQ..
kingwrcy
2020-08-11 11:10:01 +08:00
内存溢出跟这个 redis 的阻塞 有毛关系?
blpop 也可以设置 timeout,timeout 到了继续监听就可以啊.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/697283

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX