PHP实现订单的延时处理

真没想到本身的这篇很水的文章还有一些可爱的朋友们去阅读,真的很感谢大家。其实这篇文章是我在元旦假期最后一天无事可作的时候偶然脑子抽搐想到的一个场景,而后试着去实现的,其实订单自动取消功能网上有不少可借鉴的方法,包括评论区的朋友们提到的定时任务和消息队列,我这个只是在一个本身想到的方法(我认可真的真的很水)。
感谢评论区的朋友们的热心建议和教导,我也会去借鉴一下大家的指导意见,同时继续学习,再次对大家表示感谢~ღ( ´・ᴗ・` )比心php


如下是原文:html

业务需求

最近在作业务的时候须要实现客户下单以后订单超时未支付自动取消的功能,刚开始确认了几种方法:python

  • 客户端到时间请求取消
  • 服务端定时查询有没有须要取消的订单,而后批量处理
  • 下单后建立定时器,延时处理
  • 使用redis或者memcache存储,设置过时时间,自动删除

综合考虑上述方法,第一种最早排除,由于若是客户把APP后台禁止或者网络链接禁止,那么就没法发给服务端请求,订单就会一直是未处理状态;第二种方法使用的比较多,不过存在准确度的问题,还有须要确认定时任务的周期,暂时列为后补方法;第四种方法存在的问题就是订单若是删除就是物理删除,没法统计未处理数据(固然能够存redis时候顺便存在mysql这样的数据库作长久存储而后用方法二定时处理)。
最终准备使用方法三。
再确认使用方法3的时候,因为使用的PHP这种开发语言,因此想实现定时器功能须要借助Swoole或者workerman。因为SwooleC开发的扩展框架,性能方面确定比较好,就选了Swoolemysql

前期准备

  • 使用Swoole首先须要在服务器上安装Swoole扩展,安装方法和安装其余扩展大同小异,能够参考这边文章
  • 安装完以后检测下扩展是否正常安装,查看phpinfo或者PHP-m,若是出现Swoole,则说明安装成功
  • Swoole官方文档有定时器的相关文档

开始测试

咱们建立一个swoole_test.php文件和一个log.txt文件(用来测试),swoole_test.php代码以下:web

<?php
swoole_timer_after(3000, function () {
    append_log(time());
    echo "after 3000ms.\n";
});

function append_log($str) {
    $dir = 'log.txt';
    $fh = fopen($dir, "a");
    fwrite($fh, $str."\n");
    fclose($fh);
}

而后在网页访问这个PHP文件,结果以下:图片描述ajax

而后在Linux终端运行PHP:/usr/local/php7/bin/php /home/app/swoole_test.php,结果以下:
图片描述
心里一阵。。。
图片描述
原来定时器只能在cli模式下,那么这个想法怕是要GG了,难道就栽倒这里了吗,难道就没有别的方法了吗?就在我欲哭无泪的时候忽然灵光乍现,一个词闪到个人脑海:Python
对,咱们不能单单靠着PHP啊,还有Python这种神奇的语言呢,咱们知道Pythonos模块里的os.system方法是能够执行命令行的,那么不就能够实如今cli模式下运行刚才的swoole_test.php文件了么。
心里一阵激动后,以为测试是否可行
咱们知道Linux都是自带Python的,可是不一样的版本Python版本不一样,有的自带的是Python2.6,版本太低了,因此须要装一个高版本的,这里我选择Python3,注意不要覆盖系统自带的Python2 。如下是大体的安装步骤:redis

  • wget http://python.org/ftp/python/...
  • tar xf Python-3.6.0.tar.xz
  • cd Python-3.6.0
  • ./configure --prefix=/usr/local/python3
  • make && make install
  • ln -s /usr/local/python3/bin/python3 /usr/bin/python3

接下来终端输入:Python3,若是出现
图片描述sql

则安装成功。
安装完Python3以后,咱们新建一个test.py文件,内容以下:数据库

#!usr/bin/env python3`
#-*- coding:utf-8 -*-

import os
ret = os.system("/usr/local/php7/bin/php /home/app/swoole_test.php") #请使用本身系统的绝对路径
print(ret)

而后咱们在终端执行:/usr/bin/python3 /home/app/test.py,注意:这里只是执行PHP文件,可是文件里的echo内容是不会在终端输出的,这时候就用到刚才新建的log.txt文件了。执行完Python文件后,咱们去log文件检查下,发现内容已经写入,因此使用Python是能够实现PHPcli模式的。┗|`O′|┛ 嗷~~
图片描述segmentfault

到这里就会有同窗疑惑了,你这使用Python实现了PHPcli模式,可是怎么经过web远程访问呢?这个时候就用到PHP的exec方法了,咱们知道PHP的exec方法和Python的os.system方法同样是能够执行命令行命令的,因此咱们能够新建一个test.php文件,内容以下:

<?php
$program="/usr/bin/python3 /home/app/nongyephp/test.py"; #注意使用绝对路径
echo "begin<br>";
(exec ($program));
echo "end<br>";
die;

而后咱们经过网页访问test.php文件。结果以下:
图片描述

而后去log文件检查,发现也写入日志了,因此这个方法是可行的!
作到这里内心美滋滋的,不过老以为好像哪里不对,终于终于意识到一个很傻逼的问题:既然PHP能够直接有命令行函数,为啥画蛇添足借助Python而后在用Python的函数呢?这不是脱了裤子放屁画蛇添足吗?
再大骂本身是傻逼N遍以后,我默默修改了test.php文件内容:

<?php
echo "begin<br>";
$program="/usr/local/php7/bin/php /home/app/nongyephp/swoole_test.php"; #注意使用绝对路径
(exec ($program));
echo "end<br>";
die;

在直接访问test.php文件,反馈结果和借助Python同样,这样就能够免去Python那一步,直接用PHPexec函数来执行PHP文件。

结尾

测试经过后发现这种方法是能够建立定时器而且经过web远程使用的,不过有个问题,若是用和我上述同样用网页模拟会发现网页刷新是要等test.php执行完才会结束,也就是说若是咱们把延时器的时间设成30分钟会要等待30分钟才会有反馈信息,这种方式确定行不通的,因此须要使用异步访问,好比使用web的ajax技术和其余异步技术,这里再也不赘述

尾巴

  • 以上只是我想到解决问题的想法和实施步骤,到了真正开发可能不会选择这种方式,由于没有通过性能测试,并且对于进程控制和线程控制并无多深刻的了解,因此之后作订单自动取消仍是会选择方法2的吧。
  • 上述方法其实彻底能够省掉Python那一步,我没有去掉的缘由是把个人实现经历写出来,由于我以为开发期间可能真的会遇到这种画蛇添足的方式,总之是要多思考,多看代码,找出能优化的方案,这里感受本身差得很远,共勉吧
相关文章
相关标签/搜索