例如要記錄些日誌數據,我並不需要即時入庫,我想程式碼非同步執行後立刻執行下面的程式碼,我也不需要回調處理,如果把數據發給訊息佇列,這也需要時間吧,我想在毫秒就繼續下面的程式碼了,至於他把資料傳給誰,入庫花了多少時間我並不關心,舉個例子,
echo 1;
log(數據);
echo 2;
我想log函數後台執行,至於花多少時間,我不管,但是我不用去等他,對於我來說就是毫秒級執行完了似的。
例如要記錄些日誌數據,我並不需要即時入庫,我想程式碼非同步執行後立刻執行下面的程式碼,我也不需要回調處理,如果把數據發給訊息佇列,這也需要時間吧,我想在毫秒就繼續下面的程式碼了,至於他把資料傳給誰,入庫花了多少時間我並不關心,舉個例子,
echo 1;
log(數據);
echo 2;
我想log函數後台執行,至於花多少時間,我不管,但是我不用去等他,對於我來說就是毫秒級執行完了似的。
發給訊息佇列 VS 毫秒等級 >>> 矛盾點在哪裡?
用 Redis 可以做隊列吧,Redis 操作每秒讀寫上萬次 ,你把訊息放到 Redis 裡面也就 1次寫操作吧,時間消耗低於毫秒吧。
所以我覺得 使用隊列,完全可以達到你說的毫秒級的需求吧。
另外,不管透過何種手段執行非同步操作,總是伴隨時間開銷,不可避免。
<code>//程序被阻塞10秒 shell_exec('timeout 10 vmstat 1 >/dev/null 2>&1 &'); //程序不会被阻塞 pclose(popen('timeout 10 vmstat 1 >/dev/null 2>&1 &', 'r')); //因此可以异步执行任务 pclose(popen("timeout 60 php /path/to/task.php '$arg' >/dev/null 2>&1 &", 'r'));</code>
其中變數$arg是傳遞給腳本task.php的參數,task.php裡透過$argv[1]拿到這個參數.
timeout 60 表示task.php腳本的最大執行時間60秒,不需要的話可以去掉.
pclose(popen())實現異步的本質是打開一個進程去執行阻塞代碼,
適用於不要求執行完成後自動返回結果(回調)的異步場景.
字串參數$arg可以用單引號括起來,可以避免一些空格的影響,但還是有缺陷.
字串參數最好還是serialize序列化到文件,
然後給腳本task.php傳檔路徑這個參數,
讓task.php自己讀檔案unserialize反序列化拿資料.
檔案名稱應該做到唯一,例如可以是使用者ID或是進程PID加上時間隨機數:
<code>$filename = md5(uniqid($uid.'_', true)); $filename = md5(uniqid($getmypid().'_', true));</code>