PHP实现电商订单自动确认收货redis队列


Posted in PHP onMay 17, 2017

一、场景

之前做的电商平台,用户在收到货之后,大部分都不会主动的点击确认收货,导致给商家结款的时候,商家各种投诉,于是就根据需求,要做一个订单在发货之后的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_time
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)<$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 相关文章推荐
利用php来自动调用不同服务器上的flash
Oct 09 PHP
让你的WINDOWS同时支持MYSQL4,MYSQL4.1,MYSQL5X
Dec 06 PHP
用PHP调用Oracle存储过程的方法
Sep 12 PHP
php入门学习知识点二 PHP简单的分页过程与原理
Jul 14 PHP
PHP多例模式介绍
Jun 24 PHP
codeigniter自带数据库类使用方法说明
Mar 25 PHP
Yii实现多数据库主从读写分离的方法
Dec 29 PHP
php页面,mysql数据库转utf-8乱码,utf-8编码问题总结
Aug 27 PHP
PHP 读取大文件并显示的简单实例(推荐)
Aug 12 PHP
php删除数组指定元素实现代码
May 03 PHP
微信支付之JSAPI公众号支付详解
May 15 PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
Feb 16 PHP
老生常谈PHP面向对象之解释器模式
May 17 #PHP
phpmyadmin下载、安装、配置教程
May 16 #PHP
Windows下php+mysql5.7配置教程
May 16 #PHP
php使用curl实现ftp文件下载功能
May 16 #PHP
PHP jpgraph库的配置及生成统计图表:折线图、柱状图、饼状图
May 15 #PHP
php使用curl实现简单模拟提交表单功能
May 15 #PHP
PHP读取Excel类文件
May 15 #PHP
You might like
PHP中PDO基础教程 入门级
2011/09/04 PHP
php中计算程序运行时间的类代码
2012/11/03 PHP
获取用户Ip地址通用方法与常见安全隐患(HTTP_X_FORWARDED_FOR)
2013/06/01 PHP
windows中为php安装mongodb与memcache
2015/01/06 PHP
SESSION存放在数据库用法实例
2015/08/08 PHP
超强多功能php绿色集成环境详解
2017/01/25 PHP
jquery 3D球状导航的文章分类
2010/07/06 Javascript
基于jquery可配置循环左右滚动例子
2011/09/09 Javascript
js 控制下拉菜单刷新的方法
2013/03/03 Javascript
JavaScript 函数惰性载入的实现及其优点介绍
2013/08/12 Javascript
js设置cookie过期当前时间减去一秒相当于立即过期
2014/09/04 Javascript
javascript文件加载管理简单实现方法
2015/07/25 Javascript
jQuery树形插件jquery.simpleTree.js用法分析
2016/09/05 Javascript
深究AngularJS中$sce的使用
2017/06/12 Javascript
使用ionic(选项卡栏tab) icon(图标) ionic上拉菜单(ActionSheet) 实现通讯录界面切换实例代码
2017/10/20 Javascript
基于vue实现网站前台的权限管理(前后端分离实践)
2018/01/13 Javascript
jquery拖拽自动排序插件使用方法详解
2020/07/20 jQuery
ES6知识点整理之数组解构和字符串解构的应用示例
2019/04/17 Javascript
在微信小程序中使用图表的方法示例
2019/04/25 Javascript
electron实现静默打印的示例代码
2019/08/12 Javascript
vue获取验证码倒计时组件
2019/08/26 Javascript
[48:46]完美世界DOTA2联赛PWL S2 SZ vs FTD.C 第二场 11.19
2020/11/19 DOTA
[原创]使用豆瓣提供的国内pypi源
2017/07/02 Python
Python基于多线程操作数据库相关问题分析
2018/07/11 Python
Python爬虫文件下载图文教程
2018/12/23 Python
Python 3.8 新功能大揭秘【新手必学】
2020/02/05 Python
pytorch读取图像数据转成opencv格式实例
2020/06/02 Python
pandas使用函数批量处理数据(map、apply、applymap)
2020/11/27 Python
纯css3实现效果超级炫的checkbox复选框和radio单选框
2014/09/01 HTML / CSS
HTML5印章绘制电子签章图片(中文英文椭圆章、中文英文椭圆印章)
2019/06/03 HTML / CSS
财务会计人员求职的自我评价
2014/01/13 职场文书
重阳节活动总结
2014/08/27 职场文书
2014年度个人工作总结范文
2015/03/09 职场文书
2015年财政所工作总结
2015/04/25 职场文书
2019安全宣传标语大全
2019/08/14 职场文书
Redisson实现Redis分布式锁的几种方式
2021/08/07 Redis