定时任务之行为触发

  in   tech with  0  comment

一个完整的项目往往需要定时的自检、数据备份、数据处理等等定时执行的任务。

说到定时任务可能都不陌生,linux有crontab,windows有计划任务。在服务器维护中,很多地方比如定时检测服务器状态、定时备份文件等比较常用。

但是具体到项目中的时候再用系统的定时任务可能就不太方便了,因为网站维护和服务器运维往往是分开的,而且服务器编写脚本执行也不太适合项目中灵活多变的计划任务,所以我们需要另外一种定时任务的方法,那就是用户行为触发。就是在用户访问网站的时候,程序自动检测有没有预置的计划任务,如果有就执行。这种方式后台配置方便,操作简单。下面我们就用来实现一下这一过程。

首先,我们用数据库来保存任务的详情。

CREATE TABLE IF NOT EXISTS `sp_crontab` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `title` varchar(100) NOT NULL COMMENT '任务名称', `type` int(1) NOT NULL DEFAULT '1' COMMENT '任务类型', `interval` int(10) DEFAULT NULL COMMENT '间隔时间', `time` int(10) DEFAULT NULL COMMENT '定时时间', `execution` int(10) DEFAULT NULL COMMENT '执行时间', `action` varchar(100) NOT NULL COMMENT '执行动作', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

因为要提供两种任务类型,所以用 interval 和 time 两个字段分别保存间隔时间和定时时间,用 execution 来保存上次执行时间以作判断。

在我们后台创建任务之后,尽量将任务缓存起来,否则用户的每个请求都要执行查询任务,浪费资源。

然后我们在程序的全局方法里进行检测

$crontab=new Crontab(); $data=Cache::get('crontab'); try { foreach ($data as $val) { $check=false; if($val['type']==1&&!$val['execution']&&$val['time']<=time()){ //定时任务 $check=true; } if($val['type']==2&&(time()-$val['interval']*86400)>$val['execution']){ //循环任务 $check=true; } if($check){ ob_start(); $crontab->run($val['action'],$val['id']); ob_get_clean(); ob_end_flush(); } } } catch (Exception $e) { }

这里一定要注意配合日志使用,一旦出现问题能及时排查。

注意,这种方式也有一定的缺陷性,就是如果没有用户访问或用户访问量很小的话很难达到及时的任务处理。所以这种方式更适合用来处理和用户相关的数据,并且实时性要求不是特别严格的数据。比如热门搜索、热门文章、排行榜之类的缓存更新。

Responses