轮询是否比设置多个setTimeout()更好?

3

我正在开发一个邮件提醒系统,可以在任务到期前24、8、3和1小时向用户发送提醒。

我有一个运行在 Node.js 上的服务器。我的第一个想法是每次分配任务时设置四个单独的 setTimeout()。但是,我认为在服务器上拥有数百个空闲的 setTimeout() 不是最佳性能。

因此,我是否应该每五分钟轮询未完成的任务并向具有即将到期任务的用户发送提醒?这种方法的缺点是每五分钟都需要读取整个 MongoDB 集合。


我认为使用超时不是一个好主意,如果由于任何原因nodejs重新启动,则所有计时器都会丢失。我建议使用调度程序每分钟检查哪些用户应该被ping,并使用cronjob调用“独立”的js脚本,即您的第二个解决方案。 - apokryfos
1个回答

2
Nodejs非常高效,可以处理大量的定时器,你可以轻松地拥有成千上万个定时器而没有任何实质性的影响。它使用了一个排序的链表,插入新的计时器只需要很少的时间,并且一旦插入后就不会再花费任何时间。
事件循环中只会比较位于列表开头的下一个要触发的定时器。当它触发时,它将从链表的开头移除,并且列表中的下一个定时器现在位于链表头部。由于它是一个链表,因此触发定时器并从链表开头移除所需的时间与列表的长度无关(例如,它不是必须复制下来的数组)。
因此,对于您特定的应用程序而言,优化数据库的效率(尽可能少的请求)比最小化定时器的数量更为重要。因此,我建议采用优化数据库负载的任何定时器设计/实现。
顺便说一下,如果您想提醒用户4次即将到期的任务,每个任务仍然只能同时有一个活动定时器。设置第一个定时器触发后,当它通知时,您可以对先前保存的到期日期/时间进行一些时间计算,看何时设置下一个定时器。这将使您每个任务只保留一个定时器,而不是四个。
但是,这里的主要观点仍然是您应该首先优化设计以有效地使用数据库。
另外,定时器不是持久性的,因此如果您的服务器重新启动,则需要一种机制来在服务器启动时重新创建适当的定时器(可能是提供在某个时间内待处理任务的数据库查询)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接