我有一个消息记录的SQL表tbl_message_queue
,每个消息记录都有一个发布时间戳字段(现在或将来)。不断插入新记录。
当发布时间戳成熟时,符合条件的记录需要由控制台应用程序.exe处理。完成流程后,相应的记录将从tbl_message_queue
中删除。
发布时间戳之间的延迟时间应该减少/消除执行。
我可以通过Windows Task Scheduler将我的.exe设置为每10-15秒运行一次。其中包括一个SQL语句,如:
SELECT *
FROM tbl_message_queue
WHERE qmsg_ts_release <= GETDATE()
这感觉就像一个效率低下,蛮力,滞后友好的解决方案。但它是我最熟悉的结构。
我从来没有试过这个,但似乎它可以工作。这听起来真的很糟糕,所以请原谅我,如果这是一个非常糟糕的主意。
我可以创建一个CmdExec Job Step的SQL代理作业,并不断重新安排作业:
UPDATE qmsg_ts_release
INSERT tbl_message_queue
在MIN(qmsg_ts_release)
开始下一步。
Phew ...我知道听起来很难看,但它没有积极地进行投票,并且可能会消除任何延迟。
针对此类问题还有其他选择或更好的解决方案吗?我不熟悉消息队列体系结构中的最佳实践。
像MSMQ或SQL Server Service Broker这样的问题会更好吗?我对其他选项知之甚少,不知道从哪里开始。
答案 0 :(得分:1)
你的选项2应该可以工作,但是你可能会遇到意想不到的问题,因为频繁的重新安排很可能不是SQL代理的常用用法而你几乎无法控制它。
根据您的基础设施,您可以自己实施类似的方法。我将概述算法。
首先,假设您的队列中的表已填充,并且不会被外部进程更改。
您的控制台应用程序无法启动和停止,但会始终运行。 它启动后立即运行查询以确定位于队列顶部的消息:
SELECT TOP(1) *
FROM tbl_message_queue
ORDER BY qmsg_ts_release
应用程序检查返回消息的时间戳,以查看它是在过去还是将来。如果它是过去的,应该立即处理,消息是“过期”。如果有过期消息,请对其进行处理,将其从队列中删除,然后重复查询并查找队列中可能过期的下一条消息,依此类推。
处理完所有逾期消息后,循环停止。此时,您将来会有一条消息的时间戳。所以,我们只需要等到将来的那一刻。在这段时间内将线程发送到睡眠状态。一旦唤醒,您就会知道处理消息是正确的时刻。然后重复整个过程。
如果计算机上的时钟稳定且可能的等待时间不是太长,这种方法可以很好地工作。所有时钟和定时器漂移,等待的时间越长,累积误差就越大。
接下来要考虑的是在将新项目添加到队列时要执行的操作。将项添加到队列的过程/过程需要一种方法来通知处理应用程序它可能需要比预期更早地唤醒。但首先,做一个简单的检查。将项添加到队列时,您可以检查队列中是否有任何具有较小时间戳的项。如果已经存在这样的项目,您只需将新项目添加到队列中,处理应用程序就会像往常一样进入它。如果检查显示新项目的时间戳早于队列中已有的所有其他时间戳,则表示处理应用程序正在休眠,我们必须提前将其唤醒。
不幸的是,我不知道从存储过程向外部应用程序发送信号的好方法。我想知道一个人。在您的情况下,只要将此类项添加到队列中,就可以简单地重新启动处理应用程序。当处理应用程序重新启动时,它会重新读取队列并继续相应地等待。
通常,将项添加到队列的进程/应用程序应该能够通知工作者应用程序更改。
我刚发现另一个question,表示您可以使用SqlDependency来接收此类通知。