redis php 漏斗算法限流

漏斗算法

漏桶算法的原理:
漏桶有一定的容量,给漏桶注水,当单位时间内注入水量大于流出水量,漏桶内积累的水就会越来越多,直到溢出。

就好比大批量请求访问nginx相当于注水,nginx根据配置按照固定速率处理请求当做排水。

漏桶容量就好比配置给nginx的队列长度。当漏桶发生溢出,则禁止请求进入,直接返回错误

在这里插入图片描述

php实现一个简单的漏斗算法

/**
 * [leaky php实现漏桶算法]
 * @param    [type]     $contain            [int 桶的总容量]
 * @param    [type]     $addNum             [int 每次注入桶中的水量]
 * @param    [type]     $leakRate           [int 桶中漏水的速率,秒为单位。例如2/s,3/s]
 * @param    integer    &$water             [int 当前水量]
 * @param    integer    &$preTime           [int 时间戳,记录的上次漏水时间]
 * @return   [type]                         [bool,返回可否继续注入true/false]
 */
function leaky($contain,$addNum,$leakRate,&$water=0,&$preTime=0)
{
    //参数赋值
    //首次进入默认当前水量为0
    $water = empty($water) ? 0 : $water;
    //首次进入默认上次漏水时间为当前时间
    $preTime = empty($water) ? time() : $preTime;
    $curTime = time();
    //上次结束到本次开始,流出去的水
    $leakWater = ($curTime-$preTime)*$leakRate;
    //上次结束时候的水量减去流出去的水,也就是本次初始水量
    $water = $water-$leakWater;
    //水量不可能为负,漏出大于进入则水量为0
    $water = ( $water>=0 ) ? $water : 0 ;
    //更新本次漏完水的时间
    $preTime = $curTime;
    //水小于总容量则可注入,否则不可注入
    if( ($water+$addNum) <= $contain ){
        $water += $addNum;
        return true;
    }else{
        return false;
    }
 
}
 
/**
 * 测试
 * @var integer
 */
for($i=0;$i<500;$i++){
    $res = leaky(50,1,5,$water,$timeStamp);
    var_dump($res);
    usleep(50000);
}

redis 的漏斗算法实现

public function SpeedCounter() {
	$redis = new \Redis();
	$redis->connect('127.0.0.1', 6379);
	// 最大请求数量
	$maxCount = 100;
	//每分钟内,一个用户只能访问10次
	$interval =60;
	//请求总数量
	$zcount = $redis->incr('zcont');
	//判断是否超过最大值
	if ($zcount<=$maxCount) {
		//业务处理
		$user = [
		                11,21,31,41,51,61
		            ];
		foreach ($user as $val) {
			$key = $val;
			$check = $redis->exists($key);
			if ($check) {
				$sum = $redis->incr($key);
				if ($sum<=5) {
					//业务处理
					echo "每个用户在规定的时间内只能访问5次 $sum";
				} else {
					echo "你已经购买过 $sum";
				}
			} else {
				//print_r($redis->get($key)) ;
				///请购买
				echo "请购买";
				$sum = $redis->incr($key);
				$redis->Expire($key,$interval);
			}
		}
	} else {
		//超过请求数量
		$redis->Expire('zcont',$interval);
		echo '超出请求'.$zcount;
	}

	/**
     * **漏桶的大小是固定的,处理速度也是固定的,但是请求的速率的不固定的。在突发的情况下,会丢弃很多请求。**
     */
	function LeackBucket() {
		$redis = new \Redis();
		$redis->connect('127.0.0.1', 6379);
		//桶的容量
		$maxCount = 1000;
		//时间
		$interval = 10;
		//每分钟流出的数量
		$speed   = 20;
		//用户
		$time = $redis->time();
		$key = $time[0].$time[1];
		//时间判断
		//$redis->del('outCount');
		$check = $redis->exists('outCount');
		// echo $check;
		if ($check) {
			//出桶的速率的请求数量
			$outCount = $redis->incr('outCount');
			if ($outCount<=$speed) {
				//业务处理
				echo "规定的时间内只能访问20次 $outCount";
			} else {
				echo "你已经超过每分钟的访问 $outCount";
			}
		} else {
			$outCount = $redis->incr('outCount');
			//  echo $outCount;
			$redis->Expire('outCount',$interval);
			echo "时间过了";
			exit;
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值