At the request of the group, we created a flash sale function for the service account. We needed to test the flash sale. We wanted to try PHP multi-threading, so we simulated the order grabbing function. This article mainly shares with you PHP multi-thread simulation to realize the flash sale and order grabbing function. It has certain reference value. Interested friends can refer to it. I hope it can help everyone.
Let’s talk about the idea of the flash sale module first:
User flash sale operation under normal circumstances
1. Initiate a flash sale request
2. Enter the flash sale Queue
3. Randomly lag 1-2 seconds for flash sale result query request (it can be regarded as a disguised diversion)
4. Generate an order if successful
5. Return results
The following are Code to simulate flash sale:
<?php set_time_limit(0); /** * 线程的执行任务 */ class Threadrun extends Thread { public $url; public $data; public $params; public function __construct($url, $params=[]) { $this->url = $url; $this->params = $params; } public function run() { if(($url = $this->url)) { $params = [ 'goods_id' => 1, 'activity_id' => 1, 'user_id' => isset($this->params['user_id']) ? $this->params['user_id'] : $this->getCurrentThreadId(), ]; $startTime = microtime(true); $this->data = [ 'id' => $params['user_id'], 'result' => model_http_curl_get( $url, $params ), 'time' => microtime(true)-$startTime, 'now' => microtime(true), ]; } } } /** * 执行多线程 */ function model_thread_result_get($urls_array) { foreach ($urls_array as $key => $value) { $threadPool[$key] = new Threadrun($value["url"],['user_id'=>$value['user_id']]); $threadPool[$key]->start(); } foreach ($threadPool as $thread_key => $thread_value) { while($threadPool[$thread_key]->isRunning()) { usleep(10); } if($threadPool[$thread_key]->join()) { $variable_data[$thread_key] = $threadPool[$thread_key]->data; } } return $variable_data; } /** * 发送 HTTP 请求 */ function model_http_curl_get($url,$data=[],$userAgent="") { $userAgent = $userAgent ? $userAgent : 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)'; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_TIMEOUT, 5); curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); curl_setopt($curl, CURLOPT_POST, true); if( !empty($data) ) { curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } $result = curl_exec($curl); curl_close($curl); return $result; } /** * 友好的打印变量 * @param $val */ function dump( $val ) { echo '<pre class="brush:php;toolbar:false">'; var_dump($val); echo ''; } /** * 写日志 * @param $msg * @param string $logPath */ function writeLog( $msg, $logPath='' ) { if( empty($logPath) ) { $logPath = date('Y_m_d').'.log'; } if( !file_exists($logPath) ) { $fp = fopen( $logPath,'w' ); fclose( $fp ); } error_log( $msg.PHP_EOL, 3, $logPath); } /** * 生成日志信息 * @param $result * @param $timeDiff * @return bool|string */ function createLog( $result, $timeDiff ){ if( empty($result) || !is_array($result) ) { return false; } $succeed = 0; $fail = 0; foreach( $result as $v ) { $times[] = $v['time']; $v['result'] === false ? $fail++ : $succeed++; } $totalTime = array_sum( $times ); $maxTime = max( $times ); $minTime = min( $times ); $sum = count( $times ); $avgTime = $totalTime/$sum; $segment = str_repeat('=',100); $flag = $segment . PHP_EOL; $flag .= '总共执行时间:' . $timeDiff . PHP_EOL ; $flag .= '最大执行时间:' . $maxTime . PHP_EOL; $flag .= '最小执行时间:' . $minTime . PHP_EOL; $flag .= '平均请求时间:' . $avgTime . PHP_EOL; $flag .= '请求数:' . $sum . PHP_EOL; $flag .= '请求成功数:' . $succeed . PHP_EOL; $flag .= '请求失败数:' . $fail . PHP_EOL; $flag .= $segment . PHP_EOL; return $flag; } /** * 发起秒杀请求 */ function insertList( $urls, $logPath='' ) { $t = microtime(true); $result = model_thread_result_get($urls); $e = microtime(true); $timeDiff = $e-$t; echo "总执行时间:" . $timeDiff . PHP_EOL; foreach( $result as $v ) { $msg = '用户【' . $v['id'] . '】秒杀商品, 返回结果 ' . $v['result'] . ' 用时【' . $v['time'] . ' 秒】 当前时间【'.$v['now'].'】'; writeLog( $msg,$logPath ); } $logStr = createLog( $result, $timeDiff); writeLog( $logStr, $logPath ); return $result; } //发起秒杀请求 for ($i=0; $i < 1000; $i++) { $urls_array[] = array("name" => "baidu", "url" => "http://***.***.com/seckill/shopping/listinsert"); } $list = insertList( $urls_array, './inset.log' ); //发起秒杀结果查询请求 $urls_array = []; foreach( $list as $v ) { if( $v['result'] === false ) { continue; } $urls_array[] = array( "name" => "baidu", "url" => "http://***.***.com/seckill/shopping/query", 'user_id' => $v['id'], ); } insertList( $urls_array, './query.log' );
Test code machine performance (development machine):
Order code machine performance ( Test machine):
System test results:
Simulating 1000 concurrent situations, a single machine can process 300+ orders per second, and the server has no pressure.
On the contrary, the test machine couldn't bear it, and the CPU surged by 100%. Apache occasionally crashes.
I don’t know whether it’s the poor support of PHP multi-threading and Windows environment, or the problem of PHP multi-threading itself, but only 1000 threads can’t run. Multi-threading still requires Python and C.
Related recommendations:
php and redis realize mall flash sale function code sharing
JS script realizes web page automatic flash sale example sharing
Video resource recommendation for PHP e-commerce website product flash sale function
The above is the detailed content of PHP implements flash sale code. For more information, please follow other related articles on the PHP Chinese website!