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實現的詳細內容,更多請關注億速云其它相關文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。