mouse 发表于 2018-11-4 06:35:07

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>  
order 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)
页: [1]
查看完整版本: PHP电商订单自动确认收货redis队列