


So verhindern Sie, dass der Produktbestand unter Bedingungen hoher Parallelität in PHP überverkauft wird
Dieser Artikel vermittelt Ihnen relevantes Wissen über PHP. Er stellt hauptsächlich verwandte Probleme zur Verhinderung überverkaufter Warenbestände unter Bedingungen hoher Parallelität dar. Er löst hauptsächlich den Druck, der durch hohe Parallelität auf der Datenbank entsteht, und wie das Problem des Wettbewerbs gelöst werden kann Ich hoffe, dass es für alle hilfreich ist.
Sie können die auf diesem Artikel basierenden Testfälle unter „php High Concurrency Test: Fallstudie zur Verhinderung von Überverkäufen von Lagerbeständen“ anzeigen. [Empfohlenes Lernen: „PHP-Tutorial“]
Im Mall-System sind Eilverkäufe und Flash-Sales sehr häufige Marketingszenarien. Innerhalb eines bestimmten Zeitraums besuchen viele Benutzer das Einkaufszentrum, um dort Bestellungen aufzugeben Es gibt zwei Hauptprobleme, die gelöst werden müssen:
Der Druck hoher Parallelität auf die Datenbank;
Wie man den überverkauften Warenbestand im Wettbewerb löst; Die Datenbank
Bei der ersten Frage wird Caching verwendet, um den direkten Betrieb der Datenbank zu vermeiden, z. B. die Verwendung von Redis. Wie löst man das Problem überverkaufter Produktbestände in einer Wettbewerbssituation?
Bei der zweiten Frage muss man sich auf die Erklärung konzentrieren. Herkömmliche Schreibmethode: Fragen Sie den Lagerbestand des entsprechenden Produkts ab, stellen Sie fest, ob die Lagerbestandsmenge größer als 0 ist, und führen Sie dann Vorgänge wie das Generieren einer Bestellung aus. Bei der Feststellung, ob der Lagerbestand größer als 0 ist, treten jedoch Probleme auf unter hoher Parallelität, was zu einer negativen Bestandsmenge führt.
Tabellen-SQL testen
Importieren Sie die folgenden Tabellendaten in die Datenbank/*
Navicat MySQL Data Transfer
Source Server : 01 本地localhost
Source Server Version : 50553
Source Host : localhost:3306
Source Database : test
Target Server Type : MYSQL
Target Server Version : 50553
File Encoding : 65001
Date: 2020-11-06 14:31:35
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for products
-- ----------------------------
DROP TABLE IF EXISTS `products`;
CREATE TABLE `products` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`title` varchar(50) DEFAULT NULL COMMENT '货品名称',
`store` int(11) DEFAULT '0' COMMENT '货品库存',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='货品表';
-- ----------------------------
-- Records of products
-- ----------------------------
INSERT INTO `products` VALUES ('1', '稻花香大米', '20');
-- ----------------------------
-- Table structure for order_log
-- ----------------------------
DROP TABLE IF EXISTS `order_log`;
CREATE TABLE `order_log` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`content` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '日志内容',
`c_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`oid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '订单号',
`product_id` int(11) DEFAULT '0' COMMENT '商品ID',
`number` int(11) DEFAULT '0' COMMENT '购买数量',
`c_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`oid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='订单表';
<?php db(); global $con; //step1 接收下单参数 $product_id = 1;// 商品ID $buy_num = 1;// 购买数量 //step2 查询商品信息 $sql = "select * from products where id={$product_id}"; $result = mysqli_query($con, $sql); $row = mysqli_fetch_assoc($result); //step3 判断商品下单数量是否大于商品库存数量 //此处在高并发下,可能出现上一个下单后还没来得及更新库存,下一个下单判断库存数不是最新的库存 if ($row['store'] > 0) { sleep(1); //step4 更新商品库存数量(减去下单数量) $sql = "update products set store=store-{$buy_num} where id={$product_id}"; if (mysqli_query($con, $sql)) { echo "更新成功"; //step5 生成订单号创建订单 $oid = build_order_no(); create_order($oid, $product_id, $buy_num); insertLog('库存减少成功,下单成功'); } else { echo "更新失败"; insertLog('库存减少失败'); } } else { echo "没有库存"; insertLog('库存不够'); } function db() { global $con; $con = new mysqli('localhost','root','root','test'); if (!$con) { echo "数据库连接失败"; } } /** * 生成唯一订单号 */ function build_order_no() { return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); } function create_order($oid, $product_id, $number) { global $con; $sql = "INSERT INTO `order` (oid, product_id, number) values('$oid', '$product_id', '$number')"; mysqli_query($con, $sql); } /** * 记录日志 */ function insertLog($content) { global $con; $sql = "INSERT INTO `order_log` (content) values('$content')"; mysqli_query($con, $sql); }
Setzen Sie das Lagerbestandsfeld auf „Unsigned“
weil Inventarfelder nicht vorhanden sein können Eine negative Zahl. Wenn beim Aktualisieren des Produktbestands nach dem Aufgeben einer Bestellung eine negative Zahl angezeigt wird, wird „false“ zurückgegeben Wenn Sie MySQL verwenden, wird die Bestellung aufgegeben. Sperren Sie die Produktliniendaten Zu diesem Zeitpunkt können Sie entweder warten oder direkt. Der Benutzer erhält die Meldung „Der Server ist ausgelastet“ und der Zähler speichert die Anzahl der gekauften Produkte, um eine Abfrage der Datenbank zu vermeiden. Blockierungsmodus (Wartemodus): Wenn während der Parallelität eine zweite Benutzeranforderung vorliegt, wartet das Programm auf den Abschluss der ersten Benutzeranforderung, hebt die Sperre auf und erhält die Dateisperre, bevor das Programm weiter ausgeführt wird. <?php
db();
global $con;
//step1 接收下单参数
$product_id = 1;// 商品ID
$buy_num = 1;// 购买数量
//step2 查询商品信息
$sql = "select * from products where id={$product_id} for UPDATE";//利用for update 开启行锁
$result = mysqli_query($con, $sql);
$row = mysqli_fetch_assoc($result);
//step3 判断商品下单数量是否大于商品库存数量
if ($row['store'] > 0) {
sleep(1);
//step4 更新商品库存数量(减去下单数量)
$sql = "update products set store=store-{$buy_num} where id={$product_id}";
if (mysqli_query($con, $sql)) {
echo "更新成功";
//step5 生成订单号创建订单
$oid = build_order_no();
create_order($oid, $product_id, $buy_num);
insertLog('库存减少成功,下单成功');
} else {
// 如果出现负数将返回false
echo "更新失败";
insertLog('库存减少失败');
}
} else {
//商品已经抢购完
echo "没有库存";
insertLog('库存不够');
}
function db()
{
global $con;
$con = new mysqli('localhost','root','root','test');
if (!$con) {
echo "数据库连接失败";
}
}
/**
* 生成唯一订单号
*/
function build_order_no()
{
return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
}
function create_order($oid, $product_id, $number)
{
global $con;
$sql = "INSERT INTO `order` (oid, product_id, number) values('$oid', '$product_id', '$number')";
mysqli_query($con, $sql);
}
/**
* 记录日志
*/
function insertLog($content)
{
global $con;
$sql = "INSERT INTO `order_log` (content) values('$content')";
mysqli_query($con, $sql);
}
Die MySQL-Transaktionsleistung sinkt bei hoher Parallelität erheblich, und die Methode der Dateisperre ist ebenfalls
1. Stellen Sie das Produkt zunächst in die Redis-Warteschlange<?php db(); global $con; //step1 接收下单参数 $product_id = 1;// 商品ID $buy_num = 1;// 购买数量 mysqli_query($con, "BEGIN"); //开始事务 //step2 查询商品信息 $sql = "select * from products where id={$product_id} for UPDATE";//利用for update 开启行锁 $result = mysqli_query($con, $sql); $row = mysqli_fetch_assoc($result); //step3 判断商品下单数量是否大于商品库存数量 if ($row['store'] > 0) { sleep(1); //step4 更新商品库存数量(减去下单数量) $sql = "update products set store=store-{$buy_num} where id={$product_id}"; if (mysqli_query($con, $sql)) { echo "更新成功"; //step5 生成订单号创建订单 $oid = build_order_no(); create_order($oid, $product_id, $buy_num); insertLog('库存减少成功,下单成功'); mysqli_query($con, "COMMIT");//事务提交即解锁 } else { echo "更新失败"; insertLog('库存减少失败'); mysqli_query($con, "ROLLBACK");//事务回滚即解锁 } } else { //商品已经抢购完 echo "没有库存"; insertLog('库存不够'); mysqli_query($con, "ROLLBACK");//事务回滚即解锁 } function db() { global $con; $con = new mysqli('localhost','root','root','test'); if (!$con) { echo "数据库连接失败"; } } /** * 生成唯一订单号 */ function build_order_no() { return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); } function create_order($oid, $product_id, $number) { global $con; $sql = "INSERT INTO `order` (oid, product_id, number) values('$oid', '$product_id', '$number')"; mysqli_query($con, $sql); } /** * 记录日志 */ function insertLog($content) { global $con; $sql = "INSERT INTO `order_log` (content) values('$content')"; mysqli_query($con, $sql); }
<?php db(); global $con; //step1 接收下单参数 $product_id = 1;// 商品ID $buy_num = 1;// 购买数量 $fp = fopen('lock.txt', 'w'); if (flock($fp, LOCK_EX)) { //文件独占锁,阻塞 //step2 查询商品信息 $sql = "select * from products where id={$product_id}"; $result = mysqli_query($con, $sql); $row = mysqli_fetch_assoc($result); //step3 判断商品下单数量是否大于商品库存数量 if ($row['store'] > 0) { //处理订单 sleep(1); //step4 更新商品库存数量(减去下单数量) $sql = "update products set store=store-{$buy_num} where id={$product_id}"; if (mysqli_query($con, $sql)) { echo "更新成功"; //step5 生成订单号创建订单 $oid = build_order_no(); create_order($oid, $product_id, $buy_num); insertLog('库存减少成功,下单成功'); } else { echo "更新失败"; insertLog('库存减少失败'); } } else { //商品已经抢购完 echo "没有库存"; insertLog('库存不够'); } flock($fp, LOCK_UN); //释放锁 } fclose($fp); function db() { global $con; $con = new mysqli('localhost','root','root','test'); if (!$con) { echo "数据库连接失败"; } } /** * 生成唯一订单号 */ function build_order_no() { return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); } function create_order($oid, $product_id, $number) { global $con; $sql = "INSERT INTO `order` (oid, product_id, number) values('$oid', '$product_id', '$number')"; mysqli_query($con, $sql); } /** * 记录日志 */ function insertLog($content) { global $con; $sql = "INSERT INTO `order_log` (content) values('$content')"; mysqli_query($con, $sql); }
<?php db(); global $con; //step1 接收下单参数 $product_id = 1;// 商品ID $buy_num = 1;// 购买数量 $fp = fopen('lock.txt', 'w'); if (flock($fp, LOCK_EX|LOCK_NB)) { //文件独占锁,非阻塞 //step2 查询商品信息 $sql = "select * from products where id={$product_id}"; $result = mysqli_query($con, $sql); $row = mysqli_fetch_assoc($result); //step3 判断商品下单数量是否大于商品库存数量 if ($row['store'] > 0) { //处理订单 sleep(1); //step4 更新商品库存数量(减去下单数量) $sql = "update products set store=store-{$buy_num} where id={$product_id}"; if (mysqli_query($con, $sql)) { echo "更新成功"; //step5 生成订单号创建订单 $oid = build_order_no(); create_order($oid, $product_id, $buy_num); insertLog('库存减少成功,下单成功'); } else { echo "更新失败"; insertLog('库存减少失败'); } } else { //商品已经抢购完 echo "没有库存"; insertLog('库存不够'); } flock($fp, LOCK_UN); //释放锁 } else { //系统繁忙,请稍后再试 echo "系统繁忙,请稍后再试"; insertLog('系统繁忙,请稍后再试'); } fclose($fp); function db() { global $con; $con = new mysqli('localhost','root','root','test'); if (!$con) { echo "数据库连接失败"; } } /** * 生成唯一订单号 */ function build_order_no() { return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); } function create_order($oid, $product_id, $number) { global $con; $sql = "INSERT INTO `order` (oid, product_id, number) values('$oid', '$product_id', '$number')"; mysqli_query($con, $sql); } /** * 记录日志 */ function insertLog($content) { global $con; $sql = "INSERT INTO `order_log` (content) values('$content')"; mysqli_query($con, $sql); }
PHP-Video-Tutorial
“Das obige ist der detaillierte Inhalt vonSo verhindern Sie, dass der Produktbestand unter Bedingungen hoher Parallelität in PHP überverkauft wird. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen





PHP 8.4 bringt mehrere neue Funktionen, Sicherheitsverbesserungen und Leistungsverbesserungen mit einer beträchtlichen Menge an veralteten und entfernten Funktionen. In dieser Anleitung wird erklärt, wie Sie PHP 8.4 installieren oder auf PHP 8.4 auf Ubuntu, Debian oder deren Derivaten aktualisieren. Obwohl es möglich ist, PHP aus dem Quellcode zu kompilieren, ist die Installation aus einem APT-Repository wie unten erläutert oft schneller und sicherer, da diese Repositorys in Zukunft die neuesten Fehlerbehebungen und Sicherheitsupdates bereitstellen.

Wenn Sie ein erfahrener PHP-Entwickler sind, haben Sie möglicherweise das Gefühl, dass Sie dort waren und dies bereits getan haben. Sie haben eine beträchtliche Anzahl von Anwendungen entwickelt, Millionen von Codezeilen debuggt und eine Reihe von Skripten optimiert, um op zu erreichen

Visual Studio Code, auch bekannt als VS Code, ist ein kostenloser Quellcode-Editor – oder eine integrierte Entwicklungsumgebung (IDE) –, die für alle gängigen Betriebssysteme verfügbar ist. Mit einer großen Sammlung von Erweiterungen für viele Programmiersprachen kann VS Code c

JWT ist ein offener Standard, der auf JSON basiert und zur sicheren Übertragung von Informationen zwischen Parteien verwendet wird, hauptsächlich für die Identitätsauthentifizierung und den Informationsaustausch. 1. JWT besteht aus drei Teilen: Header, Nutzlast und Signatur. 2. Das Arbeitsprinzip von JWT enthält drei Schritte: Generierung von JWT, Überprüfung von JWT und Parsingnayload. 3. Bei Verwendung von JWT zur Authentifizierung in PHP kann JWT generiert und überprüft werden, und die Funktionen und Berechtigungsinformationen der Benutzer können in die erweiterte Verwendung aufgenommen werden. 4. Häufige Fehler sind Signaturüberprüfungsfehler, Token -Ablauf und übergroße Nutzlast. Zu Debugging -Fähigkeiten gehört die Verwendung von Debugging -Tools und Protokollierung. 5. Leistungsoptimierung und Best Practices umfassen die Verwendung geeigneter Signaturalgorithmen, das Einstellen von Gültigkeitsperioden angemessen.

Dieses Tutorial zeigt, wie XML -Dokumente mit PHP effizient verarbeitet werden. XML (Extensible Markup-Sprache) ist eine vielseitige textbasierte Markup-Sprache, die sowohl für die Lesbarkeit des Menschen als auch für die Analyse von Maschinen entwickelt wurde. Es wird üblicherweise für die Datenspeicherung ein verwendet und wird häufig verwendet

Eine Zeichenfolge ist eine Folge von Zeichen, einschließlich Buchstaben, Zahlen und Symbolen. In diesem Tutorial wird lernen, wie Sie die Anzahl der Vokale in einer bestimmten Zeichenfolge in PHP unter Verwendung verschiedener Methoden berechnen. Die Vokale auf Englisch sind a, e, i, o, u und sie können Großbuchstaben oder Kleinbuchstaben sein. Was ist ein Vokal? Vokale sind alphabetische Zeichen, die eine spezifische Aussprache darstellen. Es gibt fünf Vokale in Englisch, einschließlich Großbuchstaben und Kleinbuchstaben: a, e, ich, o, u Beispiel 1 Eingabe: String = "TutorialPoint" Ausgabe: 6 erklären Die Vokale in der String "TutorialPoint" sind u, o, i, a, o, ich. Insgesamt gibt es 6 Yuan

Statische Bindung (statisch: :) implementiert die späte statische Bindung (LSB) in PHP, sodass das Aufrufen von Klassen in statischen Kontexten anstatt Klassen zu definieren. 1) Der Analyseprozess wird zur Laufzeit durchgeführt.

Was sind die magischen Methoden von PHP? Zu den magischen Methoden von PHP gehören: 1. \ _ \ _ Konstrukt, verwendet, um Objekte zu initialisieren; 2. \ _ \ _ Destruct, verwendet zur Reinigung von Ressourcen; 3. \ _ \ _ Call, behandeln Sie nicht existierende Methodenaufrufe; 4. \ _ \ _ GET, Implementieren Sie den dynamischen Attributzugriff; 5. \ _ \ _ Setzen Sie dynamische Attributeinstellungen. Diese Methoden werden in bestimmten Situationen automatisch aufgerufen, wodurch die Code -Flexibilität und -Effizienz verbessert werden.
