Heim >Datenbank >Redis >So lösen Sie mit PHP+Redis das Problem des Überverkaufs von Produkten bei hoher Parallelität

So lösen Sie mit PHP+Redis das Problem des Überverkaufs von Produkten bei hoher Parallelität

WBOY
WBOYnach vorne
2023-05-26 15:31:061805Durchsuche

Bei einigen E-Commerce-Websites mit einer bestimmten Anzahl von Benutzern ist der Druck auf die Datenbank sehr groß, wenn sie einfach relationale Datenbanken (wie MySQL, Oracle) für Eilkäufe verwenden, und wenn der Datenbanksperrmechanismus nicht verwendet wird Nun, es wird auch zum Problem überverkaufter Produkte und Gutscheine führen. Das gleiche Problem trat auch bei meinem Unternehmen auf, als das Problem auftrat. Da ich häufig Redis verwende, habe ich vor, dieses Problem zu lösen . Nutzen Sie die Hochleistungs- und Transaktionsfunktionen von Redis, um das Problem zu lösen, dass Online-Gutscheine durch Überbestände aufgebraucht werden. Nachfolgend gebe ich die erste Version des Pseudocodes an, mit dem ich dieses Problem vorübergehend gelöst habe, indem ich einige Details entfernte:

/**
 * 抢优惠券(秒杀)
 * @param int $couponId 商品ID
 * @param int $uid 用户ID
 * @return bool
 */
function secKill($couponId, $uid)
{
    //1.初始化Redis连接
    $redis = new Redis();
    if (!$redis->connect('127.0.0.1', 6379)) {
        trigger_error('Redis连接出错!!!', E_USER_ERROR);
    } else {
        echo &#39;连接正常<br>&#39;;
    }

    //秒杀商品的库存key
    $key = &#39;secKill:&#39;.$couponId.&#39;:stock&#39;;
    $redis->watch($key);

    //获取库存
    $stock = $redis->get($key);

    //秒杀未开始,表示库存为null
    if (!$stock && !is_numeric($stock)) {
        echo &#39;秒杀未开始&#39;;
        return false;
    }

    //判断库存,如果库存大于0,则减库存,将该成功秒杀用户加入哈希表,如果小于等于0,秒杀结束
    if ($stock <= 0) {
        echo &#39;秒杀已结束&#39;;
        return false;
    }

    //用户已经成功秒杀过一次了,不允许再次参与秒杀
    if ($redis->sIsMember(&#39;secKill:&#39;.$couponId.&#39;:uid&#39;, $uid)) {
        echo &#39;秒杀失败&#39;;
        return false;
    }

    //代码走到这里,说明该用户是第一次参与秒杀,将库存减一,然后把这个人放到已抢到的集合表
    $redisMulti = $redis->multi();
    $redisMulti->decr($key);
    $redisMulti->sAdd(&#39;secKill:&#39;.$couponId.&#39;:uid&#39;, $uid);
    $result = $redisMulti->exec();

    if (empty($result)) {//事务被取消
        echo &#39;秒杀失败&#39;;
        return false;
    }

    //抢券成功,将优惠券ID和UID放入到队列中,由一个单独的进程队列来消费队列里的数据,向用户推送抢到的优惠券
    $redis->lPush(&#39;couponOrder&#39;, $couponId.&#39;+&#39;.$uid);

    return true;
}

$couponId = 11211;
$uid      = mt_rand(1, 100);
secKill($couponId, $uid);

Zuerst habe ich simuliert Setzen Sie den Coupon-Bestand mit der Coupon-ID 11211 auf 10.

So lösen Sie mit PHP+Redis das Problem des Überverkaufs von Produkten bei hoher Parallelität

Dann verwenden wir das AB-Tool, um 1000 Anfragen und 50 Parallelität zum Testen zu simulieren.

ab -n 1000 -c 50 www.test.com/

Und die verbleibende Anzahl an Coupons ist ebenfalls 0, also keine negative Zahl mehr

So lösen Sie mit PHP+Redis das Problem des Überverkaufs von Produkten bei hoher Parallelität

Gleichzeitig werden auch die UID-Informationen von 10 Benutzern in der Benutzercoupon-Sammlung gespeichert.

So lösen Sie mit PHP+Redis das Problem des Überverkaufs von Produkten bei hoher Parallelität

Der obige Code löst zwei Probleme:

So lösen Sie mit PHP+Redis das Problem des Überverkaufs von Produkten bei hoher ParallelitätEs löst das Problem einer großen Anzahl sofortiger Abfragen an die Datenbank, was einen großen Druck auf die Datenbank ausübt. Der Datenverkehr wird in der Redis-Cache-Ebene abgefangen

    Das Problem, dass Coupons durch Überbestände weggeschnappt werden, wurde gelöst
  • Dieser Code weist jedoch auch bestimmte Probleme auf:
  • verwendet nicht den Redis-Verbindungspool und das häufige Erstellen neuer Redis hat bestimmte Auswirkungen auf die Leistung

    Aufgrund der Verwendung von Transaktionen gelingt es nur einem Benutzer, Gutscheine in jeder gleichzeitigen Anfrage abzurufen. Andere Benutzer in der gleichzeitigen Anfrage schlagen fehl und können nur auf die zweite Parallelität warten.
  1. Es ist auch die durch die Transaktion verursachte Bestandsvermächtnis . Wenn es 10 Produkte gibt, 1000 Anfragen mit jeweils 200 gleichzeitigen Anfragen, werden 1000 Anfragen abgeschlossen, aber nur 5 Benutzer werden es erfolgreich abrufen. Wenn es keine weiteren Anfragen gibt, sind noch 5 Exemplare im Inventar übrig
  2. Tipps: Wenn der Coupon in der Verbrauchswarteschlange nicht ausgestellt wird, notieren Sie ihn unbedingt sofort und benachrichtigen Sie den Betriebsleiter per SMS, um zu prüfen, ob er erneut gesendet oder manuell im Hintergrund an den Benutzer weitergeleitet werden kann.

Das obige ist der detaillierte Inhalt vonSo lösen Sie mit PHP+Redis das Problem des Überverkaufs von Produkten bei hoher Parallelität. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen