【问题标题】:Large number of single threaded task queues大量单线程任务队列
【发布时间】:2015-11-02 00:00:18
【问题描述】:

在我们公司,我们有一个分布在几个实例中的服务器。服务器处理用户请求。来自不同用户的请求可以并行处理。来自同一用户的请求应按顺序执行。但是由于平衡,它们可以到达不同的实例。目前我们使用基于 Redis 的分布式锁,但这很容易出错,并且需要围绕并发进行比业务逻辑更多的工作。

我想要的是这样的(更像是一个概念):

  • 每个用户都有不同的队列
  • 队列以用户 ID 命名
  • 每个请求都由请求 ID 标识
  • 假设来自同一用户的两个请求同时到达两个不同的实例:

    1. 每个实例都将其请求 ID 放入此用户队列。
    2. 此外,它们都将请求 ID 存储在本地。
    3. 然后某个代理从“some_user_queue”顶部获取请求 ID 并将其移动到“some_user_queue_processing”中
    4. 两个实例都侦听“some_user_queue_processing”。他们偷看它,看看这是否是他们在本地存储的请求 ID。如果是,则进行处理。如果没有,则忽略并等待。
    5. 工作完成后,服务器会从“some_user_queue_processing”中删除此 ID。
    6. 然后再次执行第 3 步。

所有这一切同时发生在许多(数千个)不同用户(及其队列)中。

现在,我知道这听起来很像演员,但是:

  1. 我们需要的解决方案需要尽可能小的更改才能从锁定中快速过渡。 Akka 将迫使我们从头开始重写几乎所有内容。
  2. 我们需要生产就绪的解决方案。 Quasar 听起来不错,但尚未准备好生产(更准确地说,是他们的 Galaxy 集群)。
  3. 我工作的上层非常保守,他们根本不想要我们需要支持的另一个依赖项。但是我们已经在使用 Redis(用于分布式锁),所以我想也许它也可以帮助解决这个问题。

谢谢

【问题讨论】:

  • 也许你可以评估一下 Hazelcas 对分布式锁的支持,见hazelcast.org/#lock
  • 假设有粘性会话,在 Java 8 中编写 dispatch queue 很简单。
  • 你能告诉我我的答案是不是你真正需要的吗?

标签: java concurrency redis distributed task-queue


【解决方案1】:

与您的问题描述相符的最佳解决方案是Redis Cluster

基本上,集群通过以下方式解决您的并发问题:

来自同一用户的两个(或更多)请求将总是转到同一个实例,假设您使用 user-id 作为键和请求作为值。该值实际上必须是请求的list。当您收到一个时,您会将其附加到该列表中。换句话说,这就是您的请求队列(每个用户一个)。

通过集群实现的设计可以实现这种匹配。它基于分布在所有实例上的一系列哈希槽。

当一个 set 命令被执行时,集群会执行一个散列操作,这会产生一个值(我们将要写入的散列槽),它位于一个特定的实例上.集群找到包含正确范围的实例,然后执行写入过程。

此外,当执行 get 时,集群执行相同的过程:它找到包含键的实例,然后获取值。

从锁的转换非常容易执行,因为您只需要准备好实例(将启用集群的指令设置为“是”),然后从 redis-trib.rb 脚本运行集群创建命令.

去年夏天,我在生产环境中使用集群,它的表现非常好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 2014-05-06
    • 2017-04-02
    相关资源
    最近更新 更多