做DB查询Verus存储集合中的项目?

cho*_*bo2 7 c# performance shared-hosting scheduling quartz.net

我正在尝试制作一个提醒系统,我正在使用石英作为我的日程安排.然而,我提出了几种可能的方法,如何做我需要做的事情,但我不知道最好的方法是什么以及如何测试它.

基本上我有一个提醒系统,用户可以设置提醒.它就像谷歌日历.您可以设置活动的日期和时间,然后通过说"提前15分钟提醒我"来设置提醒

所以你可以在2011年5月10日上午9:59举办活动,你可以说"提前15分钟"

那将是5月10日上午10:44.

我将在托管环境中.(我的网站和日程安排将在相同的环境中运行,甚至在相同的解决方案中.所以它不能减慢浏览我网站的用户的速度.)

我也使用nhibernate和流畅的nhibernate来进行db查询.我在我的网站上使用asp.net mvc 3.

选项1.

每分钟进行一次数据库查询,并获取应该在该分钟发送的所有提醒.这当然意味着每分钟进行一次数据库查询,对于共享环境而言可能过于密集.

选项2.

每5分钟进行一次数据库查询,并获取应该在该5分钟块中发送的所有提醒,并将它们存储在一个集合中(如此内存),然后检查每一分钟需要发送的内容.

这当然会减少查询的数量,但不确定这是否会占用大量内存.

选项3

与选项2相同,但每15分钟发送一次查询并存储在集合中.

这当然意味着很少的数据库查询,但更多的存储在内存中.

选项4

每15分钟进行一次数据库查询,并获取该块中的所有提醒并立即将其解除.

这意味着它们不会在内存中存储很长时间并减少查询量.但是,根据用户设置被提醒的时间,电子邮件可能会更早到达,然后他们设置.

例如他们说在上午10:44提醒我.我的调度程序将在上午10:00开始,它将从上午10:00到上午10:15,然后上午10:15到上午10:30,然后是上午10:30到上午10:45.

因此,电子邮件实际上会提前14分钟到达.

Hog*_*gan 1

这是我解决这个问题的方法。

  • 在数据库层,我将创建一个简单的队列。该消息列表还包括发送时间。当查询该列表时,下一个项目将位于顶部。

  • 消息代理将查询该列表并对最上面的项目进行操作或者休眠直到列表上的最上面的项目到期。

此技术的优点之一是,您无需代理代理在检查队列时应用业务规则。如果您希望它每分钟唤醒一次(例如检查是否有需要发送的新消息),那么您只需确保该队列每分钟始终有一个事件(该事件可能具有不发送的类型)消息,“唤醒”消息没有目标)。代理将醒来并执行检查。然后,如果您想应用更复杂的调度规则,它们很容易。您不必重新编码代理,只需更改放入队列中的消息即可。(例如,当系统使用率高时每 10 分钟检查一次,当系统使用率低时每 20 分钟检查一次,并在夜间备份期间停止检查)。这一切都可以完成(和更改),而无需更改代理上的代码。


一个简单的现实世界例子

QueueTable
----------
ID int
deliverTime datetime
nagCount int
expireTime datetime
active bool
processed datetime (null)
' maybe some audit stuf...
' content of the message -- or external link
' etc
Run Code Online (Sandbox Code Playgroud)

START:代理拨打这样的电话

SELECT TOP 1 * 
FROM QueueTable
WHERE active = true and processed is null
ORDER BY deliverTime DESC
Run Code Online (Sandbox Code Playgroud)

然后代理查看 DeliverTime 时间是多少:

  • 如果它已经通过或在下一个模糊边界(1秒?),它会发送消息,然后将处理设置为数据库中的当前时间并循环回到开始:

  • 如果是在未来,它会休眠直到交付时间或设置一个事件以在那时唤醒它(取决于平台)。

我最初是作为布尔值进行处理的,但如果您使用 null 来等于未处理,那么它可以兼作审计字段。


无论如何,每 10 分钟检查一次的示例。

工作原理: 因为结果是按时间排序的,最早的结果将显示在顶部。我们所做的是将 10 分钟后的项目添加到结果集中。因此,最上面的项目距离当前时间永远不会超过 10 分钟。

SELECT TOP 1 * 
FROM QueueTable
WHERE active = true and processed is null
UNION ALL
SELECT NULL, DATEADD(min,GETDATE(),10), null, null, false, null, ...
ORDER BY deliverTime DESC
Run Code Online (Sandbox Code Playgroud)

请注意,活动列在此处用作标志,以表明不会执行任何操作。这条记录只是一个唤醒代理的标记。此方法还可以根据其他规则进行调整(例如一天中的时间,因为在晚上您不需要经常检查等)