概述
一 生产者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 List队列简单实现秒杀功能所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复