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

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

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

14132 次点击
所在节点    Java
34 条回复
evanmeng
2015-12-25 11:08:58 +08:00
这不就是要做 Exactly Once 吗?虽然有很多绕过去的做法,但直接的回答就是一句:不能。
surfire91
2015-12-25 11:11:13 +08:00
考虑过走队列吗?哪个消费者拿到了,哪个消费者处理。
Lullaby
2015-12-25 11:13:21 +08:00
@evanmeng 意思是只能 producers / consumers ?
Lullaby
2015-12-25 11:15:04 +08:00
@surfire91 就是走队列,只是借用了 redis 的 pub / sub ,生产消费者模式能保证只有一个消费者拿到并消费
evanmeng
2015-12-25 11:19:10 +08:00
在生产者和消费者都有可能当机的现实网络,要保证无数据丢失的 Exactly Once 是做不到的。
常用的做法无非是:用一个 Zookeeper 之类的分布式锁记录已发送信息, pub 要 sub 发送确认,在多个 sub 一方去重。
@Lullaby
est
2015-12-25 11:21:21 +08:00
@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
odirus
2015-12-25 11:21:57 +08:00
无法保证的,建行当年花那么多钱都无法保证,还是需要去重,别去踩坑了。
yangmls
2015-12-25 11:25:30 +08:00
为什么不用 redis 的 lpop ?
Lullaby
2015-12-25 11:47:55 +08:00
@evanmeng pub 要 sub 发送确认是什么意思?
Lullaby
2015-12-25 11:48:43 +08:00
@yangmls 看到支持 pub/sub 就直接扯来用了
moe3000
2015-12-25 11:57:45 +08:00
不要用 pub/sub 用 list 操作
xiamx
2015-12-25 12:02:06 +08:00
无法保证, CAP Theorem: https://en.wikipedia.org/wiki/CAP_theorem
love
2015-12-25 12:02:16 +08:00
只能绕过这个问题。

比如以前我们的做法:
队列向一个 consumer 发一个消息后,把这个消息设置为正在处理,并设置一个倒计时,时间到后 consumer 没有回发确认处理完毕的消息的话再放回队列以便给别的 consumer 再处理。
xiamx
2015-12-25 12:06:17 +08:00
嗯 @love 说的是一个比较常见的折中方案了
surfire91
2015-12-25 12:12:37 +08:00
@Lullaby 我懂了,你是用 pub/sub 来实现消息队列。 pub/sub 就没法保证只消费一次,还不如用 LIST 。
xufang
2015-12-25 12:22:50 +08:00
简单一点用数据库, sql 的 acid 特性可以保证。 单点问题可以通过主从来实现。

复杂一些上 zk 或 etcd ,这个前面有人提到了。
xufang
2015-12-25 12:48:27 +08:00
见我 /t/233785 的回复,和这贴可以互相验证。
zacard
2015-12-25 12:59:20 +08:00
一个订阅者即可啊。
SparkMan
2015-12-25 12:59:57 +08:00
还是使用生产者消费者模式吧,否则就算加锁来保证,效率也大大降低了
eimsteim
2015-12-25 14:00:59 +08:00
不开启多个 MQ 应该能解决这个问题吧?如果单个 MQ 没有性能瓶颈的话,就不要开启多个了撒

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

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

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

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

© 2021 V2EX