Für einige Szenarien, in denen der gleichzeitige Zugriff durch denselben Benutzer eingeschränkt werden muss, wenn die Benutzer haben viele gleichzeitige Anforderungszeiten und es gibt keine Sperrbeschränkung für die Serververarbeitung, und Benutzer können mehrere Male erfolgreich Anforderungen stellen.
Wenn der Benutzer beispielsweise beim Einlösen von Gutscheinen den Einlösungscode gleichzeitig einreicht, kann der Benutzer denselben Einlösungscode verwenden, um mehrere Gutscheine gleichzeitig einzulösen, ohne Einschränkungen zu sperren.
Der Pseudocode lautet wie folgt:
if A(可以换领) B(执行换领) C(更新为已换领)D(结束)
Wenn Benutzer gleichzeitig Einlösecodes einreichen, werden alle das Urteil fällen, dass sie einlösen können (A), weil Es muss eine Ausführung erfolgen. Nach dem Einlösen (B) wird es auf eingelöst (C) aktualisiert. Wenn der Benutzer daher mehrere Anfragen stellt, bevor eine Aktualisierung als eingelöst vorliegt, können diese Anfragen erfolgreich ausgeführt werden.
Durch die Verwendung von Dateisperren können gleichzeitige Zugriffsbeschränkungen erreicht werden. In Umgebungen mit verteilter Architektur kann die Verwendung von Dateisperren jedoch nicht die Sicherheit mehrerer Server gewährleisten. Gleichzeitige Zugriffsbeschränkungen.
Redis ist eine Open-Source-Protokoll-Schlüsselwertdatenbank, die in der Sprache ANSI C geschrieben ist, Netzwerke unterstützt, speicherbasiert und persistent sein kann und APIs in mehreren Sprachen bereitstellt.
In diesem Artikel wird die setnx-Methode verwendet, um die verteilte Sperrfunktion zu implementieren. setnx ist Set es Nnicht eXist.
Wenn der Schlüsselwert nicht vorhanden ist, ist das Einfügen erfolgreich (die Sperre wurde erfolgreich erworben). Wenn der Schlüsselwert bereits vorhanden ist, schlägt das Einfügen fehl (der Sperrenerwerb schlägt fehl)
RedisLock.class.php
<?php/** * Redis锁操作类 * Date: 2016-06-30 * Author: fdipzone * Ver: 1.0 * * Func: * public lock 获取锁 * public unlock 释放锁 * private connect 连接 */class RedisLock { // class start private $_config; private $_redis; /** * 初始化 * @param Array $config redis连接设定 */ public function __construct($config=array()){ $this->_config = $config; $this->_redis = $this->connect(); } /** * 获取锁 * @param String $key 锁标识 * @param Int $expire 锁过期时间 * @return Boolean */ public function lock($key, $expire=5){ $is_lock = $this->_redis->setnx($key, time()+$expire); // 不能获取锁 if(!$is_lock){ // 判断锁是否过期 $lock_time = $this->_redis->get($key); // 锁已过期,删除锁,重新获取 if(time()>$lock_time){ $this->unlock($key); $is_lock = $this->_redis->setnx($key, time()+$expire); } } return $is_lock? true : false; } /** * 释放锁 * @param String $key 锁标识 * @return Boolean */ public function unlock($key){ return $this->_redis->del($key); } /** * 创建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?>
demo.php
<?php require 'RedisLock.class.php'; $config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, ); // 创建redislock对象$oRedisLock = new RedisLock($config); // 定义锁标识$key = 'mylock'; // 获取锁$is_lock = $oRedisLock->lock($key, 10); if($is_lock){ echo 'get lock success<br>'; echo 'do sth..<br>'; sleep(5); echo 'success<br>'; $oRedisLock->unlock($key); // 获取锁失败 } else{ echo 'request too frequently<br>'; }?>
Testmethode:
Öffnen Sie zwei verschiedene Browser und greifen Sie gleichzeitig auf demo.php in A und B zu
Wenn Sie zuerst darauf zugreifen, wird die Sperre erhalten
Ausgabe
Sperre erfolgreich erhalten
etwas tun.
Erfolgreich sein
Wenn ein anderer die Sperre nicht erhalten kann, wird Anfrage zu häufig ausgegeben
Um sicherzustellen, dass nur ein Zugriff gleichzeitig gültig ist, beschränken Sie den gültigen gleichzeitigen Zugriff.
Um einen Deadlock durch plötzliche Systemfehler zu vermeiden, wird beim Erwerb der Sperre eine Ablaufzeit hinzugefügt. Wenn die Ablaufzeit abgelaufen ist, wird die Sperre auch im gesperrten Zustand aufgehoben um ein Deadlock-Problem zu vermeiden.
Quellcode-Download-Adresse: Zum Anzeigen klicken
Für einige Benutzer, die dies benötigen Parallelität begrenzen Wenn der Benutzer im Zugriffsszenario mehrere gleichzeitige Anforderungen stellt und der Serverprozess keine Sperrbeschränkungen hat, kann der Benutzer mehrere erfolgreiche Anforderungen stellen.
Wenn der Benutzer beispielsweise beim Einlösen von Gutscheinen den Einlösungscode gleichzeitig einreicht, kann der Benutzer denselben Einlösungscode verwenden, um mehrere Gutscheine gleichzeitig einzulösen, ohne Einschränkungen zu sperren.
Der Pseudocode lautet wie folgt:
if A(可以换领) B(执行换领) C(更新为已换领)D(结束)
Wenn Benutzer gleichzeitig Einlösecodes einreichen, werden alle das Urteil fällen, dass sie einlösen können (A), weil Es muss eine Ausführung erfolgen. Nach dem Einlösen (B) wird es auf eingelöst (C) aktualisiert. Wenn der Benutzer daher mehrere Anfragen stellt, bevor eine Aktualisierung als eingelöst vorliegt, können diese Anfragen erfolgreich ausgeführt werden.
Durch die Verwendung von Dateisperren können gleichzeitige Zugriffsbeschränkungen erreicht werden. In Umgebungen mit verteilter Architektur kann die Verwendung von Dateisperren jedoch nicht die Sicherheit mehrerer Server gewährleisten. Gleichzeitige Zugriffsbeschränkungen.
Redis ist eine Open-Source-Protokoll-Schlüsselwertdatenbank, die in der Sprache ANSI C geschrieben ist, Netzwerke unterstützt, speicherbasiert und persistent sein kann und APIs in mehreren Sprachen bereitstellt.
In diesem Artikel wird die setnx-Methode verwendet, um die verteilte Sperrfunktion zu implementieren. setnx ist Set es Nnicht eXist.
Wenn der Schlüsselwert nicht vorhanden ist, ist das Einfügen erfolgreich (die Sperre wurde erfolgreich erworben). Wenn der Schlüsselwert bereits vorhanden ist, schlägt das Einfügen fehl (der Sperrenerwerb schlägt fehl)
RedisLock.class.php
<?php/** * Redis锁操作类 * Date: 2016-06-30 * Author: fdipzone * Ver: 1.0 * * Func: * public lock 获取锁 * public unlock 释放锁 * private connect 连接 */class RedisLock { // class start private $_config; private $_redis; /** * 初始化 * @param Array $config redis连接设定 */ public function __construct($config=array()){ $this->_config = $config; $this->_redis = $this->connect(); } /** * 获取锁 * @param String $key 锁标识 * @param Int $expire 锁过期时间 * @return Boolean */ public function lock($key, $expire=5){ $is_lock = $this->_redis->setnx($key, time()+$expire); // 不能获取锁 if(!$is_lock){ // 判断锁是否过期 $lock_time = $this->_redis->get($key); // 锁已过期,删除锁,重新获取 if(time()>$lock_time){ $this->unlock($key); $is_lock = $this->_redis->setnx($key, time()+$expire); } } return $is_lock? true : false; } /** * 释放锁 * @param String $key 锁标识 * @return Boolean */ public function unlock($key){ return $this->_redis->del($key); } /** * 创建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?>
demo.php
<?phprequire 'RedisLock.class.php'; $config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, ); // 创建redislock对象$oRedisLock = new RedisLock($config); // 定义锁标识$key = 'mylock'; // 获取锁$is_lock = $oRedisLock->lock($key, 10); if($is_lock){ echo 'get lock success<br>'; echo 'do sth..<br>'; sleep(5); echo 'success<br>'; $oRedisLock->unlock($key); // 获取锁失败 } else{ echo 'request too frequently<br>'; }?>
Testmethode:
Öffnen Sie zwei verschiedene Browser und greifen Sie gleichzeitig auf demo.php in A und B zu
Wenn Sie zuerst darauf zugreifen, wird die Sperre erhalten
Ausgabe
Sperre erfolgreich erhalten
etwas tun.
Erfolg haben
Wenn ein anderer die Sperre nicht erhalten kann, wird eine Anfrage zu häufig ausgegeben
Um sicherzustellen, dass nur ein Zugriff gleichzeitig gültig ist, beschränken Sie den gültigen gleichzeitigen Zugriff.
Um einen Deadlock durch plötzliche Systemfehler zu vermeiden, wird beim Erwerb der Sperre eine Ablaufzeit hinzugefügt. Wenn die Ablaufzeit abgelaufen ist, wird die Sperre auch im gesperrten Zustand aufgehoben um ein Deadlock-Problem zu vermeiden.
Das Obige ist der Inhalt von PHP, der die Redis-Sperre verwendet, um den gleichzeitigen Zugriff einzuschränken. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php .cn)!