课程名称:PHP消息队列实现及应用
课程章节:流量削峰案例:Redis的List类型实现秒杀
讲师:Wicon
https://www.imooc.com/video/15163
课程内容:
Redis数据类型中的list类型 1、lpush/lpushx:将值插入到(是否存在)列表头部 2、rpush/rpushx:从尾部插入 3、lpop:移除第一个元素并获取值 4、rpop:移除最后一个元素并获取值 5、ltrim:保留指定区间内元素 6、llen:获取元素长度 7、lset:通过索引设置元素的值 架构设计
秒杀程序实现代码
<?php
//连接本地的 Redis 服务
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
if ($redis) {
echo "success";
}
$redis_name='miaosha';
for ($i=0; $i<100; $i++) {
$uid = rand(100000, 9999999);
//接受用户id
// $uid = $_GET['uid'];
//获取一下redis里面已有的数量
$num = 10;
//如果当前人数少于时候的时候,则加入这个队列
if ($redis->lLen($redis_name) < 10) {
$redis->rPush($redis_name,$uid.'%'.microtime());
echo $uid . '秒杀成功!'.'<br>';
} else {
//如果当天人数已经达到了十个人,则返回秒杀已完成
echo "秒杀已结束";
}
}
$redis->close();
?>
服务端:
<?php
include './db.php';
//连接本地的 Redis 服务
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis_name="miaosha";
$db=DB::getIntance();
//死循环,
while (1){
//第一步
//从队列最左侧取出一个值来,
$user = $redis->lPop($redis_name);
//然后判断这个值是否存在,
if(!$user||$user=='nil'){
sleep(2);
continue;
}
//如果存在切割出时间,uid
$user_arr = explode('%', $user);
$insert_data = array(
'uid' => $user_arr[0],
'time_stamp' => $user_arr[1]);
$res = $db->insert('redis_queue',$insert_data);
//保存数据库中,
if(!$res){
$redis->rPush($redis_name,$user);
}
sleep(2);
//第二部
//redis如果把值取出来这个值就不在队列里了
//如果出现问题了我的业务没有完成失败的情况下,我们需要有一个备份机制把值重新插回队列里
//数据库插入失败时候的回滚机制
//释放一下redis
}
$redis->close();
?>课程收获:
这样的秒杀做法可能实际项目中有所不足,我倒是感觉讲师的意思是一种限流的概念,并非是份数的把控,如果需要做到不超卖,还需要再用一个队列对产品的份数进行一个校验。