Heim > Backend-Entwicklung > PHP-Tutorial > So verwenden Sie die Redis-Sperre, um Probleme mit hoher Parallelität zu lösen

So verwenden Sie die Redis-Sperre, um Probleme mit hoher Parallelität zu lösen

不言
Freigeben: 2023-04-04 06:46:02
Original
3377 Leute haben es durchsucht

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
Nach dem Login kopieren

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
Nach dem Login kopieren

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);
    }
}
Nach dem Login kopieren

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)
Nach dem Login kopieren

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)
Nach dem Login kopieren

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
{
    //加锁不成功执行其他操作。
}
Nach dem Login kopieren

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)
Nach dem Login kopieren

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

Wie wäre es mit der Verwendung von Redis zum Speichern von PHP-Sitzungen? Lösen Sie das Problem der Parallelität und Konsistenz

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!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage