繁体   English   中英

使用数据库作为任务队列

[英]use database as a queue of tasks

在我们的一个Java应用程序(基于postgresql db)中,我们有一个数据库表,该表维护着要执行的任务列表。 每行都有一个json blob,用于显示任务的详细信息以及计划的时间值。

我们有一些Java工作程序/线程,其工作是搜索准备好执行的任务(基于其计划值),执行该任务并将其从表中删除。 执行任务可能需要几秒钟。

问题是,一个以上的工人可能会抓住同一行,从而导致重复执行任务,这是我们要避免的事情。

一种方法是,在执行select抓取一行时,使用FOR UPDATE来锁定该行,以防止其他工作程序抓取被锁定的同一行。

我对这种方法的担心是,仅当在db中执行select事务时,行才被锁定(根据this ),而Java代码实际上正在执行所选的行/任务时,锁定已消失,另一位工作者可以再次抓住它。

是否可以确定上述方法是否一定行得通? 谢谢!

将DB调用视为原子指令,并使用更新将布尔值列“进行中”的布尔值从false更改为true,从而在表周围设计无锁算法。 也可能只是一个state int (0 =可用,1 =进行中,N =结果代码)。

确保在状态0上有部分索引(可能从崩溃中恢复以找到正在执行的任务的状态为1),以便...where state=0保持选择性和快速(当然是在计划的时间索引之上) 。

希望这可以帮助。

当一个线程已成功锁定给定连接上的行时,另一线程尝试获得另一连接上的行上的锁应该失败。 如果该行被锁定,则应发出带有某种no-wait子句的select-for-update,以请求立即失败。

现在,这不能解决查询与锁竞争,因为失败的锁可能会中断线程的执行。 您可以通过以下方式解决此问题:

  1. 选择带有新任务的所有记录(无论是否正在处理它们)
  2. 对于[1]中返回的每个新任务,运行匹配的select-for-update,如果锁定失败,则继续处理任务。
  3. 如果任何锁定尝试失败,请跳过该任务而不会使整个过程失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM