php+redis는 토큰 버킷 알고리즘 코드를 구현합니다:
<?phpnamespace Api\Lib;/** * 限流控制 */class RateLimit{ private $minNum = 60; //单个用户每分访问数 private $dayNum = 10000; //单个用户每天总的访问量 public function minLimit($uid) { $minNumKey = $uid . '_minNum'; $dayNumKey = $uid . '_dayNum'; $resMin = $this->getRedis($minNumKey, $this->minNum, 60); $resDay = $this->getRedis($minNumKey, $this->minNum, 86400); if (!$resMin['status'] || !$resDay['status']) { exit($resMin['msg'] . $resDay['msg']); } } public function getRedis($key, $initNum, $expire) { $nowtime = time(); $result = ['status' => true, 'msg' => '']; $redisObj = $this->di->get('redis'); $redis->watch($key); $limitVal = $redis->get($key); if ($limitVal) { $limitVal = json_decode($limitVal, true); $newNum = min($initNum, ($limitVal['num'] - 1) + (($initNum / $expire) * ($nowtime - $limitVal['time']))); if ($newNum > 0) { $redisVal = json_encode(['num' => $newNum, 'time' => time()]); } else { return ['status' => false, 'msg' => '当前时刻令牌消耗完!']; } } else { $redisVal = json_encode(['num' => $initNum, 'time' => time()]); } $redis->multi(); $redis->set($key, $redisVal); $rob_result = $redis->exec(); if (!$rob_result) { $result = ['status' => false, 'msg' => '访问频次过多!']; } return $result; }}
코드 포인트:
1 먼저 규칙을 정의합니다.
단일 사용자의 분당 방문 횟수($minNum), 총 방문 횟수 단일 사용자의 일일($dayNum ), 인터페이스에 대한 총 액세스 횟수 및 기타 다른 규칙입니다.
2. 계산 비율
이 코드 예제에서는 최소 시간 단위로 초를 사용합니다. 비율 = 방문 횟수/시간($initNum / $expire)
3. 각 방문 후 추가된 토큰 수 계산 방법
마지막 방문 시간, 즉 토큰이 마지막으로 저장된 시간을 구합니다. 현재 시간과 마지막 방문 사이의 시간 차이를 계산하고 여기에 비율을 곱하여 이번에 보충해야 하는 토큰 수를 구합니다. . 토큰 보충 후 총 토큰 수에 주의하세요. 초기화된 토큰 수보다 클 수 없으며, 보충 수와 초기화 수의 최소값이 적용됩니다.
4. 프로그램 흐름
첫 번째 방문 시 토큰 수($minNum)를 초기화하고 이를 Redis에 저장한 후 현재 타임스탬프를 저장하여 다음에 보충해야 하는 토큰 수를 계산합니다.
두 번째 방문에서 남은 토큰 수를 가져오고 이번에 보충해야 할 토큰 수를 추가합니다. 보충 후 토큰 수가 > 0이면 현재 방문이 유효하고 액세스 가능합니다. 토큰이 모두 사용되었습니다. 토큰을 먼저 보충한 후 토큰이 >0인지 판단하는 이유는 비율의 개념도 있기 때문입니다. 즉, 지난번에 남은 토큰이 0이었지만 이번에 보충해야 할 토큰이 >1인 경우입니다. , 이번에는 여전히 액세스할 수 있습니다.
5. 동시 처리를 위해
Redis의 낙관적 잠금 메커니즘을 사용하세요.
더 많은 관련 지식은 PHP 중국어 홈페이지를 주목해주세요! !
위 내용은 PHP를 사용하여 토큰 버킷 알고리즘을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!