最近用 redis 的 pub/sub 做消息队列,开启多个 MQ 应用进程,由于使用的是发布订阅者模式,多个监听者(消费者)如何保证只有一个监听器接收到消息并消费?
最近用 redis 的 pub/sub 做消息队列,开启多个 MQ 应用进程,由于使用的是发布订阅者模式,多个监听者(消费者)如何保证只有一个监听器接收到消息并消费?
|
1
这不就是要做 Exactly Once 吗?虽然有很多绕过去的做法,但直接的回答就是一句:不能。
|
|
2
考虑过走队列吗?哪个消费者拿到了,哪个消费者处理。
|
|
evanmengDec 25, 2015
5
在生产者和消费者都有可能当机的现实网络,要保证无数据丢失的 Exactly Once 是做不到的。
常用的做法无非是:用一个 Zookeeper 之类的分布式锁记录已发送信息, pub 要 sub 发送确认,在多个 sub 一方去重。 @Lullaby |
|
6
@mathiasverraes
There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery https://twitter.com/mathiasverraes/status/632260618599403520 |
|
7
无法保证的,建行当年花那么多钱都无法保证,还是需要去重,别去踩坑了。
|
|
8
为什么不用 redis 的 lpop ?
|
|
11
不要用 pub/sub 用 list 操作
|
|
12
无法保证, CAP Theorem: https://en.wikipedia.org/wiki/CAP_theorem
|
|
13
只能绕过这个问题。
比如以前我们的做法: 队列向一个 consumer 发一个消息后,把这个消息设置为正在处理,并设置一个倒计时,时间到后 consumer 没有回发确认处理完毕的消息的话再放回队列以便给别的 consumer 再处理。 |
|
16
简单一点用数据库, sql 的 acid 特性可以保证。 单点问题可以通过主从来实现。
复杂一些上 zk 或 etcd ,这个前面有人提到了。 |
|
18
一个订阅者即可啊。
|
|
19
还是使用生产者消费者模式吧,否则就算加锁来保证,效率也大大降低了
|
|
20
不开启多个 MQ 应该能解决这个问题吧?如果单个 MQ 没有性能瓶颈的话,就不要开启多个了撒
|
|
21
|
|
22
你这是订阅模式,跟 broadcast 一样, 如果在 rabbitmq 中就是 fanout
要做的比较多的策略, 还是用 rabbitmq 这种消息队列服务把 |
|
23
量子信息能保证只能消费一次。
|
|
24
pub/sub 不合适用作队列,在没有订阅者的频道 pub 时会失败,如果要求强实时的话,加快 RPOP 的频率就行, redis 的操作都是原子的
|
|
25
这个适合用队列
|
|
26
使用姿势不对,应该用 list 的 bpop
|
|
27
|
|
28
java 用 synchronized 可以搞定
|
|
estDec 25, 2015
29
@pokolovsky 没法保证的。首先你如何检测量子丢包?
|
|
31
@love 说的那种方法,可以通过简单的把 mq 替换为 beanstalkd 来实现
不过还那句话:考虑到 sub 死的时候都喊不出来,这事不可能完全实现 |
|
32
最近也在撸,用的 list 。 pop 的话可以卡看 rbpop ,但是阻塞需要酌情考虑。
|
|
33
不用非得用 redis 啊 那个就只能订阅模式的
用 rabbitmq 之类的专业队列 或者如果是 python 项目 用 celery+redis 就好了 |
|
sbpcxDec 26, 2015
34
顺便 搭车一问: rbpop 是阻塞的,如果 queue 比较多,也有好多阻塞的,那会不会造成 redis 的链接过大呢?
现在看到如何监听 redis 队列的时候,主要想到了三种想法: 1 、用 rbpop ,阻塞监听,但是会不会碰到链接等待直至过大。 2 、采用 spring data redis 中的 messageListener 方法,大致看了下他的代码,他好像是用的线程池“轮询”的?是吗? 3 、使用一个线程或者线程池在跑监听(类似于循环跑“轮询”),其他的监听队列注册到这个线程或者线程池上面去,当前者发现消息了,就告知后者,类似于 Actor 模式这种的。 求指导。 |