Das Problem der hohen Parallelität ist ein Problem, auf das wir häufig stoßen. Wie kann das Problem der hohen Parallelität gelöst werden? In diesem Artikel wird die Verwendung von Redis-Sperren zur Lösung von Problemen mit hoher Parallelität vorgestellt.
Hier verwenden wir hauptsächlich den Befehl setnx von Redis, um eine hohe Parallelität zu bewältigen.
setnx hat zwei Parameter. Der erste Parameter stellt den Schlüssel dar. Der zweite Parameter stellt den Wert dar. Wenn der aktuelle Schlüssel nicht vorhanden ist, wird der aktuelle Schlüssel eingefügt, wobei der zweite Parameter als Wert verwendet wird. Rückkehr 1. Wenn der aktuelle Schlüssel existiert, wird 0 zurückgegeben.
Bestandstabelle erstellen
CREATE TABLE `storage` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `number` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
Anfangsbestand auf 10 setzen
Bestelltabelle erstellen
CREATE TABLE `order` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `number` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
Test ohne Sperre
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root'); $sql="select `number` from storage where id=1 limit 1"; $res = $pdo->query($sql)->fetch(); $number = $res['number']; if($number>0) { $sql ="insert into `order` VALUES (null,$number)"; $order_id = $pdo->query($sql); if($order_id) { $sql="update storage set `number`=`number`-1 WHERE id=1"; $pdo->query($sql); } }
ab Der Test simulierte Parallelität und stellte fest, dass die Bestandsaufnahme korrekt war.
mysql> select * from storage; +----+--------+ | id | number | +----+--------+ | 1 | 0 | +----+--------+ 1 row in set (0.00 sec)
Beim Blick auf die Bestelltabelle
mysql> select * from `order`; +----+--------+ | id | number | +----+--------+ | 1 | 10 | | 2 | 10 | | 3 | 9 | | 4 | 7 | | 5 | 6 | | 6 | 5 | | 7 | 5 | | 8 | 5 | | 9 | 4 | | 10 | 1 | +----+--------+ 10 rows in set (0.00 sec)
wurde festgestellt, dass mehrere Bestellungen mit denselben Bestandsdaten ausgeführt werden, was zu überverkauften Konditionen führen kann.
Ändern Sie den Code und fügen Sie eine Redis-Sperre zur Datenkontrolle hinzu
<?php /** * Created by PhpStorm. * User: daisc * Date: 2018/7/23 * Time: 14:45 */ class Lock { private static $_instance ; private $_redis; private function __construct() { $this->_redis = new Redis(); $this->_redis ->connect('127.0.0.1'); } public static function getInstance() { if(self::$_instance instanceof self) { return self::$_instance; } return self::$_instance = new self(); } /** * @function 加锁 * @param $key 锁名称 * @param $expTime 过期时间 */ public function set($key,$expTime) { //初步加锁 $isLock = $this->_redis->setnx($key,time()+$expTime); if($isLock) { return true; } else { //加锁失败的情况下。判断锁是否已经存在,如果锁存在切已经过期,那么删除锁。进行重新加锁 $val = $this->_redis->get($key); if($val&&$val<time()) { $this->del($key); } return $this->_redis->setnx($key,time()+$expTime); } } /** * @param $key 解锁 */ public function del($key) { $this->_redis->del($key); } } $pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root'); $lockObj = Lock::getInstance(); //判断是能加锁成功 if($lock = $lockObj->set('storage',10)) { $sql="select `number` from storage where id=1 limit 1"; $res = $pdo->query($sql)->fetch(); $number = $res['number']; if($number>0) { $sql ="insert into `order` VALUES (null,$number)"; $order_id = $pdo->query($sql); if($order_id) { $sql="update storage set `number`=`number`-1 WHERE id=1"; $pdo->query($sql); } } //解锁 $lockObj->del('storage'); } else { //加锁不成功执行其他操作。 }
Führen Sie den ab
Test erneut durch und überprüfen Sie die Testergebnisse
mysql> select * from `order`; +----+--------+ | id | number | +----+--------+ | 1 | 10 | | 2 | 9 | | 3 | 8 | | 4 | 7 | | 5 | 6 | | 6 | 5 | | 7 | 4 | | 8 | 3 | | 9 | 2 | | 10 | 1 | +----+--------+ 10 rows in set (0.00 sec)
Sie haben festgestellt, dass die Bestelltabelle nicht funktioniert die gleichen Bestandsdaten. Daher kann die Verwendung der Redis-Sperre eine hohe Parallelität effektiv bewältigen.
Tatsächlich besteht keine Notwendigkeit, die Ablaufzeit beim Sperren zu beurteilen. Um einen Deadlock zu vermeiden, fügen wir hier eine Beurteilung der Ablaufzeit hinzu. Löschen Sie die Sperre aktiv, wenn sie abläuft.
Verwandte Empfehlungen:
PHP verwendet Dateisperren, um Probleme mit hoher Parallelität zu lösen
Das obige ist der detaillierte Inhalt vonSo verwenden Sie die Redis-Sperre, um Probleme mit hoher Parallelität zu lösen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!