php redis implements the token bucket algorithm code:
<?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; }}
Code points:
1. First define the rules
Single user There are different rules such as the number of visits per minute ($minNum), the total number of visits per day by a single user ($dayNum), the total number of visits to the interface, etc.
2. Calculate the rate
This code example uses seconds as the minimum time unit, rate = number of visits/time ($initNum / $expire)
3. Each time How to calculate the number of tokens added after a visit
Get the time of the last visit, that is, the time when the token was last stored. Calculate the time difference between the current time and the last visit multiplied by the rate to get the number that needs to be added this time. The number of tokens. Note that the total number of tokens after replenishing tokens cannot be greater than the initialized number of tokens. The minimum value of the replenished number and the initialized number shall prevail.
4. Program flow
Initialize the number of tokens ($minNum) during the first visit, store it in Redis and store the current timestamp in order to calculate the tokens that need to be supplemented next time. Number of cards.
Get the remaining number of tokens during the second visit, and add the number of tokens that should be supplemented this time. After the supplement, if the number of tokens > 0, the current visit is valid and accessible, otherwise The token is no longer accessible after use. The reason for replenishing tokens first and then judging whether the tokens are > 0 is because there is also the concept of rate. That is, if the remaining tokens last time were 0 but the tokens that should be replenished this time are > 1, then you can still access it this time.
5. For concurrency processing
Use Redis’s optimistic locking mechanism.
For more related knowledge, please pay attention to PHP Chinese website! !
The above is the detailed content of How to implement the token bucket algorithm using php. For more information, please follow other related articles on the PHP Chinese website!