码迷,mamicode.com
首页 > Web开发 > 详细

PHP设置定时任务

时间:2021-06-20 17:58:19      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:key   超时   end   大小   数据集   返回   check   start   elf   

背景

最近接到一个项目任务,需要实现一个商品的定时上下架的功能,且可以修改这个定时任务,还有默认销毁的机制存在,即如果对一个商品设置了定时上架的任务,在未执行前手动上架,则之前设置的定时任务自动失效,这对使用PHP来解决还是比较棘手的。

现状分析

一种可以使用暴力的方式,即对于请求的定时任务设置线程休眠等待,直到时间到了再执行,但一般php进程都不会常驻内存,执行完一个请求后就销毁了。这样做,无疑会造成内存的浪费,也要考虑PHP进程超时处理的策略,并且无法做到修改或者撤销定时任务的需求。

另一种是设置linux的系统定时任务,这个方式理论上是可行的,需要做到定时任务的相关的商品标识,是可以做到修改和删除指定的定时任务的,难点在于对系统定时任务的处理比较繁琐,且这个定时任务一般不能设置具体的执行逻辑,可以是访问一个php文件,这就意味着还得单独设处理逻辑。

思路

因为php基本都是用户触发机制的,因此我的思路是这个定时任务由用户来触发,每次有用户请求时,都去检查一次是否有未执行的定时任务,如果有则在执行完成后才返回结果,这样对于用户来说,定时任务是在生效中的。因为每次访问都要检查定时任务,为了不影响访问速度,我将相应的任务存放在redis缓存中,失效的任务也会及时销毁。

具体实现

//创建定时任务
public static function handleTimedTask($id, $action, $start_time, $manager, $manager_id) {
    $id = self::changeToArray($id);
    $time = time();
    //从缓存中拿定时任务
    $redis = new Redis();
    $data = $redis->get(self::COMMODITY_TASK_LIST);
    if (!$data) {
        $data = array();
    }
    foreach ($id as $value) {
        //删除任务
        if ($action != 0 && $action != 1) {
            unset($data[$value]);
        }
        //更新任务
        else {
            if ($start_time < $time) {
                return 0;
            }
            $one = array();
            $one[self::ACTION] = $action;
            $one[self::START_TIME] = $start_time;
            $one[Commodity::MANAGER] = $manager;
            $one[Commodity::MANAGER_ID] = $manager_id;
            $data[$value] = $one;
        }            
    }
    //重新存储
    $redis->set(self::COMMODITY_TASK_LIST, json_encode($data));
    return 0;
}

//检查是否有要执行的定时任务
public static function checkTimedTask() {
    $time = time();
    //从缓存中拿定时任务
    $redis = new Redis();
    $data = $redis->get(self::COMMODITY_TASK_LIST);
    if (!$data) {
        return [];
    }
    foreach ($data as $key => $value) {
        if ($value[self::START_TIME] <= $time) {
            //执行任务
            //...
            //if ($ret < 0) return $ret;
            //删除任务
            unset($data[$key]);
        }
    }
    //重新存储
    $redis->set(self::COMMODITY_TASK_LIST, json_encode($data));
    return $data;
}

redis配置持久化

因为上面设置的定时任务是存储在redis中的,redis的数据是放在内存中的,如果一旦发生意外退出的情况,数据就会丢失,因此需要做好持久化,redis提供了两种持久化的方式:RDB和AOF。

1. RDB

redis中是默认配置的持久化方式RDB的方式

save 900 1
save 300 10
save 60 10000

配置含义:

900秒内,如果超过1个key被修改,则发起快照保存

300秒内,如果超过10个key被修改,则发起快照保存

60秒内,如果1万个key被修改,则发起快照保存

2.AOF(推荐)

redis.conf默认配置:

appendonly no

配置文件中的appendonly修改为yes,开启AOF持久化。开启后,启动redis服务端,发现多了一个appendonly.aof文件。

使用AOF做持久化,每一个命令以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写,使得 AOF文件的体积不会超出保存数据集状态所需的实际大小。实际上,AOF持久化并不会立即将命令写入到硬盘文件中,而是写入到硬盘缓存,在接下来的策略中,配置多久来从硬盘缓存写入到硬盘文件。所以在一定程度一定条件下,还是会有数据丢失,不过你可以大大减少数据损失

建议用AOF的方式来做持久化

PHP设置定时任务

标签:key   超时   end   大小   数据集   返回   check   start   elf   

原文地址:https://www.cnblogs.com/bGpi/p/14905574.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!