Home>Article>Backend Development> Detailed explanation of examples of rush buying and flash sale functions under high concurrency using PHP and redis

Detailed explanation of examples of rush buying and flash sale functions under high concurrency using PHP and redis

炎欲天舞
炎欲天舞 Original
2017-08-03 14:56:37 1834browse

Rush sales and flash sales are very common scenes. Interviewers often ask questions during interviews, such as how you implement rush sales on Taobao and so on.

The implementation of snap-up and flash sales is very simple, but some problems need to be solved, mainly focusing on two problems:

1 The pressure caused by high concurrency on the database

2 How to solve the correct inventory reduction ("oversold" problem) under competition conditions

The first question, for PHP It's very simple. You can use caching technology to relieve database pressure, such as memcache, redis and other caching technologies.

The second question is more complicated:

Conventional writing:

Query the corresponding product Inventory, see if it is greater than 0, and then perform operations such as generating orders. However, when judging whether the inventory is greater than 0, there will be problems under high concurrency, resulting in a negative inventory 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=mysql_query($sql,$conn); //库存减少 $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'"; $store_rs=mysql_query($sql,$conn); if(mysql_affected_rows()){ insertLog('库存减少成功'); }else{ insertLog('库存减少失败'); } }else{ insertLog('库存不够'); }

This occurs What to do in this situation? Let’s look at several optimization methods:

Optimization plan 1:Set the inventory field number field to unsigned. When the inventory is 0, because the field cannot be a negative number, Will return false

1 //库存减少 2 $sql="update ih_store set number=number-{$number} where sku_id='$sku_id' and number>0"; 3 $store_rs=mysql_query($sql,$conn); 4 if(mysql_affected_rows()){ 5 insertLog('库存减少成功');6 }

Optimization plan 2:UseMySQLtransaction to lock the row of operation


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=mysql_query($sql,$conn); //库存减少 $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'"; $store_rs=mysql_query($sql,$conn); if(mysql_affected_rows()){ insertLog('库存减少成功'); mysql_query("COMMIT");//事务提交即解锁 }else{ insertLog('库存减少失败'); } }else{ insertLog('库存不够'); mysql_query("ROLLBACK"); }

Optimization plan 3:Use non-blocking file exclusive lock


0){//库存是否大于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=mysql_query($sql,$conn); //库存减少 $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'"; $store_rs=mysql_query($sql,$conn); if(mysql_affected_rows()){ insertLog('库存减少成功'); flock($fp,LOCK_UN);//释放锁 }else{ insertLog('库存减少失败'); } }else{ insertLog('库存不够'); } fclose($fp);

Optimization plan 4:Use redis queue, because the pop operation is atomic, even if many users arrive at the same time, they will be executed sequentially. It is recommended to use (mysql transaction in high concurrency The performance drops drastically, as does the file lock method)

First put the product inventory into a queue


connect('127.0.0.1',6379); $res=$redis->llen('goods_store'); echo $res; $count=$store-$res; for($i=0;$i<$count;$i++){ $redis->lpush('goods_store',1); } echo $redis->llen('goods_store');

Purchase and describe the logic


f8e11ea81ba6c588bf1f2299cbda61c6connect('127.0.0.1',6379); $count=$redis->lpop('goods_store'); if(!$count){ insertLog('error:no store redis'); return; } //生成订单 $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=mysql_query($sql,$conn); //库存减少 $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'"; $store_rs=mysql_query($sql,$conn); if(mysql_affected_rows()){ insertLog('库存减少成功'); }else{ insertLog('库存减少失败'); }

The above is just a simple simulation of rush buying under high concurrency. The real scenario is much more complicated than this. There are many things to pay attention to

For example, the rush buying page is made static and the interface is called through ajax

The above will cause one user to grab multiple items. The idea is:

Needs a queuing queue, a snap-up result queue and an inventory queue. In the case of high concurrency, first enter the user into the queuing queue, use a thread loop to remove a user from the queuing queue, and determine whether the user is already in the rush-buying result queue. If it is, it has been snapped up, otherwise it is not snapped up, the inventory is reduced by 1, writeDatabase, put the user into the result queue.

When I was working on a shopping mall project, I used redis directly for flash sales. During this time, I looked at the above methods. Although they are different, they all achieve the same purpose. Everyone Make your own choice and be happy.

The above is the detailed content of Detailed explanation of examples of rush buying and flash sale functions under high concurrency using PHP and redis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn