PHP 利用redis List队列简单实现秒杀功能
一 生产者producer部分
--------------------------------producer 部分注释------------------------------------------------------------
用户在页面请求之后, 获取到用户uid , 跳转到这个加入队列的方法 (这里直接在producer中模拟了多个uid)
在方法内部判断redis队列长度是否已经达到要求, 如果没有超出, 则执行加入队列的操作 (这里为了简洁,没有封装成方法)
注: producer.php没有进行数据库的操作,只有接受uid和其他值的操作, 数据库操作一律放在消费者consumer.php中
--------------------------------producer 注释结束-----------------------------------------------------------------------
生产者代码 producer.php:
- <?php
- //连接redis数据库
- $redis = new Redis();
- $redis->connect('127.0.0.1',6379);
- $redis_name = 'secKill3';
- //模拟100人请求秒杀(高压力)
- for ($i = 0; $i < 100; $i++) {
- $uid = rand(10000000, 99999999);
- //获取当前队列已经拥有的数量,如果人数少于十,则加入这个队列
- $num = 10;
- if ($redis->lLen($redis_name) < $num) {
- $redis->rPush($redis_name, $uid);
- echo $uid . "秒杀成功"."<br>";
- } else {
- //如果当前队列人数已经达到10人,则返回秒杀已完成
- echo "秒杀已结束<br>";
- }
- }
- //关闭redis连接
- $redis->close();
注: 执行完producer.php文件,本地redis数据库第0号数据库中应该有一个键名为"secKill3"的List队列,像这样
二 消费者consumer部分
------------------------------消费者部分注释---------------------------------------------
消费者一直读取redis数据库中指定队列,一有值,立即取出,并进行相应数据库操作
------------------------------消费者部分注释结束----------------------------------------
消费者代码 consumer.php
- <?php
- //设置redis数据库连接及键名
- $redis = new Redis();
- $redis->connect('127.0.0.1');
- $key = 'secKill3';//redis数据库key [注:默认redis数据库选择第0号数据库]
- //PDO连接mysql数据库
- $dsn = "mysql:dbname=test;host=127.0.0.1";
- $pdo = new PDO($dsn, 'root', '123456');
- //死循环
- //从队列最前头取出一个值,判断这个值是否存在,取出时间和uid,保存到数据库
- //数据库插入失败时,要有回滚机制
- //注: rpush 和lpop是一对
- while(1) {
- //从队列最前头取出一个值
- $uid = $redis->lPop($key);
- //判断值是否存在
- if(!$uid || $uid == 'nil'){
- sleep(2);
- continue;
- }
- //生成订单号
- $orderNum = build_order_no($uid);
- //生成订单时间
- $timeStamp = time();
- //构造插入数组
- $user_data = array('uid'=>$uid,'time_stamp'=>$timeStamp,'order_num'=>$orderNum);
- //将数据保存到数据库
- $sql = "insert into student (uid,time_stamp,order_num) values (:uid,:time_stamp,:order_num)";
- $stmt = $pdo->prepare($sql);
- $res = $stmt->execute($user_data);
- //数据库插入数据失败,回滚
- if(!$res){
- $redis->rPush($key,$uid);
- }
- }
- //生成唯一订单号
- function build_order_no($uid){
- return substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8).$uid;
- }
注: 执行完consumer.php之后,数据库对应数据表应该有数值
到此,秒杀结束
备注:
用到的student数据表结构sql
- CREATE TABLE `student` (
- `uid` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'uid',
- `username` varchar(20) NOT NULL DEFAULT '',
- `time_stamp` int(11) NOT NULL DEFAULT 0,
- `order_num` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
- PRIMARY KEY (`uid`) USING BTREE,
- key (time_stamp)
- ) ENGINE = MyISAM default charset=utf8;
- PHP消息队列实现及应用:流量削峰案列(Redis的List类型实现秒杀)
- php结合redis实现高并发下的抢购、秒杀功能
- [置顶] php结合redis实现高并发下的抢购、秒杀功能
- 简单利用js、css、php实现手机在线编辑器功能
- php结合redis实现高并发下的抢购、秒杀功能
- php结合redis实现高并发下的抢购、秒杀功能
- 实现简单秒杀抢购,使用SpringBoot整合Spring-data-redis 、 rabbitMQ消息队列、redis缓存
- (高级篇)php结合redis实现高并发下的抢购、秒杀功能
- php结合redis实现高并发下的抢购、秒杀功能
- redis 实现消息队列,秒杀功能实现小测试
- PHP结合Redis实现高并发下的抢购、秒杀功能
- php 利用 redis 有序集合 实现 延时消费 队列
- php结合redis实现高并发下的抢购、秒杀功能
- php结合redis实现高并发下的抢购、秒杀功能
- php结合redis实现高并发下的抢购、秒杀功能
- phpredis实战--简单实现注册,删除,编辑,分页,登录,关注等功能
- php利用redis实现分页列表,新增,删除功能
- php结合redis实现高并发下的抢购、秒杀功能的实例
- 利用PHP绘图函数实现简单验证码功能
- PHP和Redis实现在高并发下的抢购及秒杀功能示例详解