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