如何保证消息只被消费一次?

2015-12-25 10:59:10 +08:00
 Lullaby

最近用 redis 的 pub/sub 做消息队列,开启多个 MQ 应用进程,由于使用的是发布订阅者模式,多个监听者(消费者)如何保证只有一个监听器接收到消息并消费?

13857 次点击
所在节点    Java
34 条回复
Lullaby
2015-12-25 14:11:35 +08:00
@xufang
贴里说的消息不安全,前排 @evanmeng 提到了: "在生产者和消费者都有可能宕机的现实网络,要保证无数据丢失是做不到的",所以需要用备用手段来保证消息通知到位,比如定时轮询几分钟之前的消息状态,如果消息过时且未被消费,则需要再 consume 一次
不过各系统是否需要这样做都跟自己的业务相关
defage
2015-12-25 14:18:20 +08:00
你这是订阅模式,跟 broadcast 一样, 如果在 rabbitmq 中就是 fanout

要做的比较多的策略, 还是用 rabbitmq 这种消息队列服务把
pokolovsky
2015-12-25 14:41:42 +08:00
量子信息能保证只能消费一次。
ybdhjeak
2015-12-25 14:46:42 +08:00
pub/sub 不合适用作队列,在没有订阅者的频道 pub 时会失败,如果要求强实时的话,加快 RPOP 的频率就行, redis 的操作都是原子的
xujif
2015-12-25 14:51:51 +08:00
这个适合用队列
dingyaguang117
2015-12-25 14:52:33 +08:00
使用姿势不对,应该用 list 的 bpop
Lullaby
2015-12-25 15:05:23 +08:00
@defage
@pokolovsky
@ybdhjeak
我想问一下 如果要求队列保证 FIFO 怎么办 话说 order 对性能损伤很大
haogefeifei
2015-12-25 15:09:05 +08:00
java 用 synchronized 可以搞定
est
2015-12-25 15:52:17 +08:00
@pokolovsky 没法保证的。首先你如何检测量子丢包?
ybdhjeak
2015-12-25 23:58:23 +08:00
@Lullaby rpush lpop 啊
julyclyde
2015-12-26 09:55:22 +08:00
@love 说的那种方法,可以通过简单的把 mq 替换为 beanstalkd 来实现
不过还那句话:考虑到 sub 死的时候都喊不出来,这事不可能完全实现
sbpcx
2015-12-26 10:10:17 +08:00
最近也在撸,用的 list 。 pop 的话可以卡看 rbpop ,但是阻塞需要酌情考虑。
Muninn
2015-12-26 10:34:42 +08:00
不用非得用 redis 啊 那个就只能订阅模式的
用 rabbitmq 之类的专业队列
或者如果是 python 项目 用 celery+redis 就好了
sbpcx
2015-12-26 11:04:20 +08:00
顺便 搭车一问: rbpop 是阻塞的,如果 queue 比较多,也有好多阻塞的,那会不会造成 redis 的链接过大呢?

现在看到如何监听 redis 队列的时候,主要想到了三种想法:
1 、用 rbpop ,阻塞监听,但是会不会碰到链接等待直至过大。
2 、采用 spring data redis 中的 messageListener 方法,大致看了下他的代码,他好像是用的线程池“轮询”的?是吗?
3 、使用一个线程或者线程池在跑监听(类似于循环跑“轮询”),其他的监听队列注册到这个线程或者线程池上面去,当前者发现消息了,就告知后者,类似于 Actor 模式这种的。

求指导。

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

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

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

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

© 2021 V2EX