2016年1月8日 16:08:43 星期五
情景: 使用者登入日志, 發郵件, 發短信等等實時性要求不怎麼高的業務通常會異步執行
之前接觸過幾種redis+crontab配套的實作方法,
比如: crontab定時執行curl腳本
1. 用curl 通路URL執行PHP腳本去pop隊列
2. PHP程式pop一次, 處理後傳回同樣的URL
3. curl收到這個URL後就可以再次跟蹤通路并執行該PHP程式, 這樣就可以實作循環pop的效果
4. 這樣需要給curl設定下最大跟蹤次數(--max-redirs), 就可以限定每次pop的最大值
但總感覺那麼不順暢
1. 不是實時的, 最高頻率是每隔一分鐘執行一次(當然也有其它方法使之能每秒都運作)
2. 不同時間段打入隊列的資料是不确定的, 比如白天登入使用者會比晚上多, crontab執行頻率設定不合理的話, 比如,白天入隊列的資料可能大于出隊列的資料進而導緻延時加大
這兩天學到了一個新的方法, 可以解決實時性的問題:
PHP程式: 一個阻塞型的死循環去pop隊列
crontab:去監控這個PHP循環是不是在運作, 沒有則啟動
PHP程式:
注意:
1. while true, 看似是死循環, 但是裡邊的brpop是阻塞型的代碼, 隊列裡邊沒有資料的時候會讓出CPU直到資料的到來, 等待10秒鐘後還沒有資料就停掉, 進入下一次循環(下一個10s)
2. 因為是死循環, 要一直執行下去, 是以最好的方式是php_cli模式下執行, 這個模式下是不會有逾時限制的
3. "read error on connection" 報錯, 因為brpop阻塞10s, 是以PHP在連接配接redis時設定的timeout時間必須得大于這個時間, 或者幹脆就不設定逾時:
crontab怎麼配合: 定期檢查這個PHP腳本是否是在執行, 如果沒有就啟動它
start.sh:
這中實作方式可以達到實時的
但是沒資料的時候, 死循環會一直阻塞下去, 但貌似也不耗費什麼資源