1. 程式人生 > 其它 >伺服器cli模式下的定時器

伺服器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);
}