2015-10-31 34 views
1

在我们公司,我们有一个分布在少数实例中的服务器。服务器处理用户请求。可以并行处理来自不同用户的请求。应该强烈地按顺序执行来自同一用户的请求。但由于平衡,他们可以到达不同的实例。目前我们使用基于Redis的分布式锁,但这很容易出错,需要更多的关于并发性的工作,而不是业务逻辑。大量的单线程任务队列

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

  • 为每个用户
  • 队列用户ID命名的鲜明队列
  • 通过请求ID标识的每个请求
  • 想象一下,来自同一用户的两个请求同时到达两个不同的实例:

    1. 每个实例将其请求标识放入此用户队列中。
    2. 另外,它们都在本地存储它们的请求ID。
    3. 那么一些券商采取从“some_user_queue”顶部请求ID,并将其移动到“some_user_queue_processing”
    4. 两个实例监听“some_user_queue_processing”。他们偷看它,看看这是否是他们本地存储的请求ID。如果是,那么请处理。如果不是,那么忽略并等待。
    5. 工作完成后,服务器将此ID从“some_user_queue_processing”中删除。
    6. 然后再次执行步骤3。

而这一切对于很多同时发生(几千条)不同的用户(以及他们的队列)的。

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

  1. 我们需要的解决方案需要的微小变化可能使从锁的快速转换。阿卡会迫使我们从头开始重写几乎所有的东西。
  2. 我们需要生产准备解决方案。类星体听起来不错,但尚未准备好生产(更准确地说,它们的Galaxy系列)。
  3. 我工作的顶部非常保守,他们根本不想要我们需要支持的另一个依赖。但是我们已经使用Redis(用于分布式锁),所以我想也许它可以帮助解决这个问题。

感谢

+0

也许您可以评估Hazelcas对分布式锁的支持,请参阅http://hazelcast.org/#lock。 –

+0

假设粘性会话,它的简单写一个[dispatch queue](http://stackoverflow.com/questions/29889885/java-divide-incoming-work-uniformly-via-hashing-in-multithreaded-evnironments/29893297#29893297 )在Java 8中。 –

+0

你能告诉我,如果我的答案是你实际需要的吗? –

回答

0

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

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

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

集群实现的设计使这种匹配成为可能。它基于散布在所有实例上的一系列散列槽。

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

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

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

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