一种秒级CRON任务的实现原理设计

发布: 2013-07-21 22:59

cron定时任务在web开发中,实现特定的后台任务处理功能非常有用。
系统级的cron是分钟级的,对有些应用可能不够用。

经过长时间的思路整理,思考出来一种秒级cron的的实现机制。
设计场景,
把秒级cron任务的下次执行时间计算为绝对时间,放在内存hash表中,
每个计算出的时间作为一个hash key,而该时间对应的可能有多个任务,
同一秒的多个任务当作数组或者队列作为hash值存储。
使用libevent的秒级计时器,每秒检测一次任务检测,这个逻辑属于hash表查询,
10w级别,甚至100w级别的内存hash查询不都会有什么延迟时间。
注意这里有个细节,可能导致跳过一秒的问题,对于这种情况,虽然说是一秒检查一次,
实现上需要记录上次执行检查的绝对时间戳,从上次时间戳的下一秒到本次检查的时间戳,
这样才不会遗漏任何任务,即使计时器长时间执行偶尔有跳过一秒。

对于当前检测到所有需要执行的任务,通过线程等异步功能执行,主线程逻辑继续等待下一秒事件。

当然,这里还有一个问题,由于同一时间的任务放在hash表的一个key,
在程序执行过程,会有修改某个key的值的问题,如果值列表的数据结构不合理,
有可能修改慢,或者有锁开销、冲突、死锁等问题,在实现实现的需要特别注意。

最后剩下的问题,就是分布式的机制问题,还需要再考虑整理下,再来补充。

分布式的问题,
每个节点均可接收原始的CRON处理请求
接收到原始的CRON注册请求后,
*)可以随机找个节点记录下原始的注册请求,基于不信任客户端的原则,
还需要重新分配一次节点,而不能直接在接收到的节点记录
*)接下来不断循环执行下次任务。

对于任务的可靠性问题,
*)可以记录原始CRON注册请求的副本,一个集群中每个原始注册请求信息会记录两份以上
*)对于等待执行的任务,也可以考虑在不同的节点写入两个副本,
以便在某节点故障时副本能够执行而不会丢失任务,或者任务的间隔超过设置的时间间隔
*)这样引入一个问题,需要确认某个任务的主本是否失效,是否在给定的时间执行了
可以通过主本执行,副本延迟检测的机制,
如果检测到已经执行,则修改其标记,以后不再检测,
如果检测到延迟某时间后主本仍旧没有执行,则副本来执行,并设置相应的标记
如果主本在某个时刻恢复了,则需要检测相应的标记。
如果主本不能够恢复,副本需要升级为主本,并再次设置一个副本。
这时,主本恢复时应该是一个空的没有任务的节点,如果有任务,则可能重复任务。
某个节点在离开集群某段时间后,需要自动清空其上的任务。

如果某个节点下线,其上很可能包含原始的注册请求信息,这个丢失的话,问题也比较严重,
需要对这种情况作处理。

如果不能合理的处理节点的下线,以及丢失CRON任务的功能,则无法称之为合格的分布式系统设计。












原文: http://qtchina.tk/?q=node/738

Powered by zexport