PHP使用MySQL实现消息队列
消息队列常用在流量削峰(秒杀场景),异步通信等地方。
大体的结构如下:

类似于消费者和生产者的关系,首先生产者在消息队列未满的时候,才将生产的产品放进消息队列中;消费者在消息队列不为空的时候,才从消息队列中取出产品进行消费。出队的那个步骤常用的方法是一直轮询和定时操作。
这里举一个外卖送餐的案例:
有个生意很好的饭店,好到什么程度呢?一分钟有500人下单,这样的话,店家掌柜肯定处理不过来,于是,就先暂时不通知用户是够接单,先把所有的订单先存着,只告诉他们正在处理中,但是呢,还有一个问题,就是有一些是其他饭店专门来搞事的(眼红了),所以就要查看订单是否合法。
上面的情景可以这样实现:用户下单之后,后台会创建一个随机的order_id对应该订单;并且该订单的初始状态(status)为待处理(0);当商家查看该订单情况时,将status改为1,表示正在处理;当商家确认这个订单可以接受时,就将该订单的status改为2,表示成功接单。
首先在数据库中创建一个order_list订单表,表结构如下:
mysql> desc order_list;
+----------+------------+------+-----+----------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------+------+-----+----------+-------+
| order_id | int(11) | NO | PRI | NULL | |
| mobile | int(8) | NO | | 88888888 | |
| status | tinyint(1) | YES | | 0 | |
+----------+------------+------+-----+----------+-------+
3 rows in set (0.05 sec)
有两个PHP程序,分别是producer.php(用户、生产者); consumer.php(商家、消费者)
一旦有用户下单,就往order_list中添加一条数据,这里方便测试,于是执行下面的PHP程序,表示用户方(producer.php),每隔2秒下一次单;
<?php
$pdo=new PDO("mysql:host=localhost;dbname=test","root","root");
$stmt=$pdo->prepare("insert into order_list (order_id,mobile,status) values (?,?,?)");
while(1){
$order_id=rand(10000,99999);
$mobile=rand(11111111,99999999);
$stmt->execute(array($order_id,$mobile,0));
echo date("Y-m-d H:i:s",time())."添加了一条订单,订单号为{$order_id},手机号为{$mobile}\n";
sleep(2);
}
?>
用户提交订单后,剩下的事情就交给商家了,商家(consumer.php)生意太忙了,每4秒才能处理一个订单:
<?php
$pdo=new PDO("mysql:host=localhost;dbname=test","root","root");
$stmt=$pdo->prepare("update order_list set status=? where status=? limit 1");
$stmt_select=$pdo->prepare("select order_id from order_list where status=1");//正在处理的订单号
while(1){
$init=0;//初始status
$lock=1;//标记为正在处理
$success=2;//成功接单
//为了保证数据的一致性,处理订单之前,要先锁定一个订单,将其status由0改为1,然后才可处理
//处理完毕后,然后再将status从1改为2 $stmt->execute(array($lock,$init));//锁定要处理的订单
$stmt_select->execute();
$result=$stmt_select->fetch(PDO::FETCH_ASSOC);//查询正在处理的订单号
$order_id=$result['order_id'];
echo date("Y-m-d H:i:s")."准备处理订单,订单号为{$order_id}\n";
sleep(3);//处理3秒
$stmt->execute(array($success,$lock));
echo date("Y-m-d H:i:s")."订单处理完成,订单号为{$order_id}\n";
sleep(1);//休息1秒
}
?>
这样就使用MySQL实现了一个简单的消息队列,可以看一下如何使用Redis实现消息队列,与这个方法类似。需要注意的是,上面的代码其实有很大的问题,比如,如果涉及到并发,数据库中同时操作一条数据怎么办,这个时候,考虑的问题就多了。
PHP使用MySQL实现消息队列的更多相关文章
- mysql实现消息队列
mysql之消息队列 消息队列:在消息的传输过程中保存消息的容器. 消息队列管理器在将消息从它的源中继到它的目标时充当中间人.队列的主要目的是提供路由并保证消息的传递:如果发送消息时接收者不可用, ...
- php mysql 实现消息队列
最近遇到一个批量发送短信的需求,短信接口是第三方提供的.刚开始想到,获取到手机号之后,循环调用接口发送不就可以了吗? 但很快发现问题:当短信数量很大时,不仅耗时,而且成功率很低. 于是想到,用PHP和 ...
- PHP(Mysql/Redis)消息队列的介绍及应用场景案例--转载
郑重提示:本博客转载自好友博客,个人觉得写的很牛逼所以未经同意强行转载,原博客连接 http://www.cnblogs.com/wt645631686/p/8243438.html 欢迎访问 在进行 ...
- PHP和MySQL实现消息队列
最近遇到一个批量发送短信的需求,短信接口是第三方提供的.刚开始想到,获取到手机号之后,循环调用接口发送不就可以了吗? 但很快发现问题:当短信数量很大时,不仅耗时,而且成功率很低. 于是想到,用PHP和 ...
- PHP(Mysql/Redis)消息队列的介绍及应用场景案例
在进行网站设计的时候,有时候会遇到给用户大量发送短信,或者订单系统有大量的日志需要记录,还有做秒杀设计的时候,服务器无法承受这种瞬间的压力,无法正常处理,咱们怎么才能保证系统正常有效的运行呢?这时候我 ...
- mysql之消息队列
消息队列:在消息的传输过程中保存消息的容器. 消息队列管理器在将消息从它的源中继到它的目标时充当中间人.队列的主要目的是提供路由并保证消息的传递:如果发送消息时接收者不可用,消息队列会保留消息,直到可 ...
- PHP使用Redis实现消息队列
消息队列可以使用MySQL来实现,可以参考博客PHP使用MySQL实现消息队列,虽然用MySQL可以实现,但是一般不这么用,因为MySQL的数据都存在硬盘中,而从硬盘中对MySQL的操作,I/O花费的 ...
- springboot2.0+redis实现消息队列+redis做缓存+mysql
本博客仅供参考,本人实现没有问题. 1.环境 先安装redis.mysql 2.springboot2.0的项目搭建(请自行完成),本人是maven项目,因此只需配置,获取相应的jar包,配置贴出. ...
- 【翻译】DotNetMQ: 一个.NET版完整的消息队列系统
在一个大型的分布式系统中,消息队列是不可缺少的中间件,能很好的解决异步消息.应用解耦.均衡并发等问题.在.net中,偶然发现一个效率不错.安全可靠.功能齐全的消息组件,忍不住翻译过来,供大家快速预览. ...
随机推荐
- OutputStreamWriter与InputStreamReader(转换流)的编码解码
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStrea ...
- Scrapy运行流程
接下来的图表展现了Scrapy的架构,包括组件及在系统中发生的数据流的概览(绿色箭头所示). 下面对每个组件都做了简单介绍,并给出了详细内容的链接.数据流如下所描述. 来源于https://scrap ...
- UCML异常提示:无效URI
UCML异常提示界面,点击确定后UCML退出无法使用,原因见图二 图一: 图二:源码路径错误导致找不到路径出异常提示,在数据库中将数据update回正确路径即可解决该问题
- python3 练习题(多级菜单)
'''多级菜单需求:1.现有省/市/县3级结构,要求程序启动后,允许用户可依次选择进入各子菜单2.可在任意一级菜单返回上一级3.可以在任意一级菜单退出程序所需新知识点: 列表/字典'''menu = ...
- Bug 14143011 : ORA-19606: CANNOT COPY OR RESTORE TO SNAPSHOT CONTROL FILE
Bug 14143011 : ORA-19606: CANNOT COPY OR RESTORE TO SNAPSHOT CONTROL FILE [oracle@test]$ tail -f rma ...
- leetcode 338. Counting Bits,剑指offer二进制中1的个数
leetcode是求当前所有数的二进制中1的个数,剑指offer上是求某一个数二进制中1的个数 https://www.cnblogs.com/grandyang/p/5294255.html 第三种 ...
- pyspider爬一批文章保存到word中
最近一直在爬新闻,对于新闻爬取的套路还是比较熟悉的.一个群友发布了一个爬文章入word的任务,我果断接单,自我挑战一下,更何况完成任务还有赏金,哈哈. 任务大概是这样的,有一个文章列表[http:// ...
- PAT A1146 Topological Order (25 分)——拓扑排序,入度
This is a problem given in the Graduate Entrance Exam in 2018: Which of the following is NOT a topol ...
- Robust Real-time Object Detection学习
健壮实时对象检测(robust real-time object detection) 高检测率(high detection rates), 一种新的图像表示方法,叫做积分图(integral im ...
- C# 语法五 单例类、单例模式
1.优点 只有一个实例 2.缺点 a)这个实例不能随时释放掉,占用资源. b)每次使用,都要判断是否为空,增加消耗 3.适用场景 只能有一个实例的业务场景,例如:数据库连接对象(每次连接都是同一个连接 ...