ホームページ  >  記事  >  バックエンド開発  >  PHPを使用してトークンバケットアルゴリズムを実装する方法

PHPを使用してトークンバケットアルゴリズムを実装する方法

尚
オリジナル
2020-04-25 11:26:463189ブラウズ

PHPを使用してトークンバケットアルゴリズムを実装する方法

php redis はトークン バケット アルゴリズム コードを実装します:

<?phpnamespace Api\Lib;/**
 * 限流控制
 */class RateLimit{
    private $minNum = 60; //单个用户每分访问数
    private $dayNum = 10000; //单个用户每天总的访问量

    public function minLimit($uid)
    {
        $minNumKey = $uid . &#39;_minNum&#39;;
        $dayNumKey = $uid . &#39;_dayNum&#39;;
        $resMin    = $this->getRedis($minNumKey, $this->minNum, 60);
        $resDay    = $this->getRedis($minNumKey, $this->minNum, 86400);
        if (!$resMin[&#39;status&#39;] || !$resDay[&#39;status&#39;]) {
            exit($resMin[&#39;msg&#39;] . $resDay[&#39;msg&#39;]);
        }
    }

    public function getRedis($key, $initNum, $expire)
    {
        $nowtime  = time();
        $result   = [&#39;status&#39; => true, &#39;msg&#39; => &#39;&#39;];
        $redisObj = $this->di->get(&#39;redis&#39;);
        $redis->watch($key);
        $limitVal = $redis->get($key);
        if ($limitVal) {
            $limitVal = json_decode($limitVal, true);
            $newNum   = min($initNum, ($limitVal[&#39;num&#39;] - 1) + (($initNum / $expire) * ($nowtime - $limitVal[&#39;time&#39;])));
            if ($newNum > 0) {
                $redisVal = json_encode([&#39;num&#39; => $newNum, &#39;time&#39; => time()]);
            } else {
                return [&#39;status&#39; => false, &#39;msg&#39; => &#39;当前时刻令牌消耗完!&#39;];
            }
        } else {
            $redisVal = json_encode([&#39;num&#39; => $initNum, &#39;time&#39; => time()]);
        }
        $redis->multi();
        $redis->set($key, $redisVal);
        $rob_result = $redis->exec();
        if (!$rob_result) {
            $result = [&#39;status&#39; => false, &#39;msg&#39; => &#39;访问频次过多!&#39;];
        }
        return $result;
    }}

コード ポイント:

1. まずルールを定義します

Singleユーザー 1 分あたりの訪問数 ($minNum)、単一ユーザーによる 1 日あたりの合計訪問数 ($dayNum)、インターフェイスへの合計訪問数など、さまざまなルールがあります。

2. レートの計算

このコード例では、最小時間単位として秒を使用します (レート = 訪問数/時間 ($initNum / $expire)

3)。毎回 訪問後に追加されるトークンの数を計算する方法

最後の訪問の時刻、つまりトークンが最後に保存された時刻を取得します。現在時刻と前回の訪問時刻との時間差を計算します。訪問数にレートを乗算して、今回追加する必要がある数を取得します トークンの数 トークンを補充した後のトークンの総数は、初期化されたトークンの数を超えることはできないことに注意してください 補充された数とトークンの最小値初期化された番号が優先されます。

4. プログラム フロー

最初の訪問時にトークンの数 ($minNum) を初期化し、それを Redis に保存し、補充する必要があるトークンを計算するために現在のタイムスタンプを保存します。次回 カードの枚数。

2 回目の訪問時に残りのトークン数を取得し、今回補充するトークンの数を追加します。補充後、トークン数 > 0 の場合、現在の訪問は有効でアクセス可能です。それ以外の場合、トークンは使用後にアクセスできなくなります。先にトークンを補充してからトークン>0かどうかを判断するのはレートの概念があるためで、前回トークンの残量が0だったけど今回補充すべきトークンが>1の場合、今回はまだアクセスできます。

5. 同時処理の場合

Redis のオプティミスティック ロック メカニズムを使用します。

さらに関連する知識については、PHP 中国語 Web サイト に注目してください。 !

以上がPHPを使用してトークンバケットアルゴリズムを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。