For some scenarios where concurrent access to the same user needs to be restricted, if the user requests are concurrent multiple times, but the server does not have the lock restriction, the user can successfully request multiple times.
1. restrictions on concurrent access
For some scenarios where concurrent access to the same user needs to be restricted, if the user requests are concurrent multiple times, but the server does not have the lock restriction, the user can successfully request multiple times.
For example, if you submit a redemption code at the same time without any lock restrictions, you can use the same redemption code to redeem multiple coupons at the same time.
The pseudocode is as follows:
If A (yes) B (execute redemption) C (updated to "redeemed") D (ended)
If you submit A redemption code concurrently, you can obtain the result (A), because A redemption code (B) must be executed before it is updated to "C ). Therefore, if you have many requests before an update is received as a replacement, these requests can be successfully executed.
2. restrictions on concurrent access
The use of file locks can limit concurrent access. However, in a distributed architecture, the use of file locks cannot guarantee the limit on concurrent access to multiple servers.
Redis is an open-source log-type and Key-Value database written in ansi c language that supports network, memory-based persistence, and provides APIs in multiple languages.
This article uses the setnx method to implement the distributed lock function. Setnx is Set it Not eXists.
If the key value does not exist, the insertion is successful (the lock is obtained successfully). if the key value already exists, the insertion fails (the lock is obtained successfully)
RedisLock. class. php
_ Config = $ config; $ this-> _ redis = $ this-> connect ();} /*** obtain the lock * @ param String $ key lock identifier * @ param Int $ expire lock expiration time * @ return Boolean */public function lock ($ key, $ expire = 5) {$ is_lock = $ this-> _ redis-> setnx ($ key, time () + $ expire); // you cannot obtain the lock if (! $ Is_lock) {// Determine whether the lock has expired $ lock_time = $ this-> _ redis-> get ($ key); // if the lock has expired, delete the lock, re-obtain 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) {return $ this-> _ redis-> del ($ key);}/*** create a redis connection * @ 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-> _ confi G ['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
'Localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry _ interval' => 100,); // Create a redislock object $ oRedisLock = new RedisLock ($ config); // define the lock identifier $ key = 'mylock '; // get the lock $ is_lock = $ oRedisLock-> lock ($ key, 10); if ($ is_lock) {echo 'get lock success
'; Echo 'do ..
'; Sleep (5); echo' success
'; $ ORedisLock-> unlock ($ key); // failed to get the lock} else {echo 'request too frequently
';}?>
Test method:
Open two different browsers and access demo. php in A and B.
If the first access is successful, the lock will be obtained.
Output
Get lock success
Do something ..
Success
If the other fails to obtain the lock, the request too frequently will be output.
Ensure that only one access is valid at a time, and effectively restrict concurrent access.
To avoid deadlocks caused by sudden system errors, an expiration time is added when the lock is obtained. if the expiration time is exceeded, the lock is released even when the lock status is locked to avoid problems caused by deadlocks.
Source code: Click to view
1. restrictions on concurrent access
For some scenarios where concurrent access to the same user needs to be restricted, if the user requests are concurrent multiple times, but the server does not have the lock restriction, the user can successfully request multiple times.
For example, if you submit a redemption code at the same time without any lock restrictions, you can use the same redemption code to redeem multiple coupons at the same time.
The pseudocode is as follows:
If A (yes) B (execute redemption) C (updated to "redeemed") D (ended)
If you submit A redemption code concurrently, you can obtain the result (A), because A redemption code (B) must be executed before it is updated to "C ). Therefore, if you have many requests before an update is received as a replacement, these requests can be successfully executed.
2. restrictions on concurrent access
The use of file locks can limit concurrent access. However, in a distributed architecture, the use of file locks cannot guarantee the limit on concurrent access to multiple servers.
Redis is an open-source log-type and Key-Value database written in ansi c language that supports network, memory-based persistence, and provides APIs in multiple languages.
This article uses the setnx method to implement the distributed lock function. Setnx is Set it Not eXists.
If the key value does not exist, the insertion is successful (the lock is obtained successfully). if the key value already exists, the insertion fails (the lock is obtained successfully)
RedisLock. class. php
_ Config = $ config; $ this-> _ redis = $ this-> connect ();} /*** obtain the lock * @ param String $ key lock identifier * @ param Int $ expire lock expiration time * @ return Boolean */public function lock ($ key, $ expire = 5) {$ is_lock = $ this-> _ redis-> setnx ($ key, time () + $ expire); // you cannot obtain the lock if (! $ Is_lock) {// Determine whether the lock has expired $ lock_time = $ this-> _ redis-> get ($ key); // if the lock has expired, delete the lock, re-obtain 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) {return $ this-> _ redis-> del ($ key);}/*** create a redis connection * @ 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-> _ con Fig ['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
'Localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry _ interval' => 100,); // Create a redislock object $ oRedisLock = new RedisLock ($ config); // define the lock identifier $ key = 'mylock '; // get the lock $ is_lock = $ oRedisLock-> lock ($ key, 10); if ($ is_lock) {echo 'get lock success
'; Echo 'do ..
'; Sleep (5); echo' success
'; $ ORedisLock-> unlock ($ key); // failed to get the lock} else {echo 'request too frequently
';}?>
Test method:
Open two different browsers and access demo. php in A and B.
If the first access is successful, the lock will be obtained.
Output
Get lock success
Do something ..
Success
If the other fails to obtain the lock, the request too frequently will be output.
Ensure that only one access is valid at a time, and effectively restrict concurrent access.
To avoid deadlocks caused by sudden system errors, an expiration time is added when the lock is obtained. if the expiration time is exceeded, the lock is released even when the lock status is locked to avoid problems caused by deadlocks.
The above is php's use of the redis lock to limit the number of concurrent class content. For more information, please follow the PHP Chinese network (www.php1.cn )!