课程名称: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(); ?>
课程收获:
这样的秒杀做法可能实际项目中有所不足,我倒是感觉讲师的意思是一种限流的概念,并非是份数的把控,如果需要做到不超卖,还需要再用一个队列对产品的份数进行一个校验。