The premise is that the purchase is limited per person 1 piece
<> Before the robbery
Stock in seckill goods Redis In line
$redis = new redis(); $redis->connect('127.0.0.1', 6379); // stock $num = 10;
// Go to the line goods_store Insert item , The length of the queue is inventory for($i=0;$i<$num;$i++) $redis->lpush(
'goods_store', 1);
<> In the middle of the attack
method 1
front end : The user clicks the purchase button form Form submission
back-end : Execute the following code
// User waiting queue $wait_key = "user_wait"; // Inventory queue $store_key = "goods_store"; // according to Redis
hash characteristic , Set successfully returned 1, If the old value is overridden, it is returned 0, It is used to control the phenomenon that the same user buys more $result = $redis->hset($wait_key,
$user_id, $user_id); if($result){ $count = $redis->lpop($store_key); if(!$count)
return ' It's gone '; // Order process , Database storage and other operations // If an order fails or an error is reported, it will be executed $redis->hdel($wait_key,
$user_id); And add inventory $redis->lpush('goods_store', 1); And jump back to the previous page, indicating that the order failed ......
// If the order is successful, it will jump to the corresponding page return ' Successful purchase '; }
problem : High and low may cause server pressure to be too high , Data warehousing failure , It can be used in the process of placing orders and warehousing crontab The timer is executed asynchronously
method 2
front end : The user clicks the buy button , Gray button to prevent users from repeatedly clicking , And pop up a small window to prompt queuing
ajax Asynchronously calling the snapping interface
* success : js Whether the polling request placed a successful interface
* success : Jump to the corresponding page for payment process
* fail : Prompt the user to restart the purchase process
* fail : Prompt the user to restart the purchase process
Flash purchase interface code
// User waiting queue $wait_key = "user_wait"; // Successful user queue $user_key = "user"; // Inventory queue
$store_key = "goods_store"; // according to Redis hash characteristic , Set successfully returned 1, If the old value is overridden, it is returned 0, It is used to control the phenomenon that the same user buys more
$result = $redis->hset($wait_key, $user_id, $user_id); if($result){ $count =
$redis->lpop($store_key); if(!$count) return ' It's gone '; $redis->lpush($user_key,
$user_id); return ' Successful purchase '; }
crontab Timer asynchronously executes the order code
// User waiting queue $wait_key = "user_wait"; // Successful user queue $user_key = "user"; $count =
$redis->rpop($user_key); if(!$count) return; // Order process , Database storage and other operations // If an order fails or an error is reported, it will be executed
$redis->hdel($wait_key, $user_id); And add inventory $redis->lpush('goods_store', 1); ......
Interface code of order success or not
// Database query order The order table returns whether there is any outstanding order data
To be solved :
Hypothetical users A When the process goes through the following logic
technological process 1. Order process , Database storage and other operations
technological process 2. If an order fails or an error is reported, it will be executed $redis->hdel($wait_key, $user_id); And add inventory
$redis->lpush('goods_store', 1);
hypothesis 1 Program crash due to unknown error , No implementation 2 And quit , user A Can't buy again
hypothesis 1 Warehousing failed due to unknown error , 2 In execution $redis->hdel failed , user A Can't buy again
optimization :
Front end static resources CDN
set up nginx Maximum number of connections for
Suppose that the inventory of seckill goods has 10 individual , When the user is waiting for the queue user_wait Length greater than 30~100 All requests after filtering
Add a delay queue , Cancel an order that has not been paid within the specified time , Add inventory
provide free gifts Redis Simple code of lock
// Lock $random: random number $expire_time: Effective time $lock_status = $redis->set($lock_key,
$random, array('nx', 'ex' => $expire_time)); if($lock_status){ // do something .
..... if($redis->get($lock_key) == $random){ // Unlock $redis->del($lock_key); } }
Technology