PHP實現電商訂單自動確認收貨redis隊列的方法

來源:互聯網
上載者:User
本篇文章主要介紹PHP實現電商訂單自動確認收貨redis隊列的方法,感興趣的朋友參考下,希望對大家有所協助。

一、情境

之前做的電商平台,使用者在收到貨之後,大部分都不會主動的點擊確認收貨,導致給商家結款的時候,商家各種投訴,於是就根據需求,要做一個訂單在發貨之後的x天自動確認收貨。所謂的訂單自動確認收貨,就是在在特定的時間,執行一條update語句,改變訂單的狀態。

二、思路

最笨重的做法,通過linux後台定時任務,查詢合格訂單,然後update。最理想情況下,如果每分鐘都有需要update的訂單,這種方式也還行。奈何平台太小,以及賣家發貨時間大部分也是密集的,不會分散在24小時的每分鐘。那麼,定時任務的話,查詢過多,不適合。這裡可以先把將要自動確認收貨的訂單資訊儲存到其他介質上,比如redis,memcache,rabbitmq,然後執行的指令碼從前面的介質擷取到訂單資訊來判斷,這裡可以大大的減少資料庫的查詢壓力。

redis隊列的生產者

對此,我們選擇每天在淩晨兩點的時候,通過linux的定時任務把即將要確認收貨的訂單資訊查詢出來,然後儲存在redis上,redis上我們選擇的隊列,隊列處理的特點就是先進先出,前面的資料在查詢訂單時,通過發貨時間排序,所以最先出隊列的肯定是距離規定的自動收貨時間最近的訂單。代碼如下

$successCount=0;$failCount=0;$screen_time = 3600*24*9;//設定篩選天數$data = array();$now_time = time();//查詢符合要求的資料$sql="select id,send_time as deliver_time from `order` where is_send=1 and is_del=0 and is_cancel=0 and is_token=0 and send_time>0 and send_time + {$screen_time} < $now_timeorder by send_time asc";$res = $con->query($sql);//當隊列還有資料時將資料記錄並清除while($redis->LLEN('auto_recevice_order')){$txt = '執行時間:'.date('Y-m-d H:i:s').',資訊:'.$redis->RPOP('auto_recevice_order');file_put_contents('./autoToken/fail_log.txt',$txt."\r\n".PHP_EOL,FILE_APPEND);$failCount++;}//重新填充資料進隊列while ($row = $res->fetch_assoc()) { $successCount++; $redis->LPUSH('auto_recevice_order',json_encode($row1));} $con->close(); $success=date('Y-m-d H:i:s').':[推送成功]:本次成功推送資料:'.$successCount.'條;記錄上次處理失敗資料:'.$failCount."條\r\n"; file_put_contents('./success_log.txt',$success."\r\n".PHP_EOL,FILE_APPEND);

redis隊列的消費者

隊列的消費者沒有通過linux的定時任務去做,用linux的screen+php cli模式執行php指令碼,消費者只需要不斷的從隊列中讀取訂單資訊,然後判斷訂單資訊中的發貨時間,如果達到自動收貨的要求,就執行update語句。同時如果沒有達到收貨的時間,而且與收貨時間間距比較大的時候,可以讓php指令碼休眠sleep一定的時間數,這個時間數自己調節設計,擷取出來的未達到時間要求的訂單,需要重新推送到redis隊列中去,而且還是隊列的頂端。以便下次擷取。代碼如下:

$set_time = 3600*24*10;//設定幾天后自動收貨while(true){if($i%30==0){usleep(10);//防止while 迴圈使CPU使用率過高}if($redis->LLEN('auto_recevice_order')){$data = json_decode($redis->RPOP('auto_recevice_order'));$id = (int)$data->id;//將資料轉化為整形$deliver_time = (int)$data->deliver_time;//將資料轉化為整形$res1 = $res2 =false;$now_time = time();if(($deliver_time+$set_time)<$now_time){ $sql1 = "update `order` set `is_token`='1',`token_time` = $now_time where id=$id and is_send=1 and is_del=0 and is_cancel=0 and is_token=0 and send_time + {$set_time} < $now_time"; $res1 = $con->query($sql1);//更新資料$rows = mysqli_affected_rows($con);if($rows){ $ip = $this->getIp(); $sql2 = "insert into `order_log`(`order_id`,`log_msg`,`log_ip`,`log_role`,`log_user`,`log_order_state`,`log_time`) VALUES($id,'系統自動收貨','$ip','系統','伺服器','收貨',$now_time)";//寫入訂單日誌 $res2 = $con->query($sql2);//添加日誌資料 } } if($res1==false){//將沒達到條件的資料重新插入隊列中  $redis->RPUSH('auto_recevice_order',json_encode(array('id'=>$id,'deliver_time'=>$deliver_time))); }} $i++;}

這裡執行php指令碼,需要用到linux的screen或者supervisor、nohup守護進程。具體用法可自行百度.同樣指令碼裡面最好有必須的日誌記錄。

三、思考

隨著業務的增長,在隊列中同一秒內,存在的多個需要處理的訂單,而一次只能從隊列中取出一個相關訂單資訊的時候,可以採用一個生產者多個消費者的模式,這種情況下,可以用到鎖機制,保證一條訊息只能到達一個消費者。當redis資料達到一定的量之後,也可以適當的調整生產者的執行頻率和對應的條件。

以上這篇PHP實現電商訂單自動確認收貨redis隊列就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援指令碼之家。

相關推薦:

電子商務網站自動確認收貨怎麼實現的

PHP擷取redis裡不存在的6位隨機數的方法

PHP實現redis訊息佇列發布微博的方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.