1. 程式人生 > 實用技巧 >php 基於redis使用令牌桶演算法 計數器 漏桶演算法 實現流量控制

php 基於redis使用令牌桶演算法 計數器 漏桶演算法 實現流量控制

通常在高併發和大流量的情況下,一般限流是必須的。為了保證伺服器正常的壓力。那我們就聊一下幾種限流的演算法。

  1. 計數器
    計數器是一種最常用的一種方法,在一段時間間隔內,處理請求的數量固定的,超的就不做處理。

demo

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;

        }

  1. 漏桶演算法

漏桶的大小是固定的,處理速度也是固定的,但是請求的速率的不固定的。在突發的情況下,會丟棄很多請求。

 /**
     * **漏桶的大小是固定的,處理速度也是固定的,但是請求的速率的不固定的。在突發的情況下,會丟棄很多請求。**
     */
    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;
            }







    }
  1. 令牌桶
    令牌桶演算法(Token Bucket)和 Leaky Bucket 效果一樣但方向相反的演算法,更加容易理解.隨著時間流逝,系統會按恆定1/QPS時間間隔(如果QPS=100,則間隔是10ms)往桶裡加入Token(想象和漏洞漏水相反,有個水龍頭在不斷的加水),如果桶已經滿了就不再加了.新請求來臨時,會各自拿走一個Token,如果沒有Token可拿了就阻塞或者拒絕服務.

令牌桶的另外一個好處是可以方便的改變速度. 一旦需要提高速率,則按需提高放入桶中的令牌的速率. 一般會定時(比如100毫秒)往桶中增加一定數量的令牌, 有些變種演算法則實時的計算應該增加的令牌的數量.

 /**
     * 令牌
     */
    function TrafficShaper(){

        $redis = new \Redis();
        $redis->pconnect('127.0.0.1', 6379);
        //桶的容量
        $maxCount = 10;
        //當前容量
        $curnum = $maxCount-$redis->get('token')-1;
        echo $curnum;


         if ($curnum>0){
             //業務邏輯
             //成功後

            $token = $redis->incr('token');
             echo "===$token";



         } else {

             echo "沒有令牌了";
             $redis->set('token',0);
         }



    }