PHP使用Redis实现消息队列
2018-01-14 21:02
1266 查看
消息队列可以使用MySQL来实现,可以参考博客PHP使用MySQL实现消息队列,虽然用MySQL可以实现,但是一般不这么用,因为MySQL的数据都存在硬盘中,而从硬盘中对MySQL的操作,I/O花费的代价很大,所以一般使用缓存来实现,因为缓存的数据是在内存中,访问内存的速度远快于访问硬盘的速度。另一方面,Redis有list类型的数据结构,非常适合做消息队列。
这里举一个很简单的秒杀例子:秒杀的名额只有5个,即消息队列的长度为5,名额已经满了之后,通知后来的人已经秒杀结束。然后后台会从消息队列中读取数据,然后将数据存到数据库中。因为消息队列长度只有5个,而且秒杀的那短短1,2秒并没有直接操作数据库,所以对于数据库来说,并没有什么压力。
先看一下数据库表(seckill)的结构:
然后是进行秒杀的用户程序(user.php),为了模拟,这里使用for循环来实现在短时间内发起大量的请求,但是要知道这是不准确的。
运行结果:
然后是后台程序将redis中订单读出,处理后存进数据库。
运行:
查看数据库:
这里举一个很简单的秒杀例子:秒杀的名额只有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使用php-resque库配合Redis实现MQ消息队列的教程
- PHP使用php-resque库配合Redis实现MQ消息队列的教程
- PHP中利用redis实现消息队列处理高并发请求--简洁代码实现效果
- PHP使用redis消息队列发布微博的方法示例
- redis实现简单的消息队列(php)
- Java使用Redis实现消息队列
- Redis使用总结(3):实现简单的消息队列
- PHP下使用Redis消息队列发布微博
- php实现redis消息队列将数据保存到mysql
- 【Redis】php+redis实现消息队列
- 使用Redis实现异步消息队列
- PHP基于Redis消息队列实现发布微博的方法
- 使用 PHP 消息队列实现 Android 与 Web 通信
- PHP消息队列实现及应用:流量削峰案列(Redis的List类型实现秒杀)
- java redis使用之利用jedis实现redis消息队列
- php 实现 redis 队列,等待有新消息入列
- 基于PHP使用rabbitmq实现消息队列
- java redis使用之利用jedis实现redis消息队列
- php+redis消息队列抢购实现
- 使用jedis实现Redis消息队列(MQ)的发布(publish)和消息监听(subscribe)