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. le nombre de personnes dans la zone diminue. Après avoir atteint une certaine valeur, l'entrée est autorisé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 qu'une personne entre, N+1, lorsque N = M, l'entrée n'est pas autorisée
Chaque fois qu'une personne sort, N-1, Lorsque N <, l'accès à est autorisé. Pendant le fonctionnement du système, si certaines activités sont rencontrées, le nombre de visiteurs va exploser. un instant, provoquant une montée en flèche instantanée de la pression du serveur, provoquant une surcharge du système.
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
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 :
<?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?>
Jeton de jointure périodique, nous pouvons utilisez l'implémentation Crontab, en appelant la méthode add pour ajouter plusieurs jetons chaque minute. 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" L'intervalle d'exécution minimum de crontab est de 1 minute si les jetons du compartiment de jetons ont été consommés dans le compartiment de jetons. premières secondes, le jeton ne peut pas être obtenu dans les dizaines de secondes restantes, ce qui oblige l'utilisateur à attendre longtemps.
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.<?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()); }?>
Le programme d'ajout de jetons appelé par crontab est le suivant, ajoutant automatiquement 3 jetons par seconde.
boolean trueboolean trueboolean trueboolean trueboolean trueboolean falseboolean falseboolean falseint 5boolean trueboolean trueboolean trueboolean trueboolean trueboolean false
La procédure de consommation de simulation est la suivante, consommant 2 à 8 jetons par seconde.
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.
Cet article explique le contenu pertinent de PHP utilisant l'algorithme de compartiment de jetons pour implémenter le contrôle du trafic basé sur Redis. Pour plus de contenu connexe, veuillez faire attention au site Web chinois de PHP.<?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); }?>
Recommandations associées : Comment créer une classe de code QR avec logo via php
* * * * * php /程序的路径/cron_add.php >> /tmp/cron_add.log
Explication détaillée de la reconstruction et de la conservation des partitions de table MySQL Méthode data
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
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!