PHP uses a token bucket algorithm based on Redis for traffic control

Source: Internet
Author: User
This article introduces PHP based on Redis, using the token bucket algorithm to achieve access traffic control, provide a complete algorithm description and demonstration examples, easy to learn to use.
Whenever the domestic long holidays or important festivals, the domestic scenic area or subway will be a sea of people, resulting in excessive load, some will use current limit measures, limit the number of entry, when the number of people in the area down to a certain value, and then allow access.

For example:
Maximum allowable number of M in the area
The current number of people in the area is N
Each entry into a person,n+1, when N = M , is not allowed to enter
Every leave a person,N-1, when N < M , allowed to enter
During the operation of the system, in the event of certain activities, the number of visitors will explode in a flash, causing the server to surge in instantaneous pressure and overload the system.

Of course, we can increase the server to share the pressure, first increase the server also need a certain amount of time to configure, and because of an activity to increase the server, the end of the activity of these server resources are wasted.

Therefore, we can reduce the server pressure by using the current limit method According to the type of business.

Unlike scenic limit flow, the system's access to the end of the time is very short , so we only need to know the average duration of each visit, set the maximum number of simultaneous access.

Token bucket algorithm

1. First, there is a token bucket, the bucket inside the token, the first token in the bucket is full (the number of tokens in the bucket can be set according to the server situation).

2. Each access takes a token from the bucket, and when the token in the bucket is 0, no further access is allowed.

3. Every once in a while, put a token, up to the inside of the barrel token. (depending on the actual situation, you can put a number of tokens at intervals, or fill the token bucket directly)

We can use the redis queue as a token bucket container, use Lpush (enqueue), Rpop (outof line), implement token join and consume operation.

TrafficShaper.class.php

<?php/** * PHP based on Redis using token bucket algorithm for traffic control * date:2018-02-23 * author:fdipzone * version:1.0 * * Descripton: * php based on Redi s uses the token bucket algorithm to achieve traffic control, using the Redis queue as the token bucket container, and the Enqueue (lpush) Outbound (Rpop) as token join and consume operations. * Func: * Public Add Add token * Public get get token * Public Reset token bucket * Private connect Create Redis connection */class Traffi  cshaper{//class start Private $_config;//Redis settings private $_redis;  Redis Object Private $_queue;    Token bucket private $_max; Maximum number of tokens/** * Initialize * @param Array $config redis Connection Settings */Public function __construct ($config, $queue, $max        ) {$this->_config = $config;        $this->_queue = $queue;        $this->_max = $max;    $this->_redis = $this->connect (); }/** * Add token * @param int $num number of tokens added * @return INT added */Public function Add ($num =0) {/        /Current number of remaining tokens $curnum = Intval ($this->_redis->lsize ($this->_queue));        Maximum number of tokens $maxnum = Intval ($this->_max); Calculate the maximum number of tokens that can be joinedNumber, cannot exceed the maximum number of tokens $num = $maxnum >= $curnum + $num?        $num: $maxnum-$curnum;            Add a token if ($num >0) {$token = Array_fill (0, $num, 1);            $this->_redis->lpush ($this->_queue, ... $token);        return $num;    } return 0; }/** * Gets token * @return Boolean/Public function get () {return $this->_redis->rpop ($this-& Gt;_queue)?    True:false;        }/** * Resets the token bucket, fills the token */Public function reset () {$this->_redis->delete ($this->_queue);    $this->add ($this->_max); /** * Create redis connection * @return Link */Private Function connect () {try{$redis = new Redi            S (); $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?>

Demo

<?php/** * Demo token join and consume */require ' TrafficShaper.class.php ';//redis connection settings $config = Array (    ' host ' = ' localhost ', c3/> ' Port ' = 6379,    ' index ' = 0,    ' auth ' + ', '    timeout ' = 1,    ' reserved ' = NULL,    ' Retry_interval ' + 100,);//token bucket container $queue = ' mycontainer ';//maximum number of tokens $max = 5;//Create Trafficshaper Object $otrafficshaper = new Traf Ficshaper ($config, $queue, $max);//Reset the token bucket to fill the token $otrafficshaper->reset ();//loop get token, only 5 tokens in the token bucket, so the last 3 times failed for ($i = 0; $i <8; $i + +) {    var_dump ($oTrafficShaper->get ());} Add 10 tokens, the maximum token is 5, so you can only add 5 $add_num = $oTrafficShaper->add, var_dump ($add _num);//loop get token, there are only 5 tokens in the token bucket. So last 1 times get failed for ($i =0; $i <6; $i + +) {    var_dump ($oTrafficShaper->get ());}? >

Output:

Boolean Trueboolean trueboolean trueboolean trueboolean trueboolean falseboolean falseboolean falseint 5boolean Trueboolean Trueboolean Trueboolean Trueboolean Trueboolean false

Adding token algorithms regularly

Periodically adding tokens, we can use the CRONTAB implementation to call the Add method every minute to add a number of tokens. Crontab can be used for reference: "Linux crontab timed Task command format and detailed example"

Crontab the minimum execution interval is 1 minutes, if the token in the token bucket has been consumed in the first few seconds, then the remaining 10 seconds of time, will not get the token, resulting in a longer waiting time for the user.

We can optimize the algorithm of adding tokens, instead of adding several tokens every few seconds in a minute, so that the tokens can be acquired every time in a minute.

The join token program for CRONTAB calls is as follows, automatically adding 3 tokens per second.

<?php/** * Timed task Add token */require ' TrafficShaper.class.php ';//redis connection setting $config = Array (    ' host ' = ' localhost ', c1/> ' Port ' = 6379,    ' index ' = 0,    ' auth ' + ', '    timeout ' = 1,    ' reserved ' = NULL,    ' Retry_interval ' + 100,);//token bucket container $queue = ' mycontainer ';//maximum number of tokens $max = 10;//number of tokens added per time interval $token_num = 3;//time interval, preferably 60 The number of integers, guaranteed to cover all the time in every minute $time_step = 1;//execution times $exec_num = (int) (60/$time _step);//Create Trafficshaper object $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);}? >

The simulated consumption program is as follows, consuming 2-8 tokens per second.

<?php/** * Simulates user access to consumption tokens, consumes several tokens per time interval */require ' TrafficShaper.class.php ';//redis connection settings $config = Array (    ' host ' = > ' localhost ',    ' port ' + 6379,    ' index ' = 0,    ' auth ' + ', '    timeout ' = 1,    ' Reserved ' = NULL,    ' retry_interval ' = 100, '//token bucket container $queue = ' mycontainer ';//maximum token $max = 10;//number of tokens randomly consumed per time interval Volume range $consume_token_range = Array (2, 8);//Interval $time_step = 1;//Create Trafficshaper Object $otrafficshaper = new Trafficshaper ($ Config, $queue, $max);//Resets the token bucket, fills the token $otrafficshaper->reset ();//performs token consumption 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);}? >

Demonstrate

Set up timed tasks to execute once per minute

* * * * * PHP/program path/cron_add.php >>/tmp/cron_add.log

Perform simulated consumption

PHP consume_demo.php

Execution Result:

[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 

Because the token bucket is full at first (the maximum number of tokens is 10), the previous 10 times can obtain the token, 10 times after the token consumed is greater than the number of tokens to limit access.
This article explains PHP based on Redis use token bucket algorithm to achieve traffic control, more relevant content please focus on PHP Chinese web.

Related recommendations:

Redis master-Slave synchronization, read and write separation settings related operations

Describes how MySQL rebuilds table partitions and preserves data

PHP generates a unique RequestID class of related content

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.