Discussion on PHP's scheme of snapping up under large flow

  • 2021-08-28 19:38:06
  • OfStack

Require a real-time countdown display of hours, minutes and seconds. Modifying the date and time by the client will not affect the normal display of the countdown (that is, the server time shall prevail).

In fact, this is the same requirement as the time limit function of many examination systems.

You can't use ajax to get server time every second, so real-time countdown 1 must be realized with javascript. This is very simple, and there are 1 lot of examples online.

The problem now is to solve the impact of modifying the date and time by the client on our display.

The solution is to calculate the time difference between the client and the server, so that the problem is solved.

In this way, php only needs to be run once, and the real-time countdown time is synchronized with the server time.

The theory is synchronous, but the actual test will have an error of 1 second. (The specific reason is related to the network speed, the faster the network speed, the smaller the error), but this will never affect our above requirements.

Note: The spike time is from 1:00 a.m. to 10:00 p.m.

Code is as follows:


<?php
//php The time is measured in seconds. js Time in milliseconds 
date_default_timezone_set('PRC'); 
//date_default_timezone_set("Asia/Hong_Kong");// Region 
// Configure daily activity periods  
$starttimestr = "08:00:00"; 
$endtimestr = "22:00:00";
$starttime = strtotime($starttimestr); 
$endtime = strtotime($endtimestr); 
$nowtime = time(); 
if ($nowtime<$starttime){ 
die(" The activity hasn't started yet , Activity time is: {$starttimestr} To {$endtimestr}"); 
} 
$lefttime = $endtime-$nowtime; // Actual remaining time (seconds)  
?>
<script language="JavaScript"> 
</script>
<h4><strong id="RemainH">XX</strong>:<strong id="RemainM">XX</strong>:<strong id="RemainS">XX</strong></h4>

There seems to be no problem above, but when encountering traffic, there will be some problems with wrong quantity, such as the problem of negative inventory caused by concurrent warehousing of large traffic

We know that the database processing sql is processed one by one, assuming that the process of purchasing goods is as follows:

sql1: Query merchandise inventory


if( Inventory quantity  > 0) 
{ 
// Generate an order …  
sql2: Inventory -1 
}

When there is no concurrency, the above process looks so perfect. Suppose two people place an order at the same time and there is only one inventory. In sql1, the inventory inquired by two people is > 0, so sql2 was finally implemented, and the inventory finally changed to-1, which was oversold. Either replenish the inventory or wait for the user to complain.

A popular way to solve this problem:

1. Use an extra single process to process a queue, put the order request into the queue, and process it one by one, so there will be no concurrency problem, but the extra background process and delay problem will not be considered.

2. Database optimistic lock, which roughly means to query the inventory first, then immediately +1 the inventory, and then after the order is generated, query the inventory again before updating the inventory to see if it keeps 1 with the expected inventory quantity, and roll back if it is not 1, prompting the user that the inventory is insufficient.

3. According to the result of update, we can add a judgment condition update … where inventory when sql 2 > 0. If false is returned, the inventory is insufficient and the transaction is rolled back.

4. With the help of file exclusive lock, when processing the order request, lock a file with flock. If the lock fails, it means that other orders are being processed. At this time, either wait or directly prompt the user that "the server is busy"

This article is going to talk about the fourth scheme, and the approximate code is as follows:

Blocking (waiting) mode


<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX))
{
 //.. Processing orders 
 flock($fp,LOCK_UN);
}
fclose($fp);
?>

Non-blocking mode


<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX | LOCK_NB))
{
 //.. Processing orders 
 flock($fp,LOCK_UN);
}
else
{
 echo " The system is busy, please try again later ";
}
fclose($fp);
?>

Related articles: