跨多个线程处理数据库队列 - 设计建议

Sql*_*yan 3 sql-server queue multithreading

我有一个SQL Server表,其中包含我的程序需要"跟进"的订单(调用web服务以查看是否已完成某些操作).我的应用程序是多线程的,可以在多个服务器上运行实例.目前,每隔一段时间(在线程计时器上),该过程ORDER BY NEWID()从"未确认"订单列表中随机选择100行并检查它们,标记任何成功返回的行.

问题是线程之间以及不同进程之间存在很多重叠,并且它们无法保证很快就会检查新订单.此外,一些订单永远不会被"确认"并且已经死亡,这意味着它们会妨碍需要确认的订单,如果我一遍又一遍地选择它们,会减慢流程.

我更喜欢的是系统地检查所有未完成的订单.我可以想到两个简单的方法:

  1. 应用程序一次提取一个订单进行检查,将其检查的最后一个订单作为参数传递,然后SQL Server回退下一个未经确认的订单.更多数据库调用,但这确保在合理的时间范围内检查每个订单.但是,不同的服务器可能会不必要地连续重新检查相同的顺序.
  2. SQL Server跟踪它要求进程检查的最后一个顺序,可能在一个表中,并为每个请求提供一个唯一的顺序,递增其计数器.这涉及将最后一个订单存储在SQL中,我想避免,但它也确保线程不会不必要地同时检查相同的订单

我还缺少其他任何想法吗?这甚至有意义吗?如果我需要澄清,请告诉我.


结果:

我最终做的是在我的表中添加一个LastCheckedForConfirmation列,其中包含已完成的订单,我添加了一个存储过程,使用GETDATE()更新单个未确认的行并踢出订单号,以便我的进程可以检查它.它尽可能多地旋转(假设进程愿意运行的线程数),并使用存储过程为每个线程获取新的OrderNumber.

要处理"不要尝试行太多次或太旧时"的问题,我这样做了:如果"自上次尝试以来的时间">"创建和上次尝试之间的时间",SP将只返回一行,因此,每次再次尝试之前需要两倍的时间 - 首先等待5秒,然后是10秒,然后是20,40,80,120,然后在尝试15次(6小时)后,它会放弃该命令SP永远不会再回来了.

感谢大家的帮助 - 我知道我这样做的方式并不理想,我很欣赏你指点正确的方向.

Rem*_*anu 7

我建议读取并内化使用表作为队列.

如果将数据用作队列,则必须正确组织数据以进行排队操作.我链接的文章详细介绍了如何执行此操作,您拥有的是Pending Queue的变体.

你必须绝对摆脱的一件事是随机性.如果在查询中有一件事难以重现,那就是随机性.ORDER BY NEWID()扫描每一行,生成一个guid,然后排序,然后返回前100名.在任何情况下,您不能每次都有每个工作线程扫描整个表,随着未处理条目数量的增加,您将终止服务器.

而是使用待处理的日期.通过处理日期列(当项目需要重试时)组织(聚集)队列,并使用我在链接文章中显示的技术出列队列.如果要重试,则出列应该推迟项目而不是删除它,即.WITH (...) UPDATE SET due_date = dateadd(day, 1, getutcdate()) ...