最近和其他部门合作项目,当然我是负责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. 移植 DeepinQQ 到 Fedora 中

    本着自由/开源软件的分享精神创作此文,如有任何权力侵害请联系我,我将积极配合. 移植 DeepinQQ 到 Fedora 中 --也不知道是用移植还是迁移更合适 写在前面 首先,在这里要感谢武汉深之度 ...

  2. 为Jquery EasyUI 组件加上“清除”功能

    1.背景 在使用 EasyUI 各表单组件时,尤其是使用 ComboBox(下拉列表框).DateBox(日期输入框).DateTimeBox(日期时间输入框)这三个组件时,经常有这样的需求,下拉框或 ...

  3. js 形参和实参---2017-04-11

    一.定义 1.实参(argument):     全称为"实际参数"是在调用时传递给函数的参数. 实参可以是常量.变量.表达式.函数等, 无论实参是何种类型的量,在进行函数调用时, ...

  4. KMP算法【代码】

    废话不多说,看毛片算法的核心在于next数组. 很多地方用的都是严书上的方法来求解next数组,代码确实简洁明了,但是可能对于初学者来说不容易想到,甚至不是一下子能理解.(好了,其实我说的就是自己,别 ...

  5. 自动生成数学题型一 (框架Struts2) 题型如(a+b=c)

    1. 加减乘除 1.1 随机生成制定范围的整数 /** * 随机产生一个被限定范围的整数 * * @param num1 * 定义起始范围 num1 * @param num2 * 定义终止范围 nu ...

  6. 对Qt下对话服务器客户端的总结(MyTcpServer与MyTcpClient)

    在汇文培训老师给讲了这个例子.讲的挺好的 Qt编写聊天服务器与客户端主要用到下面两个类: QTcpSocket --- 处理连接的 QTcpServer --- 处理服务器,对接入进行响应,创建每个链 ...

  7. html 压缩工具 html-minifier

    https://github.com/kangax/html-minifier#options-quick-reference 1.参数列表 option Description Default re ...

  8. Tomcat access log配置

    在tomcat的access中打印出请求的情况可以帮助我们分析问题,通常比较关注的有访问IP.线程号.访问url.返回状态码.访问时间.持续时间. 在Spring boot中使用了内嵌的tomcat, ...

  9. DirectFB学习笔记二

    本篇目的,画一个方框,在方框上画一串字符. 实现步骤:首先创建IDirectFB接口,通过它再创建要显示的表面surface,同时创建字体font,绘制字符必须要设置绘制的字体,否则绘制不成功.然后清 ...

  10. Android的root学习

    Android的内核就是Linux,所以Android获取root其实和Linux获取root权限是一回事儿.在Linux下获取root权限的时候就是执行sudo或者su,接下来系统会提示输入root ...