簡單定時任務解決方案:使用redis的keyspace notifications(鍵失效後通知事件) 須要注意此功能是在redis 2.8版本之後推出的,所以你服務器上的reids最少要是2.8版本以上;javascript
(A)業務場景:php
一、當一個業務觸發之後須要啓動一個定時任務,在指定時間內再去執行一個任務(如自動取消訂單,自動完成訂單等功能)java
二、redis的keyspace notifications 會在key失效後發送一個事件,監聽此事件的的客戶端就能夠收到通知mysql
(B)服務準備:nginx
一、修改reids配置文件(redis.conf)【window系統配置文件爲:redis.windows.conf 】redis
redis默認不會開啓keyspace notifications,由於開啓後會對cpu有消耗sql
備註:E:keyevent事件,事件以__keyevent@<db>__爲前綴進行發佈;shell
x:過時事件,當某個鍵過時並刪除時會產生該事件;數據庫
原配置爲:windows
更改 配置以下:
保存配置後,重啓Redis服務,使配置生效
window系統重啓redis ,先切換到redis文件目錄,而後關閉redis服務(redis-server --service-stop),再開啓(redis-server --service-start)
C)文件代碼:
phpredis實現訂閱Keyspace notification,可實現自動取消訂單,自動完成訂單。如下爲測試例子
建立4個文件,而後自行修改數據庫和redis配置參數
db.class.php
index.php
psubscribe.php
Redis2.class.php
window系統測試方法:先在cmd命令界面運行psubscribe.php,而後網頁打開index.php。
有個問題 作到這一步,利用 phpredis 擴展,成功在代碼裏實現對過時 Key 的監聽,並在 psCallback()裏進行回調處理。開頭提出的兩個需求已經實現。但是這裏有個問題:redis 在執行完訂閱操做後,終端進入阻塞狀態,須要一直掛在那。且此訂閱腳本須要人爲在命令行執行,不符合實際需求。
實際上,咱們對過時監聽回調的需求,是但願它像守護進程同樣,在後臺運行,當有過時事件的消息時,觸發回調函數。使監聽後臺始終運行 但願像守護進程同樣在後臺同樣,
我是這樣實現的。
Linux中有一個nohup命令。功能就是不掛斷地運行命令。同時nohup把腳本程序的全部輸出,都放到當前目錄的nohup.out文件中,若是文件不可寫,則放到<用戶主目錄>/nohup.out 文件中。那麼有了這個命令之後,無論咱們終端窗口是否關閉,都可以讓咱們的php腳本一直運行。
編寫psubscribe.php文件:
注意:咱們在開頭,申明 php 編譯器的路徑:
這是執行 php 腳本所必須的。
而後,nohup 不掛起執行 psubscribe.php,注意 末尾的 &
說明:腳本確實已經在 4456 號進程上跑起來。
查看下nohup.out cat 一下 nohuo.out,看下是否有過時輸出:
運行index.php ,3秒後效果如上即成功
遇到問題:使用命令行模式開啓監控腳本 ,一段時間後報錯 :Error while sending QUERY packet. PID=xxx
解決方法:因爲等待消息隊列是一個長鏈接,而等待回調前有個數據庫鏈接,數據庫的wait_timeout=28800,因此只要下一條消息離上一條消息超過8小時,就會出現這個錯誤,把wait_timeout設置成10,而且捕獲異常,發現真實的報錯是 MySQL server has gone away ,
因此只要處理完全部業務邏輯後主動關閉數據庫鏈接,即數據庫鏈接主動close掉就能夠解決問題
yii解決方法以下:
查看進程方法:
查看jobs進程ID:[ jobs -l ]命令
終止後臺運行的進程方法:
清空 nohup.out文件方法:
咱們在使用nohup的時候,通常都和&配合使用,可是在實際使用過程當中,不少人後臺掛上程序就這樣無論了,其實這樣有可能在當前帳戶非正常退出或者結束的時候,命令仍是本身結束了。
因此在使用nohup命令後臺運行命令以後,咱們須要作如下操做:
1.先回車,退出nohup的提示。
2.而後執行exit正常退出當前帳戶。3.而後再去連接終端。使得程序後臺正常運行。