最近和其他部门合作项目,当然我是负责php接口方面的工作,
get到一些东西,所以来分享记录一下。

项目需求:

题目将通过主持人ipad投射至大屏幕,选手按‘抢答’
按钮进行抢答。抢答成功,选手所在组,以及大屏幕上广播抢答成功者的ipad屏幕,
抢答失败选手,返回抢答失败界面。

需求分析:

这里抢答,其实就是和秒杀活动机制一样了,不过这里场景可能稍微复杂点,
需要用到强弱连接,实时广播,大家可以去看看GatewayWordker当然,今天我们只是单纯
讨论抢答机制是如何实现。那么既然抢答,就要考虑高并发问题了。

思路分析:

1.把题目的状态写在redis里面,比如题目还没有被抢状态为1,抢完状态为0
2.选手进行抢答时,查询redis状态,为0,直接返回,题目已经被抢完;
3.选手进行抢答时,查询redis状态,为1,进入下一步逻辑操作,修改redis状态为0,
进入数据库查询改题目数据,运用行级琐机制。返回逻辑处理结果

框架依然用的是laravel,开发模式用的是仓库模式,这用有利于项目后期的维护和升级。

(数据字段涉及安全,暂时用test1等表示便好)

/******首先进行题目获取,并把题目对应的redis编号改为1******/

     /**
* @desc 随机获得抢答题题目
* @date 2017/4/19 17:26
* @param [type]
* @author 十月桂花香十里
* @return [bool or array]
*/
public function getQuickQuestion(){
//获取抢答题随机题号id
$randNum = $this->getRandArray(config('test.start_quick_id'),config('test.end_quick_id'),config('djm.max_quick'));
DB::transaction(function () use ($randNum){
//将抢答题题号id写进redis,值为1题目可以进行抢答,0不可以进行抢答(为了便于后期维护,0和1都可以写进配置文件中)
$redis = PRedis::connection('default');
foreach($randNum as $k=>$v){
$redis->set("check_quick_id_".$v,1);
}
//将数据库中抢答题对应的id记录,test3状态改为可进行抢答
//DjmQuestion::whereIn('id', $randNum)->update(['test3'=>1]);
});
$res = DjmQuestion::whereIn('id', $randNum)
          ->orderByRaw(DB::raw("FIELD(id, ".implode(',', $randNum).")"))
             ->get(['id','test1','test2','test3','test4']);
if($res){
       foreach($res as $k=>$v){
$res[$k]['test6'] = json_decode($v['test6'],true);
}
//处理需要返回的数组
return $res;
}else return false;
}

/******利用php的array_slice函数实现编号的随机选择******/

     /*
* function getTenNum( int $min, int $max, int $num)
* 生成一定数量的随机数
* $min 和 $max: 指定随机数的范围
* $num: 指定生成数量
*/
public function getRandArray($min,$max,$num){
$array = range($min,$max);
shuffle($array);
$array = array_slice($array, -$num);
return $array;
}

/******选手抢答题目逻辑的实现******/

     /**
* @desc 选手进行题目的抢答
* @date 2017/4/19 18:19
* @param [$id $uid]
* @author 十月桂花香十里
* @return [bool or array]
*/
public function userQuickAnswer($id='',$uid){
//判断uid是否是答题选手
if(!in_array($uid, config('test1.check_uid'))) return false;
//判断$id是否存在
if($id < config('test1.start_quick_id') || $id > config('test1.end_quick_id')) return false;
//redis判断题目是否可以进行抢答
$redis = PRedis::connection('default');
$check_quick_status = $redis->get("check_quick_id_".$id);
if($check_quick_status ==1){
//运用事务,添加共享锁
//DB::transaction(function () use ($redis,$id){
//将redis的状态和数据库field3改为0,变为不可抢答
//DjmQuestion::where('id',$id)->sharedLock()->update(['test1'=>0]);
//});
//将redis的状态改为0,变为不可抢答
$redis->set("check_quick_id_".$id,0);
//redis绑定此题和选手的关系
$redis->set("check_quick_id_".$id."_".$uid,1);
//获取本条数据记录
return DjmQuestion::find($id)->toArray();
}else return false;
}

/******选手抢答题目回答的实现******/

     /**
* @desc 选手进行抢答题的回答
* @date 2017/4/20 10:09
* @param [$id,$uid]
* @author 1245049149@qq.com
* @return [bool or array]
*/
public function userQuickAnswerResult($id,$uid,$answer){
//判断uid是否是答题选手
if(!in_array($uid, config('djm.check_uid'))) return false;
//判断$id是否存在
if($id < config('djm.start_quick_id') || $id > config('djm.end_quick_id')) return false;
//redis判断此题和选手是否绑定关系
$redis = PRedis::connection('default');
$check_user_quick_status = $redis->get("check_quick_id_".$id."_".$uid);
if($check_user_quick_status == 1){
//关系如果已经绑定,判断选手答题情况
$redis->set("check_quick_id_".$id."_".$uid,0);
$check_answer = config('djm.check_answer'); //题目编号答案对照(如果题目数量不多且固定的话,建议写进配置文件中,不用查询数据库)
if($check_answer[$id] == strtoupper($answer)){
//回答正确分数自加5
DjmQuestionScore::where('test10',$uid)
->where('test11',config('djm.quick_test11'))
               ->increment('test12',5);
return array(
'msg' => '回答正确',
'status' => 1,
);
}else{
//回答错误分数自减5
DjmQuestionScore::where('test10',$uid)
 ->where('test11',config('djm.quick_test11'))
               ->decrement('score',5);
return array(
'msg' => '回答错误,正确答案:'.$check_answer[$id],
'test12' => $check_answer[$id],
'status' => 0,
);
}
}else return false;
}

ok,功能至此实现了。

php实现题目抢答、商品秒杀等类型的需求的更多相关文章

  1. PHP商品秒杀问题解决方案实例详解【mysql与redis】

    本文实例讲述了PHP商品秒杀问题解决方案.分享给大家供大家参考,具体如下: 引言 假设num是存储在数据库中的字段,保存了被秒杀产品的剩余数量. if($num > 0){ //用户抢购成功,记 ...

  2. PHP商品秒杀计时实现(解决大流量方案)

    PHP商品秒杀功能我们多半以整点或时间点为例子,这样对于php来说处理不复杂,但有一个问题就是如果流量大要如何来处理,下面我们一起来看看解决办法. 要求要有小时分钟秒的实时倒计时的显示,用户端修改日期 ...

  3. zookeeper实现商品秒杀抢购

    package com.test; import java.io.IOException; import java.util.List; import java.util.concurrent.Cyc ...

  4. 01 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之业务分析与DAO层

    作者:nnngu 项目源代码:https://github.com/nnngu/nguSeckill 这是一个整合IDEA+Maven+SSM框架的高并发的商品秒杀项目.我们将分为以下几篇文章来进行详 ...

  5. Java秒杀系统实战系列~商品秒杀代码实战

    摘要: 本篇博文是“Java秒杀系统实战系列文章”的第六篇,本篇博文我们将进入整个秒杀系统核心功能模块的代码开发,即“商品秒杀”功能模块的代码实战. 内容: “商品秒杀”功能模块是建立在“商品详情”功 ...

  6. 02 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之Service层

    作者:nnngu 项目源代码:https://github.com/nnngu/nguSeckill 首先在编写Service层代码前,我们应该首先要知道这一层到底是干什么的. Service层主要负 ...

  7. 03 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之web层

    Github:https://github.com/nnngu 项目源代码:https://github.com/nnngu/nguSeckill 前端交互流程设计 对于一个系统,需要产品经理.前端工 ...

  8. 04 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之高并发优化

    Github:https://github.com/nnngu 项目源代码:https://github.com/nnngu/nguSeckill 关于并发 并发性上不去是因为当多个线程同时访问一行数 ...

  9. 使用redis 中的事务处理实现商品秒杀

    redis中的事务处理: redis中的事物事物处理是指能够批量的执行一组命令(当事务开始执行时,事务中的命令能够按照按照规定好的顺序执行而不会被插队或打断): 与mysql事务的区别在于:mysql ...

随机推荐

  1. 【CSS/JS学习】如何实现单行/多行文本溢出的省略(...)--老司机绕过坑道的正确姿势

    引言: 写前端UI的朋友们也许都遇到过这样的问题:我们需要实现这样一个需求,在一个父级元素中隐藏一个可能过长的文本:   这个文本可能是单行的:   也可能是多行的:   下面我就给大家展示如何简单或 ...

  2. matlab 2016a破解中文版安装教程

    之前电脑重装过,所以要重新安装一个matlab,在大三的时候学过matlab,信息老师给的安装包,但是不知道放哪里去了,记忆力不好,找了些网上的教程和下载地址,真的是坑,一些都是不行的,在这里记录下m ...

  3. 非负矩阵分解(4):NMF算法和聚类算法的联系与区别

    作者:桂. 时间:2017-04-14   06:22:26 链接:http://www.cnblogs.com/xingshansi/p/6685811.html 声明:欢迎被转载,不过记得注明出处 ...

  4. C字符串处理函数

    部分参考百科. C常用字符串函数:字符串输入函数,字符串输出函数,字符串处理函数,标准输入输出流 字符串处理函数: 1.字符串长度:strlen(str),返回字符串实际长度,不包括'\0',返回值类 ...

  5. 秒懂JS对象、构造器函数和原型对象之间的关系

    学习JS的过程中,想要掌握面向对象的程序设计风格,对象模型(原型和继承)是其中的重点和难点,拜读了各类经典书籍和各位前辈的技术文章,感觉都太过高深,花费了不少时间才搞明白(个人智商是硬伤/(ㄒoㄒ)/ ...

  6. 【Java基础】Java类的加载和对象创建流程的详细分析

    相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下. 实例问题 实例代码 Parent类 package ...

  7. Spring数据库访问

    一般采用第三方具有连接缓冲池的数据源实现类:spring支持最常见的两个具有连接缓冲池的数据源为:DBCP和C3P0; DBCP(Database connection pool) 是Apache的一 ...

  8. LinkCode 整数排序II

    http://www.lintcode.com/zh-cn/problem/sort-integers-ii/ 题目 给一组整数,按照升序排序.使用归并排序,快速排序,堆排序或者任何其他 O(n lo ...

  9. 如何修改dmesg log buffer size

    CONFIG_LOG_BUF_SHIFT: Kernel log buffer size (16 => 64KB, 17 => 128KB) General informations Th ...

  10. 我拖拖拖--H5拖放API基础篇

    不要搞错,本文不是讲如何拖地的.看过<javascript精粹>朋友应该知道,他实现拖放的过程比较复杂,现在时代不同了,我们用H5的新的拖放API就能非常方便的实现拖放效果了.最近在园子见 ...