php实现题目抢答、商品秒杀等类型的需求
最近和其他部门合作项目,当然我是负责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实现题目抢答、商品秒杀等类型的需求的更多相关文章
- PHP商品秒杀问题解决方案实例详解【mysql与redis】
本文实例讲述了PHP商品秒杀问题解决方案.分享给大家供大家参考,具体如下: 引言 假设num是存储在数据库中的字段,保存了被秒杀产品的剩余数量. if($num > 0){ //用户抢购成功,记 ...
- PHP商品秒杀计时实现(解决大流量方案)
PHP商品秒杀功能我们多半以整点或时间点为例子,这样对于php来说处理不复杂,但有一个问题就是如果流量大要如何来处理,下面我们一起来看看解决办法. 要求要有小时分钟秒的实时倒计时的显示,用户端修改日期 ...
- zookeeper实现商品秒杀抢购
package com.test; import java.io.IOException; import java.util.List; import java.util.concurrent.Cyc ...
- 01 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之业务分析与DAO层
作者:nnngu 项目源代码:https://github.com/nnngu/nguSeckill 这是一个整合IDEA+Maven+SSM框架的高并发的商品秒杀项目.我们将分为以下几篇文章来进行详 ...
- Java秒杀系统实战系列~商品秒杀代码实战
摘要: 本篇博文是“Java秒杀系统实战系列文章”的第六篇,本篇博文我们将进入整个秒杀系统核心功能模块的代码开发,即“商品秒杀”功能模块的代码实战. 内容: “商品秒杀”功能模块是建立在“商品详情”功 ...
- 02 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之Service层
作者:nnngu 项目源代码:https://github.com/nnngu/nguSeckill 首先在编写Service层代码前,我们应该首先要知道这一层到底是干什么的. Service层主要负 ...
- 03 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之web层
Github:https://github.com/nnngu 项目源代码:https://github.com/nnngu/nguSeckill 前端交互流程设计 对于一个系统,需要产品经理.前端工 ...
- 04 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之高并发优化
Github:https://github.com/nnngu 项目源代码:https://github.com/nnngu/nguSeckill 关于并发 并发性上不去是因为当多个线程同时访问一行数 ...
- 使用redis 中的事务处理实现商品秒杀
redis中的事务处理: redis中的事物事物处理是指能够批量的执行一组命令(当事务开始执行时,事务中的命令能够按照按照规定好的顺序执行而不会被插队或打断): 与mysql事务的区别在于:mysql ...
随机推荐
- 原型prototype、原型链__proto__、构造器constructor
创建函数时,会有原型prototype,有原型链__proto__,有constructor.(构造函数除外,没有原型) . prototype原型:是对象的一个属性(也是对象),使你有能力向对象添加 ...
- matlab函数:c2d离散化函数(待完善)
Convert model from continuous to discrete time sysd =c2d(sys,Ts)sysd =c2d(sys,Ts,method)sysd =c2d(sy ...
- JavaScript 格式化时间
//格式化 yyyy-MM-dd hh:mm:ss function renderTime(date) { if (date == '' || date == null) { return ''; } ...
- ajax多次请求,只执行最后一次的方法
ajax多次请求,只执行最后一次的方法 有时候点击按钮进行异步请求数据的时候可能网络差,用户会点击很多次,或者页面有很多相同的按钮,参数不同,但是调用的ajax相同,只想得到最后一次结果 我的思路是用 ...
- 【从无到有】HTML的初识——part1
Ⅰ.HTML的初识 1.HTML:超文本标签语言(网页源代码) 2.html的基本结构: <html> <head> <meta charset="utf-8& ...
- ASP.NET MVC5请求管道和生命周期
请求处理管道 请求管道是一些用于处理HTTP请求的模块组合,在ASP.NET中,请求管道有两个核心组件:IHttpModule和IHttpHandler.所有的HTTP请求都会进入IHttpHandl ...
- Lucene工作原理
Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构.该结构及相应的生成算法如下: 0)设有两篇文章1和2 文章1的内容为:Tom lives in Guangzhou,I l ...
- python基本数据类型——int
一.int的范围 python2: 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1: 在64位系统上,整数的位数为64位,取值范围为-2**63-2**63-1: pyth ...
- Java中遍历Map的常用方法
以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等): 方式一(推荐): // 推荐 // 在for-each循环中使用entr ...
- 使用jquery的load方法设计动态加载,并解决浏览器前进、后退、刷新等问题
继上一篇 使用jquery的load方法设计动态加载,并解决被加载页面JavaScript失效问题 解决了后台业务系统的部分动态加载问题,然而该框架离正常的用户体验还存在一些问题,如:浏览器的前进.后 ...