1

我正在.Net 4.0 中用 C# 编写一个 Windows 服务来实现以下功能:
在每晚的设定时间,应用程序连接到 SQL Server,打开一个用户表,并为每条记录检索用户的 IP 地址,进行 WCF 调用到用户的 PC 以确定它是否可用于交易并将记录插入到状态表中(带有 y/n 和错误,如果有的话)。

处理完所有用户后,该应用程序将读取 State 表中 IsPcAvailable = true 的每条记录,从另一个表中检索该用户的报告列表,并为每个报告从 Enterprise doc 存储库中获取报告,通过调用用户的 PC WCF 并将报告推送到他们的硬盘上,然后将状态表更新为成功。

如果在 1 个应用服务器上运行单线程,则上述场景很容易编写代码;但由于冗余和性能,将至少有 2 个应用服务器同时执行完全相同的事情。

那么如何确保每个用户只在用户表中处理一次,然后是状态表(同样的问题)作为获取报告并将它们推送到全国各地的 PC 是一个漫长的过程。最佳情况下,应用程序应该是多线程的,例如,在 2 台服务器上运行 10 个线程来处理所有用户。

我更喜欢 C# 解决方案,因为我不是数据库专家 :) 我发现最接近我的问题的是:
SQL Server Process Queue Race Condition - 它使用 SQL 代码
和实体框架的多线程问题,我很可能是否必须向下一层并使用 ADO.net?

4

2 回答 2

1

我建议使用http://rusanu.com/2010/03/26/using-tables-as-queues/上的技术,这对你来说是一本很好的读物。

这是fifo的一些sql

create procedure usp_dequeueFifo
as
  set nocount on;
  with cte as (
    select top(1) Payload
      from FifoQueue with (rowlock, readpast)
    order by Id)
  delete from cte
    output deleted.Payload;
go

一个用于堆(顺序无关紧要)

create procedure usp_dequeueHeap 
as
  set nocount on;
  delete top(1) from HeapQueue with (rowlock, readpast)
      output deleted.payload;      
go

这读起来很漂亮,几乎是诗

于 2012-06-07T22:22:18.320 回答
1

您可以简单地让每个应用程序服务器轮询一个公用表 (work_queue)。您可以使用公用表表达式来读取/更新行,这样您就不会让它们互相踩踏。

;WITH t AS
(
    SELECT TOP 1 * 
    FROM work_queue WHERE NextRun <= GETDATE()
    AND IsPcAvailable = 1
)
UPDATE    t  WITH (ROWLOCK, READPAST)
SET
     IsProcessing = 1,
     MachineProcessing = 'TheServer'
OUTPUT INSERTED.*

现在,您可以在应用程序中使用生产者线程定期检查未处理的记录。一旦该线程完成它的工作,它会将项目推入 aConcurrentQueue并且消费者线程可以处理可用的工作。您可以自己将消费者线程的数量设置为最佳水平。一旦消费者线程完成,它就简单地设置IsProcessing = 0为显示 PC 已更新。

于 2012-06-07T22:26:36.170 回答