PHP消息队列实现及应用详解【队列处理订单系统和配送系统】
发布:smiling 来源: PHP粉丝网 添加日期:2021-11-22 23:22:28 浏览: 评论:0
这篇文章主要介绍了PHP消息队列实现及应用,结合实例形式详细分析了php消息队列的概念、原理及队列处理订单系统和配送系统案例,需要的朋友可以参考下。
本文实例讲述了PHP消息队列实现及应用,分享给大家供大家参考,具体如下:
在互联网项目开发者经常会遇到『给用户群发短信』、『订单系统有大量的日志需要记录』或者在秒杀业务的时候服务器无法承受瞬间并发的压力。
这种情况下,我们怎么保证系统正常有效的运行呢?
这个时候,我们可以引入一个叫『消息队列』的概念来解决上面的需求。
消息队列的概念、原理和场景
在高并发的时候,程序往往无法做到及时的处理。我们引入一个中间的系统,来进行分流和减压。
所以从本质上讲:消息队列就是一个队列结构的中间件。也就是说,你把消息和内容放入这个容器之后就可以直接返回,不用等它后期处理的结果。另外会有一个程序,读取这些数据并按照顺序处理。
1、队列结构的中间件
2、消息放入后,不必立即处理
3、由订阅者/消费者按顺序处理
也就是说:当遇到一个比较大或者耗时比较长的环节的时候,而同时你的业务又不需要立即知道这个环节的结果,使用消息队列是好的选择。
核心结构如下面:
消息队列 适用场景
一、数据需要冗余的时候
比如订单系统中,后续需要进行数据的转换和记录。消息队列可以把这些数据持久化的存储在队列中,然后由订单后期处理程序进行处理,处理完成之后再把这条记录从队列中删除。
二、系统的解耦
消息队列解决了2套系统之间深度耦合的问题。
使用消息队列后,入队的系统和出队的系统没有直接的关系。
入队系统和出队系统,其中一个崩溃之后不会影响另外一个的正常运行。
三、流量削峰
就是秒杀和抢购的时候,会出现明显的流量剧增,对服务器的压力非常大。
实际项目开发中,配合缓存来使用消息队列,一种很好的方案。
四、异步通信
消息队列本身就实现了程序的异步操作,因此只要适合于异步的场景都可以使用消息队列
五、扩展性
比如订单系统,订单入队之后,后期或许还有财务系统处理,但是如果还要加一个配货系统。
只需要让这个配货系统 订阅这个 消息队列 即可。
六、排序保证
在有些场景下,数据的处理顺序是非常重要的,队列本身就可以做成单线程的单进单出的系统。
从而有效的保证数据按照顺序进行处理。
常见 队列实现 的优缺点
队列介质:
Mysql:可靠性高、易实现、速度慢
Redis:速度快,单条大消息包时效率低
消息系统:专业性强、可靠,学习成本高(比如:RabbtiMQ)
消息处理的触发机制:
死循环方式读取:易实现,故障时无法及时恢复;
定时任务:压力均分,有处理量上限。(最大的缺陷:定位任务时间的间隔和处理的数据需要精准把握,不能上一个任务还没有处理完成,下一个认为就已经启动了)
守护进程:类似于PHP-FPM和PHP-CGI,需要shell知识
解耦案列:队列处理 订单系统和配送系统
我们在前面了解过消息队列的使用场景
这里,我们要来处理其中一个场景:系统的解耦。
在电商项目中,当客户提交了一个订单之后,客户在个人中心可以看到订单处于配送中。
这个时候就要参与进来一个系统,叫做『配送系统』。如果我们在做架构的时候,把订单系统和配送系统设计在一起的话就会出现一些问题:订单系统的压力比较大,但是配送系统没有必要对这些压力做及时的反应;我们不需要订单系统出现故障之后导致配送系统故障。
所以我们需要把这2个系统分开,通过一个中间的队列表来实现这2个系统的沟通。
如下图架构:
具体到我们的程序代码大致逻辑如下图:
大致流程:order.php来接收用户订单,生成订单号并对订单进行处理(订单系统);在订单系统会把配送系统所需要的数据放入队列表中;我们的配送系统goods.php会有个定时脚本每分钟执行一次,处理队列表中的数据。
简单设计队列表order_queue:
- CREATE TABLE `order_queue` (
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
- `order_id` int(11) unsigned NOT NULL COMMENT '订单ID(从订单系统来的)',
- `user_info` varchar(255) NOT NULL DEFAULT '' COMMENT '可以是用户手机号/用户id等(这里只是演示)',
- `created_at` datetime NOT NULL COMMENT '订单创建时间',
- `updated_at` datetime NOT NULL COMMENT '本记录最后处理完成时间',
- `status` tinyint(2) NOT NULL COMMENT '0未处理,1已处理,2处理中',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
mysql订单队列
前面我们已经分析清楚了逻辑,剩下的就是代码实现了。
注意:我这里只是演示代码,单纯为了展示实现过程。
1、接收订单,处理订单order.php
- <?php
- // 这个文件是用来接收用户的订单信息 并写入队列的一个文件
- if(!emptyempty($_GET['user_info'])){
- // 验证 过滤 接收的数据
- // todo...
- // 这里是应该首先是订单中心的处理流程
- // 因为订单系统是一套单独的系统 这里就不编写这个系统了
- // todo...
- $order_id = rand(100000,99999); // 正常的订单号从 订单系统来,我们这里只是演示
- // 把配送系统需要的订单数据存入队列表中
- $insert_data = array(
- 'order_id'=>$order_id,
- 'user_info'=>$_GET['user_info'],
- 'created_at'=>date('Y-m-d H:i:s',time()),
- 'status'=>0
- );
- // 把上面的数据 插入到order_queue表中
- // insert into order_queue
- }
2、配送系统goods.php
- <?php
- // 这个文件主要是配送系统处理队列表中的订单并进行标记的文件
- //分析:
- //第一步:先把要处理的记录更新为『等待处理』
- //第二步:选择刚刚标记为『等待处理』的记录,然后进行配送系统的处理
- //第三步:把上面前面处理过的程序标记『已完成』
- /////////////////////这里很重要,你一定要明白哦//////////////////////////////////////////////
- //疑问:为什么不直接处理最后更新为『已完成』,多了先标记为『等待处理』?
- //这是因为配送系统很可能不是及时完成的,它中间会有一段处理的时间,如果还在处理中有其他程序来进行读取和操作,就冲突了。
- //这样设计其实也是一个锁的机制
- //1、
- $waiting = array('status'=>0);
- $lock = array('status'=>2);
- //把状态为0的记录标记为2,每次更新3条(具体每次几条看情况)
- $sql = "update order_queue set status=2 where status=0 limit 3";
- //2、
- if(上面update成功){
- // 选择出要处理订单内容
- // select * from order_queue where status = 2;
- // 然后由配货系统进行处理
- // todo...
- //3、处理完成把订单状态更新为已完成
- $success = array(
- 'status'=>1,
- 'updated_at'=>date('Y-m-d H:i:s',time())
- );
- }else{
- echo 'All Finished';
- }
3、linux服务器 定时任务
写个shell脚本:goods.sh
- #!/bin/bash
- date "+%G-%m-%d %H:%M:%S"
- cd /var/www/
- php goods.php
这个脚本就是去执行orders.php这个程序的。
在linux服务器部署定时任务:
- crontab -e
- */1 * * * * /var/www/goods.sh >> /var/www/goods_shell.log 2>$1
每分钟执行一次goods.sh文件,并记录日志到goods_shell.log文件(在对应目录新建该文件)
Tags: PHP消息队列 php队列处理订单
相关文章
- ·PHP memcache实现消息队列实例(2014-08-27)
- ·PHP和RabbitMQ实现消息队列的完整代码(2020-02-04)
- ·PHP+memcache实现消息队列案例分享(2021-01-10)
- ·PHP消息队列用法实例分析(2021-07-09)
- ·PHP+RabbitMQ实现消息队列的完整代码(2021-11-13)
- ·PHP使用ActiveMQ实现消息队列的方法详解(2021-11-24)
- ·php+redis实现消息队列功能示例(2021-12-19)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)