1. Concurrent access restriction issues
For scenarios where concurrent access is restricted to the same user, users can request multiple requests successfully if the user requests multiple times and the server handles no lock limit.
For example, redemption coupons, if the user at the same time and the exchange of the code, without the lock limit, the user can use the same redemption code at the same time to redeem a number of coupons.
The pseudo code is as follows:
If A (can be changed) B (perform redemption) C (update to redemption) D (end)
If the user carries out the interchange code, it can be judged by the redemption (a), since a redemption (B) must be performed before it is updated to the Redemption (C). Therefore, if the user has a number of requests before an update to a redemption, these requests can be executed successfully.
2. Concurrent Access Throttling methods
The use of file locks allows for concurrent access restrictions, but for distributed architecture environments, using file locks does not guarantee concurrent access restrictions for multiple servers.
Redis is an open source API that is written in ANSI C, supports the web, can be persisted in memory, key-value databases, and provides multiple languages.
This article uses its Setnx method to implement the distributed lock function. setnx is Set it Not eXists.
Insert succeeds when key value does not exist (acquires lock succeeds), insert fails if key value already exists (get lock failed)
redislock.class.php
<?php/** * Redis lock Operation class * date:2016-06-30 * author:fdipzone * ver:1.0 * * FUNC: * Public lock get lock * Pub LIC unlock release lock * Private Connect connection */class Redislock {//class start Private $_config; Private $_redis; /** * Initialize * @param Array $config redis Connection Settings */Public function __construct ($config =array ()) {$this-&G T;_config = $config; $this->_redis = $this->connect (); }/** * Get lock * @param String $key Lock ID * @param Int $expire Lock Expiry time * @return Boolean */P ublic function Lock ($key, $expire =5) {$is _lock = $this->_redis->setnx ($key, Time () + $expire); Cannot get lock if (! $is _lock) {//Determine if the lock expires $lock _time = $this->_redis->get ($key); Lock expired, delete lock, retrieve if (time () > $lock _time) {$this->unlock ($key); $is _lock = $this->_redis->setnx ($key, Time () + $expire); }} return $is _locK? True:false; }/** * Release lock * @param String $key Lock identifier * @return Boolean/Public Function unlock ($key) {RET Urn $this->_redis->del ($key); /** * 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
<?phprequire ' RedisLock.class.php '; $config = Array ( ' host ' = ' localhost ', ' port ' = 6379, ' Index ' = 0, ' auth ' + ', ' timeout ' = 1, ' reserved ' = NULL, ' retry_interval ' and 100, ;//Create Redislock Object $oredislock = new Redislock ($config);//define lock identity $key = ' mylock ';//get lock $is_lock = $oRedisLock->lock ($key , if ($is _lock) { echo ' get lock success<br> '; Echo ' do sth. <br> '; Sleep (5); Echo ' success<br> '; $oRedisLock->unlock ($key); Get lock failed } else{ echo ' request too frequently<br> '; >
test method:
Open two different browsers while accessing demo.php in A/b
If the first access will get to the lock
Output
Get lock success
Do sth.
Success
Another acquisition lock failure will output the request too frequently
Ensure that only one access is valid at the same time, effectively restricting concurrent access.
to avoid a sudden system error that results in a deadlock, an expiration time is added when the lock is acquired, and if the expiration time is exceeded, the lock is released even if it is locked, avoiding the problem caused by the deadlock.
SOURCE Download Address: Click to view
1. Concurrent access restriction issues
For scenarios where concurrent access is restricted to the same user, users can request multiple requests successfully if the user requests multiple times and the server handles no lock limit.
For example, redemption coupons, if the user at the same time and the exchange of the code, without the lock limit, the user can use the same redemption code at the same time to redeem a number of coupons.
The pseudo code is as follows:
If A (can be changed) B (perform redemption) C (update to redemption) D (end)
If the user carries out the interchange code, it can be judged by the redemption (a), since a redemption (B) must be performed before it is updated to the Redemption (C). Therefore, if the user has a number of requests before an update to a redemption, these requests can be executed successfully.
2. Concurrent Access Throttling methods
The use of file locks allows for concurrent access restrictions, but for distributed architecture environments, using file locks does not guarantee concurrent access restrictions for multiple servers.
Redis is an open source API that is written in ANSI C, supports the web, can be persisted in memory, key-value databases, and provides multiple languages.
This article uses its Setnx method to implement the distributed lock function. setnx is Set it Not eXists.
Insert succeeds when key value does not exist (acquires lock succeeds), insert fails if key value already exists (get lock failed)
RedisLock.class.php
<?php/** * Redis lock Operation class * date:2016-06-30 * author:fdipzone * ver:1.0 * * FUNC: * Public lock get lock * Pub LIC unlock release lock * Private Connect connection */class Redislock {//class start Private $_config; Private $_redis; /** * Initialize * @param Array $config redis Connection Settings */Public function __construct ($config =array ()) {$this-&G T;_config = $config; $this->_redis = $this->connect (); }/** * Get lock * @param String $key Lock ID * @param Int $expire Lock Expiry time * @return Boolean */P ublic function Lock ($key, $expire =5) {$is _lock = $this->_redis->setnx ($key, Time () + $expire); Cannot get lock if (! $is _lock) {//Determine if the lock expires $lock _time = $this->_redis->get ($key); Lock expired, delete lock, retrieve if (time () > $lock _time) {$this->unlock ($key); $is _lock = $this->_redis->setnx ($key, Time () + $expire); }} return $is _locK? True:false; }/** * Release lock * @param String $key Lock identifier * @return Boolean/Public Function unlock ($key) {RET Urn $this->_redis->del ($key); /** * 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
<?phprequire ' RedisLock.class.php '; $config = Array ( ' host ' = ' localhost ', ' port ' = 6379, ' Index ' = 0, ' auth ' + ', ' timeout ' = 1, ' reserved ' = NULL, ' retry_interval ' and 100, ;//Create Redislock Object $oredislock = new Redislock ($config);//define lock identity $key = ' mylock ';//get lock $is_lock = $oRedisLock->lock ($key , if ($is _lock) { echo ' get lock success<br> '; Echo ' do sth. <br> '; Sleep (5); Echo ' success<br> '; $oRedisLock->unlock ($key); Get lock failed } else{ echo ' request too frequently<br> '; >
test method:
Open two different browsers while accessing demo.php in A/b
If the first access will get to the lock
Output
Get lock success
Do sth.
Success
Another acquisition lock failure will output the request too frequently
Ensure that only one access is valid at the same time, effectively restricting concurrent access.
to avoid a sudden system error that results in a deadlock, an expiration time is added when the lock is acquired, and if the expiration time is exceeded, the lock is released even if it is locked, avoiding the problem caused by the deadlock.
The above is PHP using Redis lock limit concurrent access to the content of the class, more relevant content please pay attention to topic.alibabacloud.com (www.php.cn)!