2

我有一个任务线程在两个单独的 tomcat 实例中运行。任务线程在某些 where 条件下同时读取(使用选择)TASKS 表,然后进行一些处理。

问题是,有时两个线程都会选择相同的任务,因此该任务会执行两次。我的问题是如何让两个线程不从 TASKS 表中读取同一组数据

4

6 回答 6

0

我认为您需要查看一些信息如何与任何企业作业调度程序一起使用,例如使用Quartz

于 2011-11-15T10:30:48.360 回答
0

数据库能否提供优雅的管理很大程度上取决于它是使用严格的两阶段锁定(S2PL)还是多版本并发控制(MVCC)技术来管理并发。在 MVCC 下读取不会阻塞写入,反之亦然,因此很可能通过相对简单的逻辑来管理这一点。在 S2PL 下,您将花费太多时间阻止数据库成为管理此问题的良好机制,因此您可能希望查看外部机制。当然,无论数据库如何,外部机制都可以工作,但MVCC并不是真正需要的。

使用 MVCC 的数据库有 PostgreSQL、Oracle、MS SQL Server(在某些配置中)、InnoDB(SERIALIZABLE 隔离级别除外),可能还有许多其他数据库。(这些是我知道的副手。)

关于您使用的是哪种数据库产品,我没有找到任何线索,但如果是 PostgreSQL,您可能需要考虑使用咨询锁。 http://www.postgresql.org/docs/current/interactive/explicit-locking.html#ADVISORY-LOCKS 我怀疑许多其他产品都有一些类似的机制。

于 2012-04-02T23:06:12.180 回答
0

对于您的用例,有一个更好的工具来完成这项工作——那就是消息传递。您正在持久化需要处理的项目,然后尝试在工作人员之间同步访问。在进行这项工作时,您需要解决许多问题 - 通常更新表并从中选择不应该混合(它锁定),因此在那里存储状态不起作用;您的 Java 代码中的同步也不会,因为服务器重新启动后它不会继续存在。

将 JMS API 与 ActiveMQ 之类的消息代理一起使用,您可以将消息发布到队列。该消息将包含要执行的任务的详细信息。消息代理会将其保存在某个地方(在它自己的消息存储或数据库中)。然后,工作线程将订阅消息代理上的队列,并且每条消息只会被传递给其中一个。这是一个非常强大的模型,因为您可以有数百个消息消费者都在执行任务,因此它可以很好地扩展。您还可以根据需要使其具有弹性,因此任务可以在 Tomcat 和代理重新启动后继续存在。

于 2011-11-15T12:17:42.287 回答
0

这只是因为您的代码(正在访问数据库)DAO 函数没有同步。让它同步,我认为您的问题将得到解决。

于 2011-11-15T10:27:37.880 回答
0

如果TASKS table您提到的是数据库表,那么我将使用事务隔离。

作为建议,在事务中,将 的属性设置TASK table为某个唯一可识别的值(如果未设置)。提交牵引。如果一切正常,则线程已选择任务。

我还没有遇到过这个用例,所以请谨慎对待我的建议。

于 2011-11-15T10:29:04.613 回答
-1

我认为您需要有一些变量(列)来保存行的最后修改日期。您的线程可以读取具有相同修改日期限制的同一组数据。

编辑: 我没有看到 “不读”

在这种情况下,您需要另一个表 TaskExecutor (taskId , executorId) ,并且当某个线程运行任务时,您将数据放入 TaskExecutor;当您启动另一个线程时,它只是检查任务是否已经执行(从 RanTask 中选择 ...,其中 taskId = ...)。您还需要注意事务的隔离级别。

于 2011-11-15T10:31:34.473 回答