【问题标题】:How should two clients simultaneously wait for a value to be present in Redis?两个客户端应该如何同时等待一个值出现在 Redis 中?
【发布时间】:2016-04-16 17:57:31
【问题描述】:

Redis 提供 BRPOP,允许发送方/接收方模型保证交付。

发件人: LPUSH foo_key bar_value
收件人: BRPOP foo_key ### => 'bar_value'

其中 ### 是任意过期间隔,例如 15 秒。

但是,如果消息有两个接收者,您应该怎么做?我考虑过以下选项:

  1. PUBLISH/SUBSCRIBE,但是如果发送者 PUBLISHes 在接收者 SUBSCRIBE 之前发送消息,这会导致竞争条件转到频道。
  2. 发送者在一个键上调用SET+EXPIRE,接收者轮询这个键直到一个值出现,然后GET得到这个值。数据最终会根据 EXPIRE 超时被删除。我不喜欢这个选项,因为如果多个客户端同时轮询 Redis 可能会导致性能不佳,而且响应不是实时的。

您如何设置具有实时、保证交付的多客户端接收器模型?

只有一条消息会通过我的架构中的特定键发送,因此客户端不会有意外收到两次相同消息的危险。

【问题讨论】:

    标签: redis publish-subscribe


    【解决方案1】:

    发送者可以将值推送到 2 个队列中,每个接收者一个队列。

    每个接收者都可以在配置文件中拥有其队列的名称。接收方可以使用阻塞弹出,因此不涉及轮询。

    当然,使用这种方法,如果您的一个接收器停止处理,很容易检测到。

    【讨论】:

    • 您可能会感兴趣,Redis 的作者创建了一个新项目以进一步探索“Redis 作为作业队列”用例:github.com/antirez/disque
    【解决方案2】:

    我意识到我可以使用 BRPOPLPUSH 来实现这一点。

    发件人: LPUSH foo_key bar_value 后跟 EXPIRE foo_key ###
    收件人: BRPOPLPUSH foo_key foo_key ### => bar_value

    和以前一样,每个 ### 都是任意的过期间隔,比如 15 秒。

    【讨论】:

    • 我认为您错过了接收者推送到的列表的名称,我假设您的意思是相同的 foo_key。如果是这种情况,如果您的接收者在超时之前完成工作并返回到BRPOPLPUSHing,他们最终可能会多次处理该值。
    • 谢谢,我编辑了这篇文章。应该是BRPOPLPUSH foo_key foo_key ###
    • 我的观点仍然存在。为不同的侦听器使用不同的队列,根据需要推送到所有/某些/一个。
    • 如果多条消息将通过同一个密钥发送,那将是一个问题。在我的例子中,每条消息都有一个唯一的键:接收者得到一个 UUID,一旦它接收到数据,它就会关闭它的连接。我将在 OP 中更好地解释这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多