Maison > Article > développement back-end > Comment utiliser le verrouillage Redis pour résoudre des problèmes de concurrence élevée
Le problème de la haute concurrence est un problème que nous rencontrons souvent, alors comment résoudre le problème de la haute concurrence ? Cet article présente l'utilisation des verrous Redis pour résoudre des problèmes de concurrence élevée. Jetons un coup d'œil.
Ici, nous utilisons principalement la commande setnx de Redis pour gérer une simultanéité élevée.
setnx a deux paramètres. Le premier paramètre représente la clé. Le deuxième paramètre représente la valeur. Si la clé actuelle n'existe pas, la clé actuelle sera insérée, en utilisant le deuxième paramètre comme valeur. Retour 1. Si la clé actuelle existe, 0 sera renvoyé.
Créer un tableau d'inventaire
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
Définir l'inventaire initial sur 10
Créer un tableau de commande
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 sans verrouillage
$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); } }
Le test ab a simulé la concurrence et a révélé que l'inventaire était correct.
mysql> select * from storage; +----+--------+ | id | number | +----+--------+ | 1 | 0 | +----+--------+ 1 row in set (0.00 sec)
En regardant le tableau des commandes
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)
J'ai découvert que plusieurs commandes fonctionnent sur les mêmes données d'inventaire, ce qui peut entraîner des conditions de survente.
Modifiez le code et ajoutez un verrouillage Redis pour le contrôle des données
<?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 { //加锁不成功执行其他操作。 }
Effectuez à nouveau le ab
test et vérifiez les résultats du test
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)
Il s'avère que la table de commande n'opère pas le même inventaire La situation des données. Par conséquent, l’utilisation du verrouillage Redis peut gérer efficacement une concurrence élevée.
En fait, il n'est pas nécessaire de juger le délai d'expiration lors du verrouillage. Ici, afin d'éviter une impasse, nous ajoutons un jugement sur le délai d'expiration. Supprimez activement le verrou lorsqu'il expire.
Recommandations associées :
php utilise des verrous de fichiers pour résoudre les problèmes de concurrence élevée
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!