0

我有很多需要频繁重复处理的数据/作业(数万)。要处理的作业存储在 SQL Server 2012 (Web Ed) 数据库中,该数据库会频繁更新新作业和/或可能会从中删除作业。

样本:

Id     |  WorkItem
1      |  Copy X to Y
2      |  Ping stackoverflow.com
3      |  Verify backupset
4      |  Send an email

我的目标是将作业处理分布在多个节点上,既是出于性能原因,也是为了确保即使节点出现故障也能处理作业。

两个考虑:

  • 我需要确保所有作业最终都由某个节点执行,并且随着作业被添加到数据库驱动的队列中,这种情况会不断发生。
  • 我希望所有节点都进行一些工作,并防止单个节点获取大部分工作,因此实施某种循环似乎是有意义的。

因为整个系统需要抵抗节点故障,所以我不能真正将工作“分配”给节点,因为我不知道怎么了正常的,什么不是。我最初的想法是让每个节点从数据库中“获取”一个或多个作业,处理它们,然后将数据返回到 SQL 数据库。但是,接下来会出现一些问题:

  • 节点需要知道其他节点已经在处理什么,因此作业不会被错误地处理两次。这意味着需要将作业标记为正在处理。
  • 其中许多作业非常小,但需要非常频繁地执行(可能每 10-30 秒一次)。不断更新谁在处理作业然后释放作业,然后再次处理似乎是主要的数据库开销。
  • 如果一个节点在处理过程中死亡会发生什么?有没有办法从中恢复?

解决这个问题最有效的方法是什么?谢谢!

4

2 回答 2

1

您可能需要尝试 SQL Server 的最佳配置(不是专家)......但基本方案如下:

  • 有 5 个列来管理作业处理
    一个称为 DONEUNTIL 的列,它在您的处理节点死亡时充当故障保护……它基本上是一个“估计的处理完成时间点”……
    第二个称为 NODEID,其中包含 NODE 处理的 ID那份工作。
    第三个称为 DONE,一旦作业完成,就会设置为 1。
    第四个称为 CREATED,其中包含将作业放入表中时的时间戳。
    第五个称为JOBID,它是主键。

  • 通过将 DONEUNTIL 和 NODEID 设置为 NULL,让每个节点经常清理 DONEUNTIL 已通过且 DONE != 1 的所有作业

  • 当一个节点准备好接受下一个作业时,它只选择最旧的 CREATED 在 NODEID 和 DONE 中具有 NULL 的 JOBID != 1
    然后在开始处理之前适当地更新 DONEUNTIL 和 NODEID。
    完成处理后,它会更新 DONE = 1。

您可以使用上述的变体——比如拥有工作优先级、重试计数器等,或者将“工作管理信息”放入单独的表格等。

这个方案工作得很好......如果你有很多工作,将 DONE=1 的工作移动到存档表中可能是有意义的......这样你的工作表只包含活动工作(等待处理或正在处理) 这应该保持它顺利运行......

于 2012-12-16T21:45:50.453 回答
0

你肯定需要使用队列机制——Sql Server 有一个内置的队列机制,称为 Sql Service Broker。

于 2012-12-16T22:15:24.470 回答