Cet article présente PHP basé sur Redis et utilise l'algorithme du bucket de jetons pour contrôler le trafic d'accès. Il fournit une description complète de l'algorithme et des exemples de démonstration que tout le monde peut apprendre et utiliser.
Chaque fois qu'il y a de longues vacances nationales ou des festivals importants, les sites touristiques nationaux ou les métros seront bondés de monde, ce qui entraînera une charge excessive. Certains adopteront des mesures de restriction de flux pour limiter le nombre de personnes entrant dans le pays. la zone est réduite à une certaine valeur, aucune autorisation supplémentaire ne sera accordée.
Par exemple :
Le nombre maximum de personnes autorisées dans la zone est de M
Le nombre actuel de personnes dans la zone est de N
Chaque fois que vous entrez Une personne, N+1, lorsque N = M, n'est pas autorisée à entrer
Chaque personne sort, N-1, quand N <
Bien sûr, nous pouvons ajouter des serveurs pour partager la pression. Tout d'abord, l'ajout de serveurs prend également un certain temps à configurer, et si des serveurs sont ajoutés en raison d'une certaine activité, ces ressources de serveur seront gaspillées. une fois l'activité terminée.
Nous pouvons donc d'abord utiliser la méthode
de limitation de courant pour réduire la pression des serveurs en fonction du type d'entreprise. Différent de la limite de circulation dans les sites pittoresques,
le temps entre la visite et la fin du système est très court, il suffit donc de connaître la durée moyenne de chaque visite et de fixer la durée maximale nombre de visiteurs simultanés. Algorithme du seau de jetons
2. Chaque visite prend un jeton du bucket Lorsque le jeton dans le bucket est 0, plus aucune visite n'est autorisée.
3. De temps en temps, ajoutez des jetons jusqu'à ce que le seau soit plein de jetons. (Vous pouvez mettre plusieurs jetons à intervalles réguliers ou remplir directement le seau de jetons en fonction de la situation réelle)
Nous pouvons utiliser la file d'attente de
redis comme conteneur du seau de jetons. >lPush (mettre en file d'attente), rPop (dequeue) pour implémenter les opérations d'ajout et de consommation de jetons. 🎜>Sortie :
Ajout régulier d'un algorithme de jeton Ajout régulier de jetons, nous pouvons utiliser crontab pour l'implémenter et appeler le ajouter une méthode pour rejoindre chaque minute Plusieurs jetons. Pour l'utilisation de crontab, veuillez vous référer à : "Format de commande d'exécution de tâche planifiée Linux crontab et exemples détaillés"
<?php/** * PHP基于Redis使用令牌桶算法实现流量控制 * Date: 2018-02-23 * Author: fdipzone * Version: 1.0 * * Descripton: * php基于Redis使用令牌桶算法实现流量控制,使用redis的队列作为令牌桶容器,入队(lPush)出队(rPop)作为令牌的加入与消耗操作。 * * Func: * public add 加入令牌 * public get 获取令牌 * public reset 重设令牌桶 * private connect 创建redis连接 */class TrafficShaper{ // class start private $_config; // redis设定 private $_redis; // redis对象 private $_queue; // 令牌桶 private $_max; // 最大令牌数 /** * 初始化 * @param Array $config redis连接设定 */ public function __construct($config, $queue, $max){ $this->_config = $config; $this->_queue = $queue; $this->_max = $max; $this->_redis = $this->connect(); } /** * 加入令牌 * @param Int $num 加入的令牌数量 * @return Int 加入的数量 */ public function add($num=0){ // 当前剩余令牌数 $curnum = intval($this->_redis->lSize($this->_queue)); // 最大令牌数 $maxnum = intval($this->_max); // 计算最大可加入的令牌数量,不能超过最大令牌数 $num = $maxnum>=$curnum+$num? $num : $maxnum-$curnum; // 加入令牌 if($num>0){ $token = array_fill(0, $num, 1); $this->_redis->lPush($this->_queue, ...$token); return $num; } return 0; } /** * 获取令牌 * @return Boolean */ public function get(){ return $this->_redis->rPop($this->_queue)? true : false; } /** * 重设令牌桶,填满令牌 */ public function reset(){ $this->_redis->delete($this->_queue); $this->add($this->_max); } /** * 创建redis连接 * @return Link */ private function connect(){ try{ $redis = new Redis(); $redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']); if(empty($this->_config['auth'])){ $redis->auth($this->_config['auth']); } $redis->select($this->_config['index']); }catch(RedisException $e){ throw new Exception($e->getMessage()); return false; } return $redis; } } // class end?>
Nous pouvons optimiser l'algorithme d'ajout de jetons et ajouter plusieurs jetons toutes les quelques secondes en une minute. Cela peut garantir qu'il y a une chance d'obtenir des jetons à chaque fois en une minute. Le programme d'ajout de jetons appelé par crontab est le suivant, ajoutant automatiquement 3 jetons par seconde.
<?php/** * 演示令牌加入与消耗 */require 'TrafficShaper.class.php';// redis连接设定$config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, );// 令牌桶容器$queue = 'mycontainer';// 最大令牌数$max = 5;// 创建TrafficShaper对象$oTrafficShaper = new TrafficShaper($config, $queue, $max);// 重设令牌桶,填满令牌$oTrafficShaper->reset();// 循环获取令牌,令牌桶内只有5个令牌,因此最后3次获取失败for($i=0; $i<8; $i++){ var_dump($oTrafficShaper->get()); }// 加入10个令牌,最大令牌为5,因此只能加入5个$add_num = $oTrafficShaper->add(10); var_dump($add_num);// 循环获取令牌,令牌桶内只有5个令牌,因此最后1次获取失败for($i=0; $i<6; $i++){ var_dump($oTrafficShaper->get()); }?>
La procédure de consommation de simulation est la suivante, consommant 2 à 8 jetons par seconde.
boolean trueboolean trueboolean trueboolean trueboolean trueboolean falseboolean falseboolean falseint 5boolean trueboolean trueboolean trueboolean trueboolean trueboolean false
Démo
Définir une tâche planifiée à exécuter toutes les minutes
Exécuter une consommation simulée
<?php/** * 定时任务加入令牌 */require 'TrafficShaper.class.php';// redis连接设定$config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, );// 令牌桶容器$queue = 'mycontainer';// 最大令牌数$max = 10;// 每次时间间隔加入的令牌数$token_num = 3;// 时间间隔,最好是能被60整除的数,保证覆盖每一分钟内所有的时间$time_step = 1;// 执行次数$exec_num = (int)(60/$time_step);// 创建TrafficShaper对象$oTrafficShaper = new TrafficShaper($config, $queue, $max);for($i=0; $i<$exec_num; $i++){ $add_num = $oTrafficShaper->add($token_num); echo '['.date('Y-m-d H:i:s').'] add token num:'.$add_num.PHP_EOL; sleep($time_step); }?>
Étant donné que le seau de jetons est plein au début (le nombre maximum de jetons est de 10), les jetons peuvent être obtenus dans les 10 premières fois, et après 10 fois Accès est restreint lorsque les jetons consommés sont supérieurs au nombre de jetons de participation.
<?php/** * 模拟用户访问消耗令牌,每段时间间隔消耗若干令牌 */require 'TrafficShaper.class.php';// redis连接设定$config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, );// 令牌桶容器$queue = 'mycontainer';// 最大令牌数$max = 10;// 每次时间间隔随机消耗的令牌数量范围$consume_token_range = array(2, 8);// 时间间隔$time_step = 1;// 创建TrafficShaper对象$oTrafficShaper = new TrafficShaper($config, $queue, $max);// 重设令牌桶,填满令牌$oTrafficShaper->reset();// 执行令牌消耗while(true){ $consume_num = mt_rand($consume_token_range[0], $consume_token_range[1]); for($i=0; $i<$consume_num; $i++){ $status = $oTrafficShaper->get(); echo '['.date('Y-m-d H:i:s').'] consume token:'.($status? 'true' : 'false').PHP_EOL; } sleep($time_step); }?>
Cet article explique comment PHP utilise l'algorithme du bucket de jetons pour implémenter un contrôle de flux basé sur Redis. Pour plus de contenu connexe, veuillez faire attention au site Web chinois de PHP.
* * * * * php /程序的路径/cron_add.php >> /tmp/cron_add.log
php consume_demo.php
[2018-02-23 11:42:57] consume token:true[2018-02-23 11:42:57] consume token:true[2018-02-23 11:42:57] consume token:true[2018-02-23 11:42:57] consume token:true[2018-02-23 11:42:57] consume token:true[2018-02-23 11:42:57] consume token:true[2018-02-23 11:42:57] consume token:true[2018-02-23 11:42:58] consume token:true[2018-02-23 11:42:58] consume token:true[2018-02-23 11:42:58] consume token:true[2018-02-23 11:42:58] consume token:true[2018-02-23 11:42:58] consume token:true[2018-02-23 11:42:58] consume token:true[2018-02-23 11:42:58] consume token:false[2018-02-23 11:42:59] consume token:true[2018-02-23 11:42:59] consume token:true[2018-02-23 11:42:59] consume token:true[2018-02-23 11:42:59] consume token:false[2018-02-23 11:42:59] consume token:false[2018-02-23 11:42:59] consume token:false[2018-02-23 11:42:59] consume token:false[2018-02-23 11:43:00] consume token:true[2018-02-23 11:43:00] consume token:true[2018-02-23 11:43:00] consume token:true[2018-02-23 11:43:00] consume token:false[2018-02-23 11:43:00] consume token:false
Synchronisation maître-esclave Redis , Opérations associées aux paramètres de séparation en lecture-écriture
Présente la méthode de MySQL pour reconstruire la table partitionne et conserve les données
PHP génère du contenu pertinent pour la classe RequestID unique
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!