服务器cli模式下的定时器

有时候需要一部分后台业务异步的处理,比如处理redis队列啊,处理mysql统计啊,数据同步啊,这种长时间任务,但是又需要每段时间去看看的,发现linux cron最小只能支持每分钟的任务

分 时 天 月 星期

这颗粒度太大了,而我们实际业务往往需要几秒一次的查询或者每秒一次的业务,甚至有时候是毫秒级别的任务。

于是干脆写个后台一直运行的程序一直监控着。

最简单的方法使用 php while 死循环

<?php
while (1) {
}

发现这样CPU马上跑满了,这样消耗CPU太厉害也不行,然后给它休息一下也行

<?php
while (1) {
    usleep(1000);
}

每次1毫秒一次 这样其实CPU也消耗的不太高 百分之2-3左右吧

如果每1秒一次的话,几乎消耗的就不多了,百分之0.几

<?php
while (1) {
    sleep(1);
}

对于php开发者而言这也不错。

然后想想要不试试lua 发现lua 也有很多不同的方案。

首先可以尝试 while 死循环

while(1)
do
    
end

CPU都百分之130了,太可怕

然后加个休息 每秒休息一次

while(1)
do
    os.execute("sleep " .. 1)
end

发现这样就压根不占用CPU啊!不过然后发现这个时间是秒级别,换个毫秒级别的

local socket_now = require('socket')
while(1)
do
    socket_now.select(nil, nil, 0.001)
end

这个就是1毫秒一次了 占用CPU 百分之3-4 也还不错。

当然完全也可以用swoole的那种定时器,不过感觉那还得搞swoole,得有学习成本,对很多公司的fpm模式而言,有时候只有几个业务是后台常驻需要弄个定时器的,这样也就足够了,简单好维护。

这里面的业务代码,可以使用redis或者文件缓存等方式,看看是不是有任务,简单迅速的查询是不是需要处理,需要就处理,给开始处理业务上一个锁,避免长时间没执行完,后面的循环又压上来了造成业务执行第二次,有锁了就不做处理等待sleep。

当然也有可能锁出现问题,一直锁住 导致业务一直无法继续,那就给它加一个过期时间,当锁自然过期后,最终还是能执行进来的,毕竟这程序在一直循环。

<?php
while(1)
{
    $check_flag = check_if_we_have_task_in_redis_or_cache();
    if ($check_flag)
    {
        add_a_lock_for_flag();
        handle_task();
    }
    usleep(1000);
}

 

posted @ 2021-06-20 15:32  李照耀  阅读(89)  评论(0编辑  收藏  举报