700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > java订单超时取消设计_PHP如何实现处理过期或者超时订单的 并还原库存

java订单超时取消设计_PHP如何实现处理过期或者超时订单的 并还原库存

时间:2020-10-29 12:03:52

相关推荐

java订单超时取消设计_PHP如何实现处理过期或者超时订单的 并还原库存

文章来自:php自学中心网站

链接:/front/php/122378.html

作者:磊丰

商务合作:请加微信(QQ):2230304070

视频教程

码农网每天更新3个教程158RMB升级永久会员,即可查看网站全部视频教程。有问题请咨询微信:2230304070

文章正文

订单是我们在日常开发中经常会遇到的一个功能,最近在做一个订单过期与超时的开发。订单过期与超时就不用我解释了吧,其实两者都是同一个问题来着,就是订单未支付的处理,我们要做的是对这些未支付的订单到了一定时间就自动取消,好了,你第一反应那肯定就是做一个定时任务了!是的,就是定时任务,但是哪个才会是最佳方案呢,下面来看看:

一、前端到时间请求取消

你肯定不会想着在前端来做定时请求取消该订单的,因为如果客户禁用了该应用或者没联网,那到了一定时间时,还一直都是未处理状态的。所以前端一般都是手动去触发取消订单的。

二、服务端定时查询有没有需要取消的订单,然后批量处理。

这种方法我们用得最多的,不过存在准确度的问题,还有需要确认定时任务的周期,但是我们可以结合redis来实现,我们可以在存redis时候顺便存在mysql这样的数据库做长久存储然后用服务端定时查询,这里我用到了redis的订阅功能。

首先先修改一下配置

vim/etc/redis/redis.conf

notify-keyspace-events“Ex”#x 代表了过期事件。

然后再重启redis

serviceredisrestart

这里创建4个文件

index.php创建订单,发布消息,10s后查询订单状态并更新订单

<?php require_once'Redis2.class.php';require_once'db.class.php';

$redis2=new\Redis2();

$list=$redis2->lRange('order',0,9999999);

$mysql=new\mysql();

$mysql->connect();

$data=['ordersn'=>'SN'.time().'T'.rand(10000000,99999999),'status'=>0,'createtime'=>date('Y-m-dH:i:s',time())];

$mysql->insert('order',$data);

$order_sn=$data['ordersn'];

$redis2->setex($order_sn,10,$order_sn);

psubscribe.php,发布redis订阅的一些逻辑处理

<?php

ini_set('default_socket_timeout',-1);//设置不超时require_once'./Redis.class.php';require_once'./db.class.php';

$redis=new\Redis2();//解决Redis客户端订阅时候超时情况

$redis->setOption();

$redis->psubscribe(array('__keyevent@0__:expired'),'keyCallback');//回调函数,这里写处理逻辑functionkeyCallback($redis,$pattern,$chan,$msg){

$mysql=new\mysql();

$mysql->connect();

$where="ordersn='".$msg."'";

$mysql->select('order','',$where);

$finds=$mysql->fetchAll();if(isset($finds[0]['status'])&&$finds[0]['status']==0){

$data=array('status'=>3,'updatetime'=>date('Y-m-dH:i:s',time()));

$where="id=".$finds[0]['id'];

$mysql->update('order',$data,$where);

}

}

这里我把redis的一些操作和mysql的一些处理做了封装处理,这个你们可以用到你们自己的项目当中的

Redis2.class.php

<?php classRedis2{private$redis;publicfunction__construct($host='127.0.0.1',$port=6379){$this->redis=newRedis();$this->redis->connect($host,$port);$this->redis->auth('123456');

}publicfunctionsetex($key,$time,$val){return$this->redis->setex($key,$time,$val);

}publicfunctionset($key,$val){return$this->redis->set($key,$val);

}publicfunctionget($key){return$this->redis->get($key);

}publicfunctionexpire($key=null,$time=0){return$this->redis->expire($key,$time);

}publicfunctionpsubscribe($patterns=array(),$callback){$this->redis->psubscribe($patterns,$callback);

}publicfunctionsetOption(){$this->redis->setOption(\Redis::OPT_READ_TIMEOUT,-1);

}publicfunctionlRange($key,$start,$end){return$this->redis->lRange($key,$start,$end);

}publicfunctionlPush($key,$value1,$value2=null,$valueN=null){return$this->redis->lPush($key,$value1,$value2=null,$valueN=null);

}publicfunctiondelete($key1,$key2=null,$key3=null){return$this->redis->delete($key1,$key2=null,$key3=null);

}

}

db.class.php,对sql处理的一些封装

<?php classmysql{private$mysqli;private$result;/**

*数据库连接

*@param$config配置数组

*/publicfunctionconnect(){

$config=array('host'=>'127.0.0.1','username'=>'root','password'=>'123456qwerty','database'=>'marhal','port'=>3306,

);

$host=$config['host'];//主机地址

$username=$config['username'];//用户名

$password=$config['password'];//密码

$database=$config['database'];//数据库

$port=$config['port'];//端口号$this->mysqli=newmysqli($host,$username,$password,$database,$port);

}/**

*数据查询

*@param$table数据表

*@paramnull$field字段

*@paramnull$where条件

*@returnmixed查询结果数目

*/publicfunctionselect($table,$field=null,$where=null){

$sql="SELECT*FROM`{$table}`";//echo$sql;exit;if(!empty($field)){

$field='`'.implode('`,`',$field).'`';

$sql=str_replace('*',$field,$sql);

}if(!empty($where)){

$sql=$sql.'WHERE'.$where;

}$this->result=$this->mysqli->query($sql);return$this->result;

}/**

*@returnmixed获取全部结果

*/publicfunctionfetchAll(){return$this->result->fetch_all(MYSQLI_ASSOC);

}/**

*插入数据

*@param$table数据表

*@param$data数据数组

*@returnmixed插入ID

*/publicfunctioninsert($table,$data){foreach($dataas$key=>$value){

$data[$key]=$this->mysqli->real_escape_string($value);

}

$keys='`'.implode('`,`',array_keys($data)).'`';

$values='\''.implode("','",array_values($data)).'\'';

$sql="INSERTINTO`{$table}`({$keys})VALUES({$values})";$this->mysqli->query($sql);return$this->mysqli->insert_id;

}/**

*更新数据

*@param$table数据表

*@param$data数据数组

*@param$where过滤条件

*@returnmixed受影响记录

*/publicfunctionupdate($table,$data,$where){foreach($dataas$key=>$value){

$data[$key]=$this->mysqli->real_escape_string($value);

}

$sets=array();foreach($dataas$key=>$value){

$kstr='`'.$key.'`';

$vstr='\''.$value.'\'';

array_push($sets,$kstr.'='.$vstr);

}

$kav=implode(',',$sets);

$sql="UPDATE`{$table}`SET{$kav}WHERE{$where}";$this->mysqli->query($sql);return$this->mysqli->affected_rows;

}/**

*删除数据

*@param$table数据表

*@param$where过滤条件

*@returnmixed受影响记录

*/publicfunctiondelete($table,$where){

$sql="DELETEFROM`{$table}`WHERE{$where}";$this->mysqli->query($sql);return$this->mysqli->affected_rows;

}

}

对每一次订单的访问我们做了服务器监听任务,如下:

cd/var/www/html/redis

#即时监听,ctrl+c退出监听ctrl+z暂停监听

nohupphppsubscribe.php

#后台监听

nohupphppsubscribe.php&

设置本地域名并访问/index.php

此时,每访问一次index.php,就会创建一个订单,10s钟后,如果该订单依旧处于未支付状态,就设置订单失效。

这里要注意一下:

在命令之前加上 nohup ,启动的进程将会忽略linux的挂起信号 (SIGHUP)

这时候,当我们组合 nohup 和 &两种方式时,启动的进程不会占用控制台,并且不依赖控制台,控制台关闭之后,进程被1号进程收养,成为孤儿进程,这就和守护进程的机制非常类似了,并且nohup默认会把程序的输出重定向到当前目录下的nohup.out文件,如果没有可写权限,则写入 $homepath/nohup.out

但是php的cli模式在服务器运行后,总是会掉线,处理这个问题的方法,我们不妨写一个脚本

1.编写shell脚本,定时检查进程是否存在,不存在的话就开启服务,并且将运行情况写入日志

cd/

mkdirmytask

cdmytask

touchphprunning.sh

viphprunning.sh

脚本文件如下:

#!/bin/sh

PIDS=`pidofphp`

if["$PIDS"!=""];then

echo"在运行"

echo-e$(date+%Y"."%m"."%d""%k":"%M":"%S)"running.....">>/mytask/task.run.log

else

echo"不在运行,开始启动"

echo-e$(date+%Y"."%m"."%d""%k":"%M":"%S)"startphpstart.....">>/mytask/task.start.log

cd/var/www/html/redis

phppsubscribe.php&

echo-e$(date+%Y"."%m"."%d""%k":"%M":"%S)"startphpsuccess.....">>/mytask/task.start.log

fi

在crontab任务里创建任务,这里设定的是每5s检查一次,crontab -e

*****sleep5;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep10;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep15;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep20;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep25;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep30;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep35;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep40;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep45;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep50;sh/mytask/phprunning.sh>>/mytask/crontab.log

*****sleep55;sh/mytask/phprunning.sh>>/mytask/crontab.log

效果你可以查看task.run.log

cat/mytask/task.run.log

结果如下:

-e.10.2214:28:41running.....

-e.10.2214:28:46running.....

-e.10.2214:28:51running.....

-e.10.2214:28:56running.....

-e.10.2214:29:06running.....

-e.10.2214:29:11running.....

-e.10.2214:29:16running.....

-e.10.2214:29:21running.....

-e.10.2214:29:26running.....

-e.10.2214:29:31running.....

-e.10.2214:29:36running.....

-e.10.2214:29:41running.....

-e.10.2214:29:46running.....

以上是本文的全部内容,希望对大家的学习有帮助,也希望大家多多支持php自学中心感谢阅读!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。