Datensicherheit bei hoher Parallelität
Wir wissen, dass beim Schreiben mehrerer Threads in dieselbe Datei Probleme mit der „Thread-Sicherheit“ auftreten (mehrere Threads führen gleichzeitig denselben Abschnitt aus). Der Code ist threadsicher, wenn das Ergebnis jedes Laufs mit dem eines Single-Thread-Laufs übereinstimmt und die Ergebnisse mit den Erwartungen übereinstimmen.
Wenn es sich um eine MySQL-Datenbank handelt, können Sie einen eigenen Sperrmechanismus verwenden, um das Problem zu lösen. In großen Parallelitätsszenarien wird MySQL jedoch nicht empfohlen. Bei Flash-Sales und Rush-Sales-Szenarien ist die „Überausgabe“ das kritischste Problem. Wenn dieser Aspekt nicht sorgfältig kontrolliert wird, führt dies dazu, dass die tatsächlich generierten Bestellungen höher sind als die Vorverkaufsprodukte.
Grund für die Überausgabe: (Empfohlenes Lernen: PHP-Programmierung vom Einstieg bis zur Beherrschung)
Gehen Sie davon aus, dass es sich um ein bestimmtes Eilkaufszenario handelt , wir haben insgesamt nur 100 Produkte, im letzten Moment haben wir 99 Produkte verbraucht und nur noch das letzte übrig. Zu diesem Zeitpunkt sendete das System mehrere gleichzeitige Anfragen. Die in diesen Anfragen gelesenen Produktsalden waren alle 1, und dann bestanden alle die Saldobeurteilung, was schließlich zu einer Überausgabe führte.
Es ist erwähnenswert: Denken Sie daran, das Feld „Inventarfeldnummer“ auf „unsigned“ zu setzen, da das vorzeichenlose Feld keine negative Zahl sein darf, wird „false“ zurückgegeben
Optimierungsplan
Optimierung 1: Verwenden Sie MySQL-Transaktionen, um die Zeilen von Operationen zu sperren. BEGIN ; SELECT ... FOR UPDATE ; ROLLBACK
Optimierung 2: Datei Sperridee
Für Anwendungen, bei denen die Anzahl der täglichen Besuche nicht hoch ist oder die Anzahl der Parallelität nicht sehr groß ist, ist die Verwendung normaler Dateioperationsmethoden kein Problem. Wenn jedoch die Parallelität beim Lesen und Schreiben von Dateien hoch ist, ist es sehr wahrscheinlich, dass mehrere Prozesse an der nächsten Datei arbeiten. Wenn der Zugriff auf die Datei nicht entsprechend monopolisiert wird, kommt es leicht zu Datenverlust.<?php //优化方案1:使用MySQL的事务,锁住操作的行 include('./mysql.php'); function build_order_no(){ return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8); } //记录日志 function insertLog($event,$type=0){ global $conn; $sql="insert into ih_log(event,type) values('$event','$type')"; mysqli_query($conn,$sql); } mysqli_query($conn,"BEGIN"); //开始事务 $sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id' FOR UPDATE";//此时这条记录被锁住,其它事务必须等待此次事务提交后才能执行 $rs=mysqli_query($conn,$sql); $row=$rs->fetch_assoc(); if($row['number']>0){ //生成订单 $order_sn=build_order_no(); $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price) values('$order_sn','$user_id','$goods_id','$sku_id','$price')"; $order_rs=mysqli_query($conn,$sql); //库存减少 $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'"; $store_rs=mysqli_query($conn,$sql); if($store_rs){ echo '库存减少成功'; insertLog('库存减少成功'); mysqli_query($conn,"COMMIT");//事务提交即解锁 }else{ echo '库存减少失败'; insertLog('库存减少失败'); } }else{ echo '库存不够'; insertLog('库存不够'); mysqli_query($conn,"ROLLBACK"); }
Das obige ist der detaillierte Inhalt vonWie man mit hoher Parallelität in PHP umgeht. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!