PHP消息队列实现及应用详解_第1页
PHP消息队列实现及应用详解_第2页
PHP消息队列实现及应用详解_第3页
PHP消息队列实现及应用详解_第4页
PHP消息队列实现及应用详解_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第PHP消息队列实现及应用详解本文实例讲述了PHP消息队列实现及应用。分享给大家供大家参考,具体如下:

在互联网项目开发者经常会遇到『给用户群发短信』、『订单系统有大量的日志需要记录』或者在秒杀业务的时候服务器无法承受瞬间并发的压力。

这种情况下,我们怎么保证系统正常有效的运行呢?

这个时候,我们可以引入一个叫『消息队列』的概念来解决上面的需求。

消息队列的概念、原理和场景

在高并发的时候,程序往往无法做到及时的处理。我们引入一个中间的系统,来进行分流和减压。

所以从本质上讲:消息队列就是一个队列结构的中间件。也就是说,你把消息和内容放入这个容器之后就可以直接返回,不用等它后期处理的结果。另外会有一个程序,读取这些数据并按照顺序处理。

1、队列结构的中间件

2、消息放入后,不必立即处理

3、由订阅者/消费者按顺序处理

也就是说:当遇到一个比较大或者耗时比较长的环节的时候,而同时你的业务又不需要立即知道这个环节的结果,使用消息队列是好的选择。

核心结构如下面:

消息队列适用场景

一、数据需要冗余的时候

比如订单系统中,后续需要进行数据的转换和记录。消息队列可以把这些数据持久化的存储在队列中,然后由订单后期处理程序进行处理,处理完成之后再把这条记录从队列中删除。

二、系统的解耦

消息队列解决了2套系统之间深度耦合的问题。

使用消息队列后,入队的系统和出队的系统没有直接的关系。

入队系统和出队系统,其中一个崩溃之后不会影响另外一个的正常运行。

三、流量削峰

就是秒杀和抢购的时候,会出现明显的流量剧增,对服务器的压力非常大。

实际项目开发中,配合缓存来使用消息队列,一种很好的方案。

四、异步通信

消息队列本身就实现了程序的异步操作,因此只要适合于异步的场景都可以使用消息队列

五、扩展性

比如订单系统,订单入队之后,后期或许还有财务系统处理,但是如果还要加一个配货系统。

只需要让这个配货系统订阅这个消息队列即可。

六、排序保证

在有些场景下,数据的处理顺序是非常重要的,队列本身就可以做成单线程的单进单出的系统。

从而有效的保证数据按照顺序进行处理。

常见队列实现的优缺点

队列介质:

Mysql:可靠性高、易实现、速度慢

Redis:速度快,单条大消息包时效率低

消息系统:专业性强、可靠,学习成本高(比如:RabbtiMQ)

消息处理的触发机制:

死循环方式读取:易实现,故障时无法及时恢复;

定时任务:压力均分,有处理量上限。(最大的缺陷:定位任务时间的间隔和处理的数据需要精准把握,不能上一个任务还没有处理完成,下一个认为就已经启动了)

守护进程:类似于PHP-FPM和PHP-CGI,需要shell知识

解耦案列:队列处理订单系统和配送系统

我们在前面了解过消息队列的使用场景

这里,我们要来处理其中一个场景:系统的解耦。

在电商项目中,当客户提交了一个订单之后,客户在个人中心可以看到订单处于配送中。

这个时候就要参与进来一个系统,叫做『配送系统』。如果我们在做架构的时候,把订单系统和配送系统设计在一起的话就会出现一些问题:订单系统的压力比较大,但是配送系统没有必要对这些压力做及时的反应;我们不需要订单系统出现故障之后导致配送系统故障。

所以我们需要把这2个系统分开,通过一个中间的队列表来实现这2个系统的沟通。

如下图架构:

具体到我们的程序代码大致逻辑如下图:

大致流程:order.php来接收用户订单,生成订单号并对订单进行处理(订单系统);在订单系统会把配送系统所需要的数据放入队列表中;我们的配送系统goods.php会有个定时脚本每分钟执行一次,处理队列表中的数据。

简单设计队列表order_queue:

CREATETABLE`order_queue`(

`id`int(11)unsignedNOTNULLAUTO_INCREMENT,

`order_id`int(11)unsignedNOTNULLCOMMENT'订单ID(从订单系统来的)',

`user_info`varchar(255)NOTNULLDEFAULT''COMMENT'可以是用户手机号/用户id等(这里只是演示)',

`created_at`datetimeNOTNULLCOMMENT'订单创建时间',

`updated_at`datetimeNOTNULLCOMMENT'本记录最后处理完成时间',

`status`tinyint(2)NOTNULLCOMMENT'0未处理,1已处理,2处理中',

PRIMARYKEY(`id`)

)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;

mysql订单队列

前面我们已经分析清楚了逻辑,剩下的就是代码实现了。

注意:我这里只是演示代码,单纯为了展示实现过程。

1、接收订单,处理订单order.php

//这个文件是用来接收用户的订单信息并写入队列的一个文件

if(!empty($_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-dH:i:s',time()),

'status'=0

//把上面的数据插入到order_queue表中

//insertintoorder_queue

2、配送系统goods.php

//这个文件主要是配送系统处理队列表中的订单并进行标记的文件

//分析:

//第一步:先把要处理的记录更新为『等待处理』

//第二步:选择刚刚标记为『等待处理』的记录,然后进行配送系统的处理

//第三步:把上面前面处理过的程序标记『已完成』

/////////////////////这里很重要,你一定要明白哦//////////////////////////////////////////////

//疑问:为什么不直接处理最后更新为『已完成』,多了先标记为『等待处理』?

//这是因为配送系统很可能不是及时完成的,它中间会有一段处理的时间,如果还在处理中有其他程序来进行读取和操作,就冲突了。

//这样设计其实也是一个锁的机制

$waiting=array('status'=

$lock=array('status'=

//把状态为0的记录标记为2,每次更新3条(具体每次几条看情况)

$sql="updateorder_queuesetstatus=2wherestatus=0limit3";

if(上面update成功){

//选择出要处理订单内容

//select*fromorder_queuewherestatus=2;

//然后由配货系统进行处理

//todo...

//3、处理完成把订单状态更新为已完成

$success=array(

'status'=1,

'updated_at'=date('Y-m-dH:i:s',time())

}else{

echo'AllFinished';

3、linux服务器定时任务

写个shell脚本:goods.sh

#!/bin/bash

date"+%G-%m-%d%H:%M:%S"

cd/var/www/

phpgoods.php

这个脚本就是去执行orders.php这个程序的。

在linux服务器部署定时任务:

crontab-e

*/1****/var/www/goods.sh/var/www/goods_shell.log2$1

每分钟执行一次goods

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论