延迟队列

https://blueprints.launchpad.net/zaqar/+spec/delayed-queues

延迟队列可以推迟队列中新消息的传递,延迟特定的秒数。这对于审计观察者进程很有用,审计员可以保证在消息被声明之前看到消息,甚至可以在需要时编辑消息。

问题描述

现在 Zaqar 的一个主要功能缺失就是延迟队列。目前,发布到队列的所有消息都会立即可见。这对于大多数用例来说已经足够了。但是,对于某些用例,用户希望消息在一段时间内对最终用户不可用。

提议的变更

通常,队列会有一个新的属性,名为 _default_message_delay。如果该属性值大于 0,则队列是延迟队列,否则,它是一个普通队列。

发送到延迟队列的所有消息都不能立即声明,必须等待 delaydelay 可以在队列创建时设置或更新为元数据。

然后,当用户获取或声明延迟队列上的消息时,Zaqar 会将 delay 作为查询条件,如下所示

消息创建 + 延迟 < 当前时间

基本上,有 3 种场景

  1. 普通消息发送到延迟队列

    如果将没有 delay 属性的普通消息发送到延迟队列,则该消息将使用队列的默认延迟 _default_message_delay

  2. 带有属性 delay 的消息发送到延迟队列

    如果将带有 delay 属性的消息发送到延迟队列,则 Zaqar 将使用消息的延迟秒数,而不是延迟队列的延迟秒数。

  3. 消息发送到普通队列

    普通队列是 _default_message_delay 值为 0 的队列。无论消息是普通消息还是带有 delay 属性的消息,当它发送到普通队列时,都不会有延迟功能。Zaqar 在获取/声明消息时不会对 delay 属性执行条件过滤。这意味着延迟功能不会影响普通队列的性能。

具体的实现步骤

  1. 为所有队列的元数据添加一个新的属性 _default_message_delay

该属性 _default_message_delay 的默认值为 0,表示它是一个普通队列。它的范围是从 0 到 max_message_delay 秒,max_message_delay 是可配置的,默认值为 900 秒(15 分钟)。

  1. 为消息的请求体添加一个新的属性:delay

当将消息发布到队列时,用户可以添加 delay,类似于 ttl。消息的延迟时间比队列优先级更高。如果消息 ttl < delay,则消息将永远不会被声明,因为它处于延迟期间,并且消息的 ttl 已过期,因此消息将被后端删除。

  1. 在消息后端添加一个新的字段 d

该字段 d 是一个延迟过期时间戳。它可以保存到后端存储中。当时间戳小于或等于当前时间时,延迟过期。

d = delay + MESSAGE_CREATED_TIMESTAMP

  1. 确保在延迟过期之前,消息无法被声明。

  2. 如果队列是普通队列,这意味着没有使用“延迟队列”功能,则有必要确保其开销接近于零。

  3. 支持 mongo、redis 和 swift。

缺点

这可能会引入一些性能影响,因为这需要当前消息查询的另一个新条件。但它不会对普通队列产生太大的影响。

备选方案

对于此功能没有好的选择。用户必须等待足够的时间才能从 Zaqar 获取/声明消息。

实现

负责人

主要负责人

cdyangzhenyu <cdyangzhenyu@gmail.com>

里程碑

完成目标里程碑

Queens Q-2

工作项

  1. 添加 mongodb 支持。

  2. 添加 redis 支持。

  3. 添加 swift 支持。

  4. 添加此功能的发布说明。

  5. 更新 API 参考。

  6. 添加此功能的开发者文档。

  7. 相应地更改单元测试、功能测试和 tempest 测试。

依赖项