限量的chuli

思考:
其实下面redis方向中,自增优先和获取优先 可以合并的,是一样的,如果要返还资格,都必须要另一个字段

大方向一:利用redis

第一种:通用限量处理方式

$cur_num = $redis->Get($key);

if($cur_num > 3000){ //粗略防线,先get,肯定会超,但可以减少后续请求 执行下面内容,属于第一道防线
return;
}

$now_num = $redis->Incr($key);//要紧挨着get放,不能数据库执行完后再incr,那要超大了,切记

if($now_num < 3000){
//执行各种数据库操作,只有成功才不考虑
$add_ret = $this->addGrabInfo($op_id, $are);
if($add_ret){
$this->OutputJSON(0, "立即下载吧",array('code' => 0));return;
}
}else{
echo "超出限量";
}


第二种:限量同时可以返还限量资格

//请求进来就自增
$limit_num = $redis->Incr($key); //有个请求就自增一个,只用来做吞吐量限制

//控制请求数量,超出限量就return掉(“返还资格”需要额外变量)
if($limit_num > 3000){
if($redis->Get($failed_key) > 0){ //如果前面有请求在数据库阶段执行失败,则返还资格
$redis->Decr($failed_key); //返还的资格,用完就要立刻清掉
}else{
return;
}
}

//执行各种数据库操作,只有成功才不考虑
$add_ret = $this->addGrabInfo($op_id, $are);
if($add_ret){
$this->OutputJSON(0, "立即下载吧",array('code' => 0));return;
}else{
//凡是失败,都要返还资格
$redis->Incr($failed_key);
}

第三种方式:redis队列机制
//优点:
1、控制吞吐量
2、方便实现返回资格
3、可以准确实现控制并发
//缺点:
1、push不去除重复(重复op_id可以在插入数据库失败时,返还资格)

$cur_num = $redis->Lpush($key,$op_id); //$key为队列名 直接用op_id即可。注意队列不去除重复的,同一个op_id,可能会存两次,所以已经激活过的,要rem掉
if($cur_num > 3000){
return;
}

//执行各种数据库操作
$add_ret = $this->addGrabInfo($op_id, $are);
if($add_ret){
$this->OutputJSON(0, "立即下载吧",array('code' => 0,'link'=>$link));return;
}else{

//执行失败,回退资格(可能是数据库已经有该记录,或已经激活过),1表示删除1个与$op_id相同的值,区分大小写
$redis->Lrem($key,1,$op_id);
//$redis->Lpop($key,$op_id); //返回队列尾部最后一个值,并移除
}

大方向二:利用数据库

方式一、设置单独的限量单表单字段 num

$sql1 = "insert into jihuo values(fkas,sdf,lsd)";
$sql2 = "update xianliang set num = num+1 where num < 3000";

$tran = $db->beginTransaction(); //伪代码,事务写法依具体框架
try {
$tran->commit($sql1,$sql2);
$this->OutputJSON(0, "成功",array('code' => 0,'link'=>$link));return;
}catch(Exception $e){
$tran->rollback();
$this->OutputJSON(0, "失败",array('code' => 0,'link'=>$link));return;
}

原文地址:https://www.cnblogs.com/zhongyuan/p/5075626.html