Redis:具有多个键的事务

Redis: Transaction with multiple keys

我正在使用 Spring Data Redis。 Redis 中的基本数据模型是

job:包含作业数据的哈希。

queue:包含用作队列的作业 ID 的列表。

新作业将保存在 job 哈希中,并将推送到 queue。我们有多个工作客户端汇集 queue 以通过弹出 id 并从哈希中读取详细信息来使用新的作业 id。

现在我正在尝试根据工作数据中的某些标志制定一项新功能,即某些工作人员只能使用某些工作。问题是 worker 只有在阅读了它的详细信息后才能知道它是否可以使用该作业,而不是在从队列中获取 id 时才知道。

我本来以为可以把这一系列操作放到一个事务中,

  1. 查看队列。
  2. 从哈希中读取作业详细信息并检查是否可用。
  3. 如果是,从队列中取出它的id,否则什么也不做。

但是这种交易涉及队列和散列数据。阅读 Redis 的事务支持后,我不确定这是否可以实现。请帮忙指教我应该采取什么方法。

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

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

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

如果您想避免 polling/peeking/race-conditions 您可以考虑以下方法:

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

  2. 创建多个 worker,每个 worker 从其自己的 worker 类型队列中阻塞弹出

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

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