消息队列常用在流量削峰(秒杀场景),异步通信等地方。

大体的结构如下:

  类似于消费者和生产者的关系,首先生产者在消息队列未满的时候,才将生产的产品放进消息队列中;消费者在消息队列不为空的时候,才从消息队列中取出产品进行消费。出队的那个步骤常用的方法是一直轮询和定时操作。

这里举一个外卖送餐的案例:

  有个生意很好的饭店,好到什么程度呢?一分钟有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实现消息队列的更多相关文章

  1. mysql实现消息队列

    mysql之消息队列   消息队列:在消息的传输过程中保存消息的容器. 消息队列管理器在将消息从它的源中继到它的目标时充当中间人.队列的主要目的是提供路由并保证消息的传递:如果发送消息时接收者不可用, ...

  2. php mysql 实现消息队列

    最近遇到一个批量发送短信的需求,短信接口是第三方提供的.刚开始想到,获取到手机号之后,循环调用接口发送不就可以了吗? 但很快发现问题:当短信数量很大时,不仅耗时,而且成功率很低. 于是想到,用PHP和 ...

  3. PHP(Mysql/Redis)消息队列的介绍及应用场景案例--转载

    郑重提示:本博客转载自好友博客,个人觉得写的很牛逼所以未经同意强行转载,原博客连接 http://www.cnblogs.com/wt645631686/p/8243438.html 欢迎访问 在进行 ...

  4. PHP和MySQL实现消息队列

    最近遇到一个批量发送短信的需求,短信接口是第三方提供的.刚开始想到,获取到手机号之后,循环调用接口发送不就可以了吗? 但很快发现问题:当短信数量很大时,不仅耗时,而且成功率很低. 于是想到,用PHP和 ...

  5. PHP(Mysql/Redis)消息队列的介绍及应用场景案例

    在进行网站设计的时候,有时候会遇到给用户大量发送短信,或者订单系统有大量的日志需要记录,还有做秒杀设计的时候,服务器无法承受这种瞬间的压力,无法正常处理,咱们怎么才能保证系统正常有效的运行呢?这时候我 ...

  6. mysql之消息队列

    消息队列:在消息的传输过程中保存消息的容器. 消息队列管理器在将消息从它的源中继到它的目标时充当中间人.队列的主要目的是提供路由并保证消息的传递:如果发送消息时接收者不可用,消息队列会保留消息,直到可 ...

  7. PHP使用Redis实现消息队列

    消息队列可以使用MySQL来实现,可以参考博客PHP使用MySQL实现消息队列,虽然用MySQL可以实现,但是一般不这么用,因为MySQL的数据都存在硬盘中,而从硬盘中对MySQL的操作,I/O花费的 ...

  8. springboot2.0+redis实现消息队列+redis做缓存+mysql

    本博客仅供参考,本人实现没有问题. 1.环境 先安装redis.mysql 2.springboot2.0的项目搭建(请自行完成),本人是maven项目,因此只需配置,获取相应的jar包,配置贴出. ...

  9. 【翻译】DotNetMQ: 一个.NET版完整的消息队列系统

    在一个大型的分布式系统中,消息队列是不可缺少的中间件,能很好的解决异步消息.应用解耦.均衡并发等问题.在.net中,偶然发现一个效率不错.安全可靠.功能齐全的消息组件,忍不住翻译过来,供大家快速预览. ...

随机推荐

  1. zip 的 压缩与解压

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/xiananliu/article/details/23993481 zip格式是开源的相比rar格式 ...

  2. Java 浅拷贝,深拷贝

         从Java 强引用.软引用,弱引用http://blog.csdn.net/jltxgcy/article/details/35558465一文中,我们看到把一个对象赋值给另一个对象,本质上 ...

  3. VCS双机+oracle 11gR2+ASM主机名修改

    ----------------------------------------------------------------------------VCS修改主机名---------------- ...

  4. Jenkins持续集成之小试牛刀

    关于Jenkins的安装,大家可以参考我的这两篇文章: Ubuntu16.04环境安装jenkins docker安装jenkins及其相关问题解决 之前没有好好研究过Jenkins,只是简单学会怎么 ...

  5. shell编程之转义和引用

    shell中有两类字符,一类是普通字符,在Shell中除了本身的字面意思外没有其他特殊意义,即普通纯文本:另一类即元字符,是Shell的保留字符,在Shell中有着特殊的含义. 一.转义 转义是指使用 ...

  6. mysql分表操作

    一般分表操作有垂直拆分和水平拆分.顾名思义. 1.  垂直拆分是指,这个表的列,即字段,要拆分成两个或多个表. 这个应用场景比如:这个表字段,几个都是int.datetime等,有那么一个是text类 ...

  7. HSF源码阅读

    HSF各组成之间的关系 1 服务提供者注册与发布 <bean id="hsfTestService" class="com.test.service.impl.Hs ...

  8. LOJ2687 BOI2013 Vim 线头DP

    传送门 多图警告!!! 一种很新奇的\(DP\),全网似乎只有一两篇题解-- 首先,序列中的一段\(e\)等价于在跳的过程中这一段\(e\)之后的一个字符必须要经过,并且在最后的答案中加上$2 \ti ...

  9. 从angularjs传递参数至Web API

    昨天分享的博文<angularjs呼叫Web API>http://www.cnblogs.com/insus/p/7772022.html,只是从Entity获取数据,没有进行参数POS ...

  10. WPF 滚动文字控件MarqueeControl

    原文:WPF 滚动文字控件MarqueeControl WPF使用的滚动文字控件,支持上下左右滚动方式,支持设置滚动速度 XAML部分: <UserControl x:Class="U ...