使用Tp5.1处理订单过期
- 首先在redis配置文件(redis.conf)配置过期时间通知。
- 在项目命令行定义文件夹下创建php文件(我这里为Test.php),并写入需要执行的代码逻辑。
- 写入要处理的代码逻辑。
<?php
namespace app\command;
ini_set('default_socket_timeout', -1);
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\common\controller\MyRedis;
use think\Db
class Test extends Command
{
protected function configure()
{
// 指令配置
$this->setName('test')
->setDescription('测试订单过期处理');
// 设置参数
}
protected function execute(Input $input, Output $output)
{
// 指令输出
$output->writeln('test');
$redis = new MyRedis(); //其他地方找的redis操作类
$redis->setOption();
$redis->psubscribe(array('__keyevent@0__:expired'), function ($redis, $pattern, $chan, $msg) {
$type_info = explode(':', $msg);
$order_type = $type_info[0];
$order_id = $type_info[1];
if ($order_type == 'order_exp') {
$res1 = Db::name('order_wang')->where([['id', '=', $order_id], ['status', '=', 0]])->find();
if ($res1) {
$res2 = Db::name('order_wang')->where([['id', '=', $order_id]])->update(['status' => 3]);
if ($res2) {
echo 'order:订单处理成功\n';
$redis->del($msg);
} else {
echo 'order:订单处理失败\n';
}
}
}
});
}
}
- 创建下单逻辑并将订单ID存入Redis中,并写入过期时间。
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use app\common\controller\MyRedis;
class Order extends Controller
{
private $id = 0;
private $redis = null;
//
public function initialize()
{
$this->id = input('id');
$goods_num = Db::name('goods_wang')->value('goods_number');
$this->redis = new \Redis();
$this->redis->connect('127.0.0.1', 6379);
$this->redis->del('goods_store');
$res = $this->redis->llen('goods_store');
$content = $goods_num - $res;
for ($i = 0; $i < $content; $i++) {
$this->redis->lPush('goods_store', 1);
}
$this->redis->llen('goods_store');
}
public function CreateOrder(Request $request)
{
$id = input('id', null);
$redis = new MyRedis();
if (!$id) {
$this->result('', 201, '商品ID不能为空', 'json');
}
$count = $this->redis->rpop('goods_store');
if (!$count) {
$this->result('', 201, '商品已售罄', 'json');
}
$goods_info = Db::name('goods_wang')->where('id', $id)->find();
if (!$goods_info) {
$this->result('', 201, '商品不存在', 'json');
}
$data = [
'order_no' => $this->build_order_no(),
'goods_name' => $goods_info['goods_name'],
'number' => $count,
'create_time' => time(),
];
Db::startTrans();
$res1 = Db::name('order_wang')->insertGetId($data);
$res2 = Db::name('goods_wang')->where('id', $id)->setDec('goods_number', $count);
$key = 'order_exp:' . $res1;//拼接订单类型及订单号
$redis->setex($key, 5, 'redis延迟任务'); // 设置订单过期时间为5秒
if ($res1 && $res2) {
Db::commit();
$this->result(['order_no' => $data['order_no']], 200, '购买成功', 'json');
}
Db::rollback();
$this->result('', 201, '购买失败', 'json');
}
function build_order_no()
{
return date('ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
}
- 运行测试。
- 使用supervisor将php think test命令加入守护命令,并将supervisor设置开机自启
- 安装supervisor…(此处省略)并在supervisor配置文件supervisord.conf末尾有这样一句话。
[include]
files = supervisord.d/*.conf
- 在supervisord.d下,新建自己的配置文件 test.conf,其内容如下:
[program:test]
;这里写入自己的执行php命令及项目路径
command=/usr/local/php7/php /wwwroot/Tp/tp5.1/think test
process_name=%(program_name)s_%(process_num)02d
;numprocs=5
autostart=true
autorestart=true
startsecs=1 ;程序重启时候停留在runing状态的秒数
startretries=10 ;启动失败时的最多重试次数
redirect_stderr=true
user=root
stdout_logfile=/etc/supervisord.d/order_ex.log
[supervisord]
[supervisorctl]
8.特别注意:每次有修改自定义代码命令及新增,都需要重新加载supervisor。