0

我有一个 java 应用程序,其中 15 个线程通过名为 getNext() 的同步方法从包含 11,000 条记录的表中选择一行,线程在选择一行时变得很慢,从而花费了大量时间。每个线程都遵循以下过程:

  1. 线程检查是否存在恢复列值设置为 1 的行。

    A. 如果存在,则线程获取该行的 id 并使用该 id 选择 id 大于获取 id 的另一行。

    B. 否则选择 id 大于 0 的行。

  2. 根据上述 1 中描述的步骤的结果收到的最后一行被标记为恢复列设置为 1。

  3. 线程获取行数据并对其进行处理。

问题:

  1. 多线程如何访问同一个表选择另一个线程没有选择的行并且快速?
  2. 如果任何线程选择的最后一行发生崩溃,如何使线程恢复?
4

3 回答 3

1

好吧,会在这里想到不同的问题:

  1. 您是否在数据库中保持状态?我会寻找一些方法,在其中调用选择进行更新,您可以在其中按非活动状态进行过滤(确保只在选择中获取一行)并立即更新为活动(在同一事务中)。很高兴知道您正在使用什么数据库,不确定“选择更新”是否始终是一个选项。

  2. 处理并完成后,更新为已完成状态。

  3. 请务必在表中保留时间戳,以识别您上次更改状态的时间。制定规则来决定何时将活动线程视为丢失。

  4. 定义其他可能的错误场景(如果过程失败会发生什么)。

您还需要分析场景。你的表有多少行?有多少线程同时调用它?在给定时间内发生了多少次插入?根据这一点,您将不得不查看数据库性能的运行情况。

我假设你的 getNext() 是同步的,我在第 1 点写的内容你可能会解决这个问题......

于 2013-07-05T12:30:41.907 回答
1

1.:getNext() 中的多个数据库操作似乎是瓶颈。如果数据没有被外部源更改,您可以读取所有行的“id”和“resume”并将其缓存。比您只有一个查询,而不是仅在内存中进行读取操作。这将保护 getNext() 中大量昂贵的数据库调用:

2.:基本上你需要某种事务,或者至少添加一个在线程完成处理该行时更新的其他列。基本上,处理和更新需要在单个事务中进行。当事务未完成时发生某些事情时,您可以回滚到未处理该行的状态。

于 2013-07-05T12:19:30.420 回答
1

如果线程都在同一台机器上,他们可以使用共享数据结构来避免处理同一件事而不是同步。但以下假设线程在不同的机器上(可能是应用服务器集群的不同成员),并且只能通过数据库进行通信。

删除 getNext() 方法上的同步。将恢复标志设置为 1(步骤 2)时,请以原子方式进行。update table set resume=1 where resume = 0, commit. 只有一个线程会成功,即获得该工作单元的线程。同时,设置恢复时间——如果恢复时间大于某个最大值,则假设处理该工作单元哈希的线程崩溃,将恢复标志设置回 0。工作完成后,将恢复时间设置为空,或以其他方式将工作标记为已完成。

于 2013-07-05T12:23:38.277 回答