伺服器cli模式下的定時器
阿新 • • 發佈:2021-06-20
有時候需要一部分後臺業務非同步的處理,比如處理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啊!不過然後發現這個時間是秒級別,換個毫秒級別的
localsocket_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); }