this article takes the example of rush purchase and second killing. This paper introduces how to make sure the data is correct in high concurrency condition.
parameters of two
1. data error in high concurrent requests, resulting in oversold products.
2. operates the database frequently, causing performance degradation. The

test environment is

PHP framework yii2.0 yii2.0 tool tool (with high concurrent request tool).

usually handles the method

from the controller to see the code idea. Check the stock of the goods first. If the stock is more than 0, the stock is reduced by 1, and the order is produced and the data of the buyer is entered.

 / / function public routine code processing high concurrency (actionNormal) {/ / $stock = Goods: inventory: find (->); select ('stock') -> where (['goods_id'=> 100001]) -> asArray (->); (one); / / judge whether the commodity is in stock if ($stock['stock']> 0) {a Goods:: updateAllCounters / / inventory reduction (['stock' => -1], ['goods_id'=> 100001]); / / production orders (another function for random assignment) $order = $this-> (build_order); / / $model = new seckill information into the database (Highly); $model-> $model-> order_id = $order; goods_name = 'seckill'; $model-> buy_time = date ('Y-m-d) (H:i:s', time); $model-> mircrotime = microtime (true); if ($model-> save) (= = =false) {echo 'failed to buy! ';}else{echo' Congratulations, order < b>'.$order.'< /b> snap success';}}else{echo 'has been snapped up! '}}} 

sets the commodity stock to 20 and configuring the concurrency request of 200 through ab.

 ab -n -c 200 http//localhost/highly/normal 


implementation results show that the inventory turned negative, oversold goods.


optimization 1: modification of inventory data type

first optimization method, starting from the database. As the result of the inquiry is not accurate, I will do it in stock reduction. Change the data type of the inventory to unsigned (no negative value). The

code is similar to the above, only to make a judgment where the inventory is reduced by 1. Avoid making mistakes.

 public function (actionNormal) {/ / $stock = Goods: inventory: find (->); select ('stock') -> where (['goods_id'=> 100001]) -> asArray (->); (one); / / judge whether the commodity and stock if ($stock['stock']& gt; 0) {/ / inventory minus one (if Goods:: updateAllCounters (['stock' => -1], ['goods_id'=> 100001]) {echo ===false) "has been sold out!"; return false;} / / production order (another function for random assignment) $order = $this-> (build_order); / / $model = new Highly seckill information storage (); $model-> order_id = $order; $model-> goods_name = '$model->'; buy_time seckill goods; date = ('Y-m-d) (H:i:s', time); mircrotime = $model-> Microtime (true); if ($model-> save () ===false) {echo 'failed to be snapped up successfully! ';}else{echo' Congratulations, order < b>'.$order.'< /b> snap success';}}else{echo 'has been snapped up! ";}}} 

this time the same 200 concurrency, the execution result found. The data is correct, and will not appear oversold.
is also a simple idea. Because the stock can not be negative, when the stock is equal to 0, if the value is passed in, it will be reported wrong. The request is terminated.

this kind of optimization methods, while avoiding the commodity oversold conditions. However, on the other hand, the request will still cause pressure on the database. If multiple functions use this database, performance degrades badly.

optimizes two: redis

uses the atomicity of the pop of the redis list type. Before operating the database, do a validation. When the goods are sold out, it is not allowed to continue the database operation.

 / / redis list public function actionRedis (high concurrent test) {$redis = $app-> Yii:: redis; / / $redis-> lpush ('mytest', 1); $order = $this-> build_order (echo); / / $order / / echo; die; $redis-> llen ('mytest'); $reg = $redis-> lpop ('mytest'); if (! $reg) {echo "! It's been robbed! "; return false;}); $model ($redis-> close = new (Highly); $model-> $model-> order_id = $order; goods_name = '$model->'; buy_time seckill goods; date = ('Y-m-d) (H:i:s', time); $model-> mircrotime = microtime (true); if ($model-> (save); ===false) {echo' failed to panic buying! }else{echo ';' Congratulations, order < b>'.$order.'< /b>}} / / panic buying success; add public function actionInsertgoods to redis (commodity) {$count = $app-> yii:: request-> get ('count', 0); if (empty ($count)) {echo' big brother, you also I need not tell how many goods shelves! '; return false;} $redis = Yii:: $app-> redis; for ($i=0; $i < $count; $i++) {$redis-> lpush ('mytest', 1);} echo 'successfully added'.$redis-> llen ('mytest'). Items. ';'; $redis-> close ();} 

code, I wrote two methods. The first method is the code for the second kill, and the second method is to set the number of commodities for the second kill. In order to facilitate the test, I deal with the simple.

passed the test, and the number of orders produced by the database was normal, and there was no problem. It also avoids the problem of performance degradation in the request database. At the same time, the memory database redis query is much faster than the mysql.

is the whole content of this article, I hope to help you, and hope that you can support a lot of scripting home.

This paper fixed link: | Script Home | +Copy Link

Article reprint please specify:PHP high concurrency request for dealing with the function of the rush order | Script Home

You may also be interested in these articles!