PHP轻松实现延时操作
发布时间:2022-07-18 12:31 所属栏目:121 来源:互联网
导读:场景:在业务中有时会碰到延迟操作,如下单后半小时未支付则取消订单、下单后十五分钟未支付则发短信提醒等等。那这样的需求如何去实现呢。 实现方式 第一个简单的方式就是用一个后台进程死循环去查订单,根据下单时间去做不同的操作 第二种就是使用消息队列
场景:在业务中有时会碰到延迟操作,如下单后半小时未支付则取消订单、下单后十五分钟未支付则发短信提醒等等。那这样的需求如何去实现呢。 实现方式 第一个简单的方式就是用一个后台进程死循环去查订单,根据下单时间去做不同的操作 第二种就是使用消息队列的定时消息,下单之后发送定时消息,不同的定时队列去处理不同的逻辑 第三种可以使用框架提供的一些既有功能去做 实现代码 我们以订单创建15分钟后未支付,给用户发送邮件为场景进行学习 准备工作: 简单的订单表:order 各种需要的composer包 rabbitMq本地服务 开通阿里云RocketMq服务 第一种 比如使用阿里云的MQ服务,目前rocketMq与rabbitMq版本支持延迟消息,但是rabbit的延时消息收费太高了 这里先使用rocketMq的延迟消息去实现 需要开通阿里云的服务 消费逻辑 同样是在消费者中处理 启动生产一条消息 gaoz@nobodyMBP delay_mq_demo % php rocket_mq_handler_producer.php Send mq message success. msgId is:76CF2135696C3D4EAC698A9FA1E1879D, bodyMD5 is:63448B50AA7B8AF47B07AA7CE807E3D3 gaoz@nobodyMBP delay_mq_demo % 启动消费者慢慢等待 gaoz@nobodyMBP delay_mq_demo % php rocket_mq_handler_consumer.php No message, contine long polling!RequestId:5EF752583441411C74869BA9 No message, contine long polling!RequestId:5EF7525B3441411C74869FE2 No message, contine long polling!RequestId:5EF7525E3441411C7486A42C No message, contine long polling!RequestId:5EF752613441411C7486A7D9 consume finish, messages:send email to 95 success ...2020-06-27 12:08:05:update-success-orderId-8-userId-95 Array( [0] => 76CF2135696C3D4EAC698A9FA1E1879D-MCAxNTkzMjY2NzkxNDM5IDMwMDAwMCAzIDAgYmpzaGFyZTUtMDggNSAw) ack 这种方式有现有的服务可以使用,减少开发时间 第二种 代码逻辑很简单就直接死循环就行了 启动这个脚本进程,可以用supervisor配置 部分代码 //创建订单的逻辑/** * 随机创建订单 */$order = [ 'order_number' => mt_rand(100,10000).date("YmdHis"), 'user_id' => mt_rand(1, 100), 'order_amount' => mt_rand(100, 1000),]; /**@var $manager Illuminate\Database\Capsule\Manager **/ $conn = $manager;$insertResult = $conn::table("order") ->insert($order);print_r($insertResult); 延迟处理逻辑 while(true) { // 未支付订单列表 $orderList = $conn::table("order") ->where("created_time", '<=', date("Y-m-d H:i:s", strtotime("-15 minutes"))) ->where('sended_need_pay_notify', '=', 2) ->where('status', '=', 1) ->select(['user_id', 'id']) ->orderBy("id", 'asc') ->get(); $orderList = json_decode(json_encode($orderList), true); foreach ($orderList as $orderInfo) { sendEmail($orderInfo['user_id']); $conn::table('order') ->where('id', '=', $orderInfo['id']) ->update(['sended_need_pay_notify' => 1]); logs("update-success-orderId-". $orderInfo['id']."-userId-".$orderInfo['user_id']); } sleep(10);} 执行处理脚本 gaoz@nobodyMBP delay_mq_demo % php first_while_handler.php send email to 73 success ... 2020-06-24 11:37:36:update-success-orderId-3-userId-73 这种方式吧实现简单,但是不优雅,同时大批量订单产生也会遇到问题。 第三种 使用rabbitMq去实现 查阅文档没有找到rabbitMq支持延迟队列的原生功能,但是可以通过消息的ttl+死信队列实现 私信队列就是用来存放没有被消费或者消费失败等消息的队列 当设置消息的有效期内没有被消费消息就会被转发到死信队列 通过设置消息的有效期实现延时功能 // 生产者$exchange = 'order15min_notify_exchange'; $queue = 'order15minx_notify_queue';$dlxExchange = "dlx_order15min_exchange"; $dlxQueue = "dlx_order15min_queue"; $connection = new AMQPStreamConnection(getenv('RABBIT_HOST'), getenv('RABBIT_PORT'), getenv("RABBIT_USER"), getenv("RABBIT_PASS"), getenv("RABBIT_VHOST")); 第四种 使用laravel自带的Queue去实现 这里没有整理详细代码,后面更新出来。 (编辑:ASP站长网) |
相关内容
网友评论
推荐文章
热点阅读