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_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队列的更多相关文章
- ecshop自动确认收货(无其他商家)
1.创建文件 includes/modules/auto_order_confirm.php 代码:(思路:对已经发货和已经付款的订单检索,对比发货时间与当前时间的间隔,达到设定时间则自动收货) &l ...
- Java生鲜电商平台-电商订单系统全解析
Java生鲜电商平台-电商订单系统全解析 说明:Java生鲜电商平台-电商订单系统全解析主要讲解OMS的内容,设计,开发,架构等知识. 今天分享将会分为以下三个环节来阐述: 1.订单系统的介绍 2.订 ...
- Java生鲜电商平台-生鲜电商订单结算系统的深入解析与反思总结
Java生鲜电商平台-生鲜电商订单结算系统的深入解析与反思总结 说明:最近疫情影响,生鲜电商这个行业被彻底的激活了,全中国人民都知道用小程序或者APP可以进行买菜了,但是可惜的是,我的生鲜电商在去年经 ...
- ECSHOP订单自动确认
1.运行sql代码,生成数据库 CREATE TABLE `ecs_order_auto_confirm` ( `id` INT() UNSIGNED NOT NULL AUTO_INCREMENT, ...
- HMS Core定位服务在生活服务类App中可以自动填写收货地址啦
在涉及团购.外卖.快递.家政.物流.搬家等生活服务类的App.小程序中,填写收货地址是用户高频使用的功能.这一功能通常采取让用户手动填写的解决方案,例如上下拉动选择浙江省-->杭州市--> ...
- 电商订单ElasticSearch同步解决方案--使用logstash
一.使用logstash同步订单数据(订单表和订单项表)到ElasticSearch: 1.到官网下载logstash:https://www.elastic.co/cn/downloads/logs ...
- 电商系统架构总结2(Redis)
二 Redis缓存 考虑到将来服务器的升级扩展,使用redis代替.net内置缓存是比较理想的选择.redis是非常成熟好用的缓存系统,安装配置非常简单,直接上官网下载安装包 安装启动就行了. 1 ...
- ECSHOP自动收货解决方案 【附代码】
ecshop系统,本身不带自动确认收货的,网上也找了一下,很多很复杂,且需要在服务器端设置定时任务,如果是虚拟主机,基本上就歇菜了. 某宝有一些卖自动收货的插件,不太了解其机制,不过也比较贵,要1-2 ...
- ecshop订单-》待付款,待发货,待收货,收货确认
// 订单 待付款.待发货.待收货.确认收货 public function get_serch_order($type/*,$limit_statrt,$limit_end,$serch*/){ $ ...
随机推荐
- Android -- 贝塞尔使圆渐变为桃心
1,我们上一篇介绍了贝塞尔曲线推到原理和在Android里的简单使用,今天就和来写写贝塞尔曲线的实际应用,今天实现的效果图如下: 2,思路分析 我们知道首先我们的view是一个圆,这里的圆其实是由四块 ...
- HDU-2298 Toxophily (三分法入门系列)
题意: 意大利炮射出炮弹的速度为v,求在(0,0)击中(x,y)处的目标,发射炮弹的角度. 题解: 设f(α)表示角度为α时, f(α) = vsin(α) * t - 4.9 * t * t ① ...
- 查找及修改日程管理系统中的bug
1.Java没有分包都糅合在一起 2.在登录界面,没有输入账号密码,点击登录按钮时程序会崩溃,需要给给用户名和密码添加Toast (注:由于程序没有运行出来,所以是搭档孙刘兰的截图) 3.Regist ...
- Selenium测试专项二班隆重开班
Selenium测试专项二班隆重开班 应广大测试技术人员要求,以及企业技术需求.Selenium提前一周开课了,只针对合作的每家企业提供1-2个参训名额.预计培训60人次.但报名人数却远远超出我们预期 ...
- plist文件的相关操作
本文概要 1.plist文件的简介 2.在Xcode中创建plist文件 3.在Xcode中将plist文件转换成数组或者字典对象 4.将数组或者字典对象转换成plist文件并且存储 详细介绍 1.p ...
- 【微信开发】PHP中奖概率经典算法实例
$arr=array("50","30","20"); //这里简单列出三个数 $pro = array_sum($arr); // 概率数 ...
- [笔记]Learning to Rank算法介绍:RankNet,LambdaRank,LambdaMart
之前的博客:http://www.cnblogs.com/bentuwuying/p/6681943.html中简单介绍了Learning to Rank的基本原理,也讲到了Learning to R ...
- [Python]peewee使用经验
peewee 使用经验 本文使用案例是基于 python2.7 实现 以下内容均为个人使用 peewee 的经验和遇到的坑,不会涉及过多的基本操作.所以,没有使用过 peewee,可以先阅读文档 正确 ...
- yii2 创建ActiveForm(表单)
表单的生成表单中的方法 ActiveForm::begin()方法 ActiveForm::end()方法 getClientOptions()方法 其它方法:errorSum ...
- Unity 学习Json篇
介绍 JSON是一个简单的,但功能强大的序列化数据格式.它定义了简单的类型,如布尔,数(int和float)和字符串,和几个数据结构:list和dictionnary.可以在http://JSON.o ...