How to deal with high concurrency php

Data security at high concurrency

 

We know that when multiple threads write to the same file, "thread safety" issue will appear (multiple threads running the same code at the same time, if the results of each run single-threaded operating results and the same, and expected the same result It is thread-safe).

If MySQL database, you can use it comes with a good lock mechanism to solve the problem, but in large-scale concurrent scenario, it is not recommended to use MySQL. Spike and snapped the scene, the most critical issue is the "Super" and, if not controlled in this regard will lead to orders generated more than the actual sale of goods issue.

Ultra reason hair:

Suppose a buying scenario, we have a total of only 100 commodities at the last minute, we have consumed 99 commodities, the last one remaining. This time, the system is sent to a plurality of concurrent requests, these requests are read margin of a product, and then through the remainder of the judgment, resulting in Super.

It is worth noting: remember to stock field to field number unsigned, when the inventory is zero, because the unsigned field can not be negative, will return false

Optimization

Optimization 1: Using MySQL transactions lock BEGIN line operations; SELECT ... FOR UPDATE; COMMIT; ROLLBACK

? <Php // optimization scheme 1: Using MySQL transaction include the row lock operation ( './ mysql.php'); function build_order_no () {return date ( 'ymd') substr (implode (NULL, array_map. ( 'ord', str_split (substr (uniqid (), 7, 13), 1))), 0, 8);} // log 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"); // start transaction $ sql = "select number from ih_store where goods_id = '$ goods_id' and sku_id = '$ sku_id' FOR UPDATE"; // At this point this record is locked, you can perform other transactions must wait after the transaction commits $ rs = mysqli_query ($ conn, $ sql); $ row = $ rs-> fetch_assoc (); if ($ row [ 'number']> 0) {// generate orders $ 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); // inventory reduction $ sql =" update ih_store set number = number - {$ number} where sku_id = '$ sku_id' "; $ store_rs = mysqli_query ($ conn, $ sql); if ($ store_rs) {echo 'inventory reduction success'; insertLog ( 'inventory reduction success'); mysqli_query ($ conn," COMMIT "); // transaction commit that is unlocked} else {echo 'inventory reduction failed'; insertLog ( 'inventories decreased fail');}} else {echo 'inventory is not enough'; insertLog ( 'inventory is not enough'); mysqli_query ($ conn, "ROLLBACK ");}COMMIT "); // transaction commits, ie unlocked} else {echo 'inventory reduction failed'; insertLog ( 'inventories decreased fail');}} else {echo 'inventory is not enough'; insertLog ( 'inventory is not enough'); mysqli_query ($ conn, "ROLLBACK");}COMMIT "); // transaction commits, ie unlocked} else {echo 'inventory reduction failed'; insertLog ( 'inventories decreased fail');}} else {echo 'inventory is not enough'; insertLog ( 'inventory is not enough'); mysqli_query ($ conn, "ROLLBACK");}

Optimization 2: File Lock ideas

For day visits are not high or not large number of concurrent applications, file with the general method of operation is no problem. But if a concurrent high, when we read and write to the file, probably a file into multiple processes to operate, if not then access the files accordingly exclusive, it is easy to cause data loss.

? <Php // Optimization Scenario 2: Using non-blocking file exclusive lock include ( './mysql.php'); // generate a unique order number function build_order_no () {return date ( 'ymd') substr (implode (. NULL, array_map ( 'ord', str_split (substr (uniqid (), 7, 13), 1))), 0, 8);} // log function insertLog ($ event, $ type = 0) {global $ conn; $ sql = "insert into ih_log (event, type) values ​​( '$ event', '$ type')"; mysqli_query ($ conn, $ sql);} $ fp = fopen ( "lock.txt", " w + "); (! flock ($ fp, LOCK_EX | LOCK_NB) if) {echo" system is busy, please try again later "; return;} // single $ sql =" select number from ih_store where goods_id = '$ goods_id 'and sku_id =' $ sku_id ' "; $ rs = mysqli_query ($ conn, $ sql); $ row = $ rs-> fetch_assoc (); if ($ row [' number ']> 0) {// Stock is greater than 0 // single analog operation $ 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); // reduce inventory $ sql = "update ih_store set number = number - {$ number} where sku_id = '$ sku_id'"; $ store_rs = mysqli_query ($ conn, $ sql); if ($ store_rs) {echo 'inventory reduction success'; insertLog (' Stock success in reducing '); flock ($ fp, LOCK_UN); // release lock} else {echo' inventory reduction fail '; insertLog (' inventory reduction fail ');}} else {echo' stock enough '; insertLog (' Stock enough ');} fclose ($ fp);Inventory reduction success'; insertLog ( 'success in reducing inventory'); flock ($ fp, LOCK_UN); // release lock} else {echo 'inventory reduction fail'; insertLog ( 'inventory reduction fail');}} else {echo 'Stock enough'; insertLog ( 'stock enough');} fclose ($ fp);Inventory reduction success'; insertLog ( 'success in reducing inventory'); flock ($ fp, LOCK_UN); // release lock} else {echo 'inventory reduction fail'; insertLog ( 'inventory reduction fail');}} else {echo 'Stock enough'; insertLog ( 'stock enough');} fclose ($ fp);

 

Guess you like

Origin www.cnblogs.com/68xi/p/11528073.html