执行数据库查询 Verus 将项目存储在集合中

本文关键字:存储 集合 项目 执行数 数据库 查询 Verus 执行 | 更新日期: 2023-09-27 17:56:15

我正在尝试制作一个提醒系统,并且正在使用石英进行调度。但是,我想出了几种可能的方法,如何做我需要做的事情,但我不确定最好的方法是什么以及如何测试它。

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

所以你可以在2011年5月10日上午9:59有一个活动,你可以说提醒我"15分钟前"

那将是5月10日上午10点44分。

我将在托管环境中。(我的网站和计划将在同一环境甚至同一解决方案中运行。因此,它不会减慢浏览我网站的用户的速度。

我还使用 nhibernate

和 fluent nhibernate 来执行数据库查询。我正在为我的网站使用 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 分钟到达。

执行数据库查询 Verus 将项目存储在集合中

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

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

  • 消息代理将查询此列表并对顶部项目执行操作,或者休眠,直到列表顶部项目到期。

此技术的优点之一是,您不会让代理在检查队列时应用业务规则。 如果您希望它每分钟唤醒一次(例如检查是否有需要发送的新消息),那么您只需确保此队列始终每分钟都有一个事件(此事件可能具有不发送消息的类型,"唤醒"消息没有目标)。 代理将唤醒并执行检查。 然后,如果您想应用更复杂的调度规则,它们很容易。 您不必重新编码代理,只需更改队列中放入的消息即可。 (例如,当系统使用率高时每 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

开始:代理发出这样的电话

SELECT TOP 1 * 
FROM QueueTable
WHERE active = true and processed is null
ORDER BY deliverTime DESC

然后,代理查看交付时间是什么:

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

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

我最初作为布尔值进行处理,但如果您使用 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

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

如果选项4不符合您的要求,我可能会立即将其丢弃。

其他选项实际上取决于您的系统配置文件(有多少人在使用它?在任何给定的 5/15 分钟内有多少提醒?这些是您需要回答的问题。另外,服务器上已经发生了多少活动?如果它还没有处于高压力之下,那么每分钟查询一次根本不多。

最后,请记住,如果您每 5/15 分钟只查询一次,那么您可能会错过对计划的更改/添加/删除,如果它发生在您查询之后,并且提醒应该落在 5/15 分钟的窗口中。同样,这归结为应用程序要求,即是否可以接受。