消息队列可以使用MySQL来实现,可以参考博客PHP使用MySQL实现消息队列,虽然用MySQL可以实现,但是一般不这么用,因为MySQL的数据都存在硬盘中,而从硬盘中对MySQL的操作,I/O花费的代价很大,所以一般使用缓存来实现,因为缓存的数据是在内存中,访问内存的速度远快于访问硬盘的速度。另一方面,Redis有list类型的数据结构,非常适合做消息队列。

这里举一个很简单的秒杀例子:秒杀的名额只有5个,即消息队列的长度为5,名额已经满了之后,通知后来的人已经秒杀结束。然后后台会从消息队列中读取数据,然后将数据存到数据库中。因为消息队列长度只有5个,而且秒杀的那短短1,2秒并没有直接操作数据库,所以对于数据库来说,并没有什么压力。

先看一下数据库表(seckill)的结构:

mysql> desc seckill;
+----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| order_id | int(11) | NO | | NULL | |
| mobile | int(8) | YES | | 8888888 | |
+----------+---------+------+-----+---------+----------------+
3 rows in set (0.11 sec)

  然后是进行秒杀的用户程序(user.php),为了模拟,这里使用for循环来实现在短时间内发起大量的请求,但是要知道这是不准确的。

<?php
$redis=new Redis();
$redis->connect("127.0.0.1",6379); $key="seckill";
for($i=0;$i<10;$i++){
$order_id=rand(100000,999999);
$mobile=rand(11111111,99999999);
$value=$order_id."#".$mobile;//连接之后作为值
if($redis->llen("seckill") <5 ){
echo "秒杀成功,订单号为$order_id, 手机号为$mobile\n";
$redis->lpush($key,$value);
} else {
echo "秒杀已经结束\n";
}
}
?>

  运行结果:

[root@localhost ~]# php user.php
秒杀成功,订单号为643275, 手机号为50104929
秒杀成功,订单号为393012, 手机号为31213041
秒杀成功,订单号为994790, 手机号为23107569
秒杀成功,订单号为186135, 手机号为36549273
秒杀成功,订单号为821972, 手机号为11217760
秒杀已经结束
秒杀已经结束
秒杀已经结束
秒杀已经结束
秒杀已经结束

  

然后是后台程序将redis中订单读出,处理后存进数据库。

<?php
$redis=new Redis();
$redis->connect("127.0.0.1",6379);
$pdo=new PDO("mysql:host=localhost;dbname=test","root","root");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt=$pdo->prepare("insert into seckill(id,order_id,mobile) values(?,?,?)");
$key="seckill"; while($redis->llen($key)){
//因为消息队列中添加消息是使用lpush,所以这里使用rpop
$order=$redis->rpop($key);
list($order_id,$mobile)=explode("#",$order);
echo "正在处理订单$order_id\t";
try{
$res=$stmt->execute(array(null,$order_id,$mobile));
if(!$res){
throw new PDOException("wrong");
}
} catch (PDOException $e){
echo $e->getMessage();
echo "订单处理失败\n";
$redis->rpush($key,$order_id."#".$mobile);//将数据恢复达到队列中
continue;
}
echo "订单处理完成\n";
}
?>

  运行:

[root@localhost ~]# php consumer.php
正在处理订单643275 订单处理完成
正在处理订单393012 订单处理完成
正在处理订单994790 订单处理完成
正在处理订单186135 订单处理完成
正在处理订单821972 订单处理完成

  查看数据库:

mysql> select * from seckill;
+----+----------+----------+
| id | order_id | mobile |
+----+----------+----------+
| 1 | 643275 | 50104929 |
| 2 | 393012 | 31213041 |
| 3 | 994790 | 23107569 |
| 4 | 186135 | 36549273 |
| 5 | 821972 | 11217760 |
+----+----------+----------+
5 rows in set (0.00 sec)

  

PHP使用Redis实现消息队列的更多相关文章

  1. Redis 做消息队列

    一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式.利用redis这两种场景的消息队列都能够实现.定义: 生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列, ...

  2. Redis作为消息队列服务场景应用案例

    NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例   一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更 ...

  3. redis resque消息队列

    Resque 目前正在学习使用resque .resque-scheduler来发布异步任务和定时任务,为了方便以后查阅,所以记录一下. resque和resque-scheduler其优点在于功能比 ...

  4. 【springboot】【redis】springboot+redis实现发布订阅功能,实现redis的消息队列的功能

    springboot+redis实现发布订阅功能,实现redis的消息队列的功能 参考:https://www.cnblogs.com/cx987514451/p/9529611.html 思考一个问 ...

  5. 【Redis】php+redis实现消息队列

    在项目中使用消息队列一般是有如下几个原因: 把瞬间服务器的请求处理换成异步处理,缓解服务器的压力 实现数据顺序排列获取 redis实现消息队列步骤如下: 1).redis函数rpush,lpop 2) ...

  6. Lumen开发:结合Redis实现消息队列(1)

    1.简介 Lumen队列服务为各种不同的后台队列提供了统一的API.队列允许你推迟耗时任务(例如发送邮件)的执行,从而大幅提高web请求速度. 1.1 配置 .env文件的QUEUE_DRIVER选项 ...

  7. Redis除了做缓存--Redis做消息队列/Redis做分布式锁/Redis做接口限流

    1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...

  8. sping+redis实现消息队列的乱码问题

    使用spring支持redis实现消息队列,参考官方样例:https://spring.io/guides/gs/messaging-redis/ 实现后在运行过程中发现消费者在接收消息时会出现乱码的 ...

  9. 程序员过关斩将--redis做消息队列,香吗?

    Redis消息队列 在程序员这个圈子打拼了太多年,见过太多的程序员使用redis,其中一部分喜欢把redis做缓存(cache)使用,其中最典型的当属存储用户session,除此之外,把redis作为 ...

  10. NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例

    一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器 ...

随机推荐

  1. St_geometry 初始用

    数据准备 点表 CREATE TABLE point_stgeom tablespace UBOSS_STS_WAREHOUSE as select car_number, longid, latid ...

  2. JS进阶1

    一 表格案例 二 onchange事件(二级联动) 三 onmouse事件 四 事件委派 五  作用域链 一表格案例 <!DOCTYPE html> <html lang=" ...

  3. socket.io+angular.js+express.js做个聊天应用(三)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/www19940501a/article/details/27590611 接着前面博客文章socke ...

  4. D - C Looooops POJ - 2115 欧几里德拓展

    题意:就是看看for(; ;)多久停止. 最让我蛋疼的是1L和1LL的区别!让我足足wa了12发! 1L 是long类型的, 1LL为long long类型的! 思路: 这就是欧几里德扩展的标准式子了 ...

  5. redis php扩展及基本命令

    linux 安装php mysql redis memchache 等工具 用 OneinStack 安装步骤 注意 如果有单独数据盘,建议您先挂载数据盘,建议将网站内容.数据库放在数据盘中.如何挂载 ...

  6. ucml JS调用其它页面上的服务端方法

    var params = { _bpoName: "BPO_KH_ED" + "Service", //BPO的名字(拥有那个服务端函数的BPO) _metho ...

  7. Java相关框架资料及其基础资料、进阶资料、测试资料之分享

    个人说明:只为分享,不为其他,愿所有的程序员们在编程的世界自由翱翔吧! 在我看来,只有不断实战,不断学习,不断积累,不断归纳总结,形成自己的核心竞争力,方能在未来竞争中脱颖而出! 程序员谨记!重要的事 ...

  8. python代码在linux服务器一般的开头

    #!/usr/bin/env python # -*- coding: utf- -*- 只做备份

  9. Photoshop 基础七 位图 矢量图 栅格化

    矢量图(CorelDraw)不是像素组成的,放大不会失真,体积小,颜色比较单一.由直线.曲线构成,画一些直线.曲线.多边形.图标. 位图(Photoshop画的就是位图),又像素组成,放大失真,放的越 ...

  10. ubuntu (14.04) 卸载 gnome 系统桌面

    1.将ubuntu 的图形界面切到命令行界面. 2.卸掉 gnome-shell 的主程序 sudo apt-get remove gnome-shell 3.卸载 gnome sudo apt-ge ...