1

I'm using Spring Data Redis. In Redis the basic data models are

job: Hash that contains a job's data.

queue: List that contains job ids serving as a queue.

New job will be saved in job hash and it will be pushed to queue. We have multiple worker clients pooling the queue to consume new job id by popping the id and read details from hash.

Now I'm trying to work out a new feature that certain worker can only consume certain jobs, based on some flags within job data. The problem is worker will only know if it can consume the job after reading its details, but not at the moment of taking the id from the queue.

I originally thought I can put this sequence of operations into a transaction,

  1. Peek the queue.
  2. Read job details from hash and check if consumable.
  3. If yes, take its id from queue, otherwise do nothing.

However this kind of transaction involves both queue and hash data. After reading Redis's transaction support I'm not sure if this is achievable. Please help to advise what approach should I take.

4

2 回答 2

1

如果您想避免轮询/窥视/竞争条件,您可以考虑以下事项:

  1. 将您现有的队列维护为通用输入队列,并拥有一个轻量级分类类型的工作程序(一个可能就足够了,但您可以有更多的冗余)从此队列中弹出项目,使用阻塞弹出来避免轮询,并基于您的作业分配逻辑将新项目推送到每个工作类型的单独队列中

  2. 创建多个工作人员,每个工作人员从自己的工作人员类型队列中进行阻塞弹出

将队列分成多个队列的一个优点是您可以在监控中获得更多可见性,因为您可以检查每个队列的长度并查看哪些类型的工作人员运行缓慢

它可能不适合生产使用,但您可能对Disque感兴趣,这是一个内存分布式作业队列,由与 Redis 同一作者创建(并基于 Redis 代码)。

于 2016-04-15T14:50:20.987 回答
1

Redis 事务与关系数据库事务略有不同,因为它们被更好地描述为条件批处理。事务是发出命令时的一堆QUEUED命令。一旦你EXEC使用事务,命令就会被执行,命令响应会在命令的响应中返回EXEC

从我的角度来看,(还)不需要交易。定期查看队列是幂等的,因此如果多次发生则不会中断。阅读工作细节也是如此。您应该期望在尝试读取时作业详细信息会消失,因为另一个节点可能更快并且已经处理了该作业。这是一个典型的竞争条件,早期识别这些是有益的。

现在是关键部分:从队列中取出作业通常是BLPOP/BRPOP以保证原子性。你没有说明工作完成后工作细节会发生什么。我假设删除哈希。因此BLPOP,队列和DEL作业哈希将成为将它们放入事务的候选者,但这取决于您的用例和条件。特别是至少一次和最多一次的行为。

于 2016-04-15T06:05:17.497 回答