一、场景
之前做的电商平台,用户在收到货之后,大部分都不会主动的点击确认收的货,导致给商家结款的时候,商家各种投诉,于是就根据需求,要做一个订单在发货之后的x天自动确认收货。所谓的订单自动确认收的货,就是在在特定的时间,执行一条更新语句,改变订单的状态。
二、思路
最笨重的做法,通过linux后台定时任务,查询符合条件的订单,然后更新。最理想情况下,如果每分钟都有需要更新的订的单,这种方式也还行。奈何平台太小,以及卖家发货时间大部分也是密集的,不会分散在24小时的每分钟,那么,定时任务的话,查询过多,不适合。这里可以先把将要自动确认收货的订单信息存储到其他介质上,比如复述,memcache, rabbitmq,然后执行的脚本从前面的介质获取到订单信息来判断,这里可以大大的减少数据库的查询压力。
<编辑>复述队列的生产者编辑>对此,我们选择每天在凌晨两点的时候,通过linux的定时任务把即将要确认收货的订单信息查询出来,然后存储在复述上,复述,上我们选择的队列,队列处理的特点就是先进先出,前面的数据在查询订单时,通过发货时间排序,所以最先出队列的肯定是距离规定的自动收货时间最近的订单。代码如下
$ successCount=0; 美元failCount=0; screen_time美元=3600 * 24 * 9;//设置筛选天数 $ data=https://www.yisu.com/zixun/array (); $ now_time=时间();//查询符合要求的数据 $ sql=把≡駃d, send_time deliver_time从‘秩序’is_send=1 is_del=0和is_cancel=0 is_token=0和send_time> 0和send_time + {$ screen_time} & lt;now_time美元 order by send_time asc”; res=反对美元→查询($ sql);//当队列还有数据时将数据记录并清除 而(复述→美元LLEN (auto_recevice_order)) { $ txt=爸葱惺奔?“。日期(Y-m-d H:我:年代”)。”,信息:“。美元复述→RPOP (“auto_recevice_order”); 写入”。/autoToken fail_log.txt’, $ txt。\ r \ n”.PHP_EOL, FILE_APPEND); 美元failCount + +; }//重新填充数据进队列 而(行=res→美元fetch_assoc ()) { 美元successCount + +; 复述→美元LPUSH (auto_recevice_order, json_encode(第一行)美元); } 反对美元→close (); 成功=美元日期(Y-m-d H:我:年代”)。”:[推送成功):本次成功推送数据:“successCount美元。”条,记录上次处理失败数据:“failCount美元。“条\ r \ n”; 写入”。/success_log.txt’,美元成功。\ r \ n .PHP_EOL, FILE_APPEND);
<编辑>复述队列的消费者编辑>
队列的消费者没有通过linux的定时任务去做,用linux的屏幕+ php cli模式执行php脚本,消费者只需要不断的从队列中读取订单信息,然后判断订单信息中的发货时间,如果达到自动收货的要求,就执行更新语句。同时如果没有达到收货的时间,而且与收货时间间距比较大的时候,可以让php脚本休眠睡一定的时间数,这个时间数自己调节设计,获取出来的未达到时间要求的订单,需要重新推送到复述队列中去,而且还是队列的顶端。以便下次获取。代码如下:
set_time=3600 * 24 * 10美元;//设置几天后自动收的货 而(真){ 如果我($ % 30==0){ usleep(10);//防止而循环使CPU使用率过高 } 如果(复述→美元LLEN (auto_recevice_order)) { (data=https://www.yisu.com/zixun/json_decode美元复述-> RPOP (' auto_recevice_order ')); id=(int)数据→美元id;//将数据转化为××× deliver_time=(int)数据→美元deliver_time;//将数据转化为××× res1=它美元=false; $ now_time=时间(); 如果((deliver_time + set_time美元)& lt; now_time美元){ sql1="美元更新“秩序”设置“is_token '=' 1 ', ' token_time=$ now_time id=$ id和is_send=1 is_del=0和is_cancel=0 is_token=0和send_time + {$ set_time} & lt;美元now_time”; res1=反对美元→查询(sql1美元);//更新数据 (行=mysqli_affected_rows美元con); 如果美元(行){ $ ip=$ this→getIp (); 美元sql2="插入“order_log”(‘order_id’,‘log_msg’,‘log_ip’,‘log_role’,‘log_user’,‘log_order_state’,‘log_time’)值($ id的系统自动收货”,“美元ip”,“系统”,“服务器”、“收货”,now_time美元)”;//写入订单日志 它=反对美元→查询(sql2美元);//添加日志数据 } } if ($ res1==false){//将没达到条件的数据重新插入队列中 复述→美元RPUSH (auto_recevice_order, json_encode(数组(“id”=祝辞$ id ' deliver_time '=祝辞deliver_time美元))); } } 美元我+ +; }PHP电商订单自动确认收货复述队列