*/ class TrafficShaper { /** * 令牌桶 * * @var string */ public $container; /** * 最大令牌数 * * @var int */ public $max; /** * @var Connection */ protected $redis; /** * TrafficShaper constructor. * @param int $max * @param string $container */ public function __construct($max = 300, $container = 'container') { $this->redis = Yii::$app->redis; $this->max = $max; $this->container = $container; } /** * 加入令牌 * * 注意:需要加入定时任务,定时增加令牌数量 * * @param int $num 加入的令牌数量 * @return int 加入的数量 */ public function add($num = 0) { // 当前剩余令牌数 $curnum = intval($this->redis->llen($this->container)); // 最大令牌数 $maxnum = intval($this->max); // 计算最大可加入的令牌数量,不能超过最大令牌数 $num = $maxnum >= $curnum + $num ? $num : $maxnum - $curnum; // 加入令牌 if ($num > 0) { $token = array_fill(0, $num, 1); $this->redis->lpush($this->container, ...$token); return $num; } return 0; } /** * 获取令牌 * * @return bool */ public function info() { return intval($this->redis->llen($this->container)); } /** * 获取令牌 * * @return bool */ public function get() { return $this->redis->rpop($this->container) ? true : false; } /** * 重设令牌桶,填满令牌 */ public function reset() { $this->redis->lrem($this->container, 0, $this->max); $this->add($this->max); } }