2012-05-07 53 views
0


MySQL的:分割在不同的节点

我有一个两难之间的特定表格的处理,也许你能帮助我。

我有一个表,其功能是作为一个工作队列。记录被插入并需要处理。记录处理完成后,将从队列中删除。 有几个限制:

  • 只有一个实体可以处理在任何给定时间的记录(以及由“实体”,我的意思是:一个线程,或连接到同一个数据库在单独的计算机)
  • 实体有些动态。它们可能会发生变化(实体数量或特征)
  • 实体处理1个事务中的记录
  • 处理必须并行发生(如果entity1选择batch1,entity2必须能够并行处理batch2,而不必等待使用实体来完成处理)
  • 一旦实体回升记录处理,记录整个“批”这一属于,不得被其他实体来采摘。当我说 “批量”,我的意思是表(逻辑)安排如下:
    • ROW1(BATCH1)
    • 2行(BATCH1)
    • ROW3(batch2)
    • ROW4(batch2)
    • ROW5(batch2)
    • ....等。

因此,可以说使用实体和ENTITY2既要挑从表中处理芯片。 如果使用实体挑选ROW1,然后ENTITY2可以挑选任何其他除外BATCH1(任何其他除外ROW1和2行)。

让抽象的处理部分,因为它并不重要的实际处理是什么。我很想知道如何才能阻止实体之间的冲突,只使用一个mysql数据库,但也保持处理的并行性质。

从我的角度来看,我看到了两个很一般方向:

  1. 使用某种状态字段,这表明一个特定实体已经选择了一个批次,而这一次必须从未来的排除选秀权。这个想法的缺点是,如果挑选批次的实体崩溃,那么恢复其他实体的处理有点困难。
  2. 下使用mysql的锁,其具有的缺点是很难保证的并行处理,而不是连续的。例如我可以做一个select ... for update,用于entity1。但是entity2不能执行相同的select ... for update,因为这会等待第一个实体在获取所需批次之前完成处理。

我想知道:

  • 将导致最小的编码工作的方向
  • 是否有任何其他的方向,我在这里失踪(记住,实体不能保持沟通除非通过数据库)
  • 如果有这种问题的标准模式
  • 如果您可以指向我的文章辩论这类问题。
  • 什么是解决这个问题的最有效的方法。

因此,我在这里的是,数据库必须拆分表不同实体之间进行处理,并想知道做到这一点的最好办法。我几乎认为我是第一个处理这个问题的人,并且想知道你的想法。 另外,请注意,这些记录可分批通过一个非常简单的标准(比如,batchId)

亲切的问候,
安德烈被拆分。

+0

请添加一些格式到您的问题和要求特定的东西,它将很难通过这个长长的描述。 – Rachel

+0

谢谢;格式添加。我同意它有点长,但不能做其他事情。第一部分总结了描述;第二部分增加了一些解释。 – Andrei

回答

1

嗯,从你所描述的,我没有看到如何数据库记录锁定将做你想做的。 DB锁定说“如果此记录不可用,请等待”,而不是“如果此记录不可用,请选择另一个”。

问题:批处理时,它是“完成”?我的意思是,假设节点A开始处理批次1.然后节点B出现,然而你这样做,发现批次1在工作,所以它从批次2开始。然后节点A结束。然后节点C出现。第1批当前未处理。节点C应该获得批1吗?或者是第一批完成,第二批正在工作,所以我们必须继续进行第三批?如果一个批处理完成,那么任何数据库锁定显然都不起作用,因为它不记得过去只有一条记录被访问过,只有现在发生的事情。

也许别人有一个更聪明的解决方案,但我认为你将不得不这样做与状态标志。我会说:

创建一个单独的批处理表,每批一个记录。将外键放在指向批处理表的工作队列表中。这样我们保持数据正常化。

在批处理表中,添加状态标志,其中包含工作中和非工作中的值;或未经处理,在工作和处理。 (取决于批次是否完成一次“完成”。)还创建一个“处理实体”字段,用于标识正在处理此批次的实体,否则为空。 (如果唯一的状态是在工作中并且不在工作中,则该字段可以与在工作标志一样加倍:空=不工作,不空=在工作。)

当实体开始处理批处理,它将处理实体字段设置为实体标识。完成后,它将该字段重置为空。当实体正在寻找要处理的批次时,它会选择“where processing_entity为null”(当然还有其他任何条件)。

然后为了确保一个实体没有崩溃离开该标志集,每当一个实体启动时,它会检查是否有一个表示它正在处理它的批处理记录。如果是这样,它肯定崩溃了,所以它重置标志并做任何清理。

只有当一组实体是固定的,例如,如果一个实体是一个服务器,或者它是一个来自线程池的线程。如果他们能来来去去任意线程这是行不通的,因为你不能在线程中重新启动来告诉它留下未完成的工作指望。

我用另一种方法是把一个时间戳,说当我们开始处理批记录。然后我有另一个过程,每隔一段时间运行一次,检查时间戳,并比较一些合理的最大时间。如果说,我们知道这个过程应该采取几秒钟,我们可以看到一个带有时间戳这是一个小时的时候,那么处理死亡或挂,而我们应该做清理适当。这确实有一个问题,它需要你能够说出最大的时间。

+0

处理完特定记录后,将从队列中删除。另外,实体可能会改变,所以我不能指望它们重新启动并清除处理标志。关于与时间戳的想法 - 我发现了一些问题:如果设置足够短的时间,那么,根据系统负载,它可能是不够的,它可能会与其他实体碰撞。如果你设置了足够长的时间,那么,如果一个实体崩溃了,需要一些时间直到另一个实体拿起它并对它做些什么。这可能是最好的妥协,但:)谢谢! – Andrei

+0

是的,这正是时间戳的问题。 '希望我有更神奇的解决方案。以下是我想到的另一种想法,但我从未尝试过:将实体ID放入记录中。有一个定期唤醒的进程,并可以询问这些实体询问“你在使用X吗?”如果实体回答“是”,那好,它仍然有效。如果它说“不”或者没有回答,那肯定会发生崩溃。这当然假设你可以做某种消息传递。 – Jay

+0

抱歉,他们无法沟通(上面已经提到)。另外,我认为这会带来与那些时间戳相同的问题,为什么不使用它们,因为它们更简单? :) – Andrei

1

我对这个解决方案在过去是更新表中的列“BATCH_ID”与“独特的无”,然后从表中使用独特的批号选择。

你的情况实体1

因此走来: “UPDATE TBL SET BATCH_ID = '123456789' WHERE BATCH_ID = '0' LIMIT 1” 然后 “SELECT * FROM TBL WHERE BATCH_ID = '123456789'”

实体2出现并重复该过程与其独特的编号'15791579'(所以它不能更新批次1),并选择批次2等等。