最近和其他部门合作项目,当然我是负责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. python 自动化接口测试(6)

    迎接新的一波更新吧,这次是基于图灵机器人的一个api接口的测试. 这是api的接口:http://www.tuling123.com/openapi/api 我们试着通过浏览器直接访问看下 这是反馈的 ...

  2. Entity Framework快速入门--IQueryable与IEnumberable的区别

    IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IQueryable 接口 ...

  3. 静态链表实现(A-B)+(B-A)【代码】

    -----------------------------------------------第一次发代码,写在前面------------------------------------------ ...

  4. React翻译官网文档之JSX

    什么是JSX? 看下面的代码它被称为JSX,它既不是字符串也不是HTML,而是一种facebook公司对javascript语法的拓展.虽然写法很奇怪最终仍会会被编译为javascript代码 con ...

  5. MySQL一个简单的存储过程demo

    使用的工具是Navicat for MySQL. 首先创建一个学生表 mysql) ) ) auto_increment,age ) ) not null,primary key(s_no)); Qu ...

  6. C++小技巧之CONTAINING_RECORD

    CONTAINING_RECORD Containing record是一个在C++编程中用处很大的一种技巧,它的功能为已知结构体或类的某一成员.对象中该成员的地址以及这一结构体名或类名,从而得到该对 ...

  7. LinkedList 学习笔记

    先摆上JDK1.8中hashMap的类注释:我翻译了一下 /** * Doubly-linked list implementation of the {@code List} and {@code ...

  8. centos7安装redis3.0和phpredis扩展详细教程(图文)

    整理一下centos7安装redis3.0和phpredis扩展的过程,有需要的朋友可以拿去使用. 一.安装redis3.0 1.安装必要的包 yum install gcc 2.centos7安装r ...

  9. bootstrap快速入门笔记(二)-栅格系统,响应式类

    一,栅格系统大致有以下: 1,行row必须包含在 .container (固定宽度)或 .container-fluid (100% 宽度)中,一行有12列 2.“列(column)”在水平方向创建一 ...

  10. tomcat的常用配置

    1.解決get请求的中文乱码问题 解决办法: 首先找到tomcat路径下的apache-tomcat-7.0.52\conf文件夹,打开server.xml文件,编辑如下内容: <Connect ...