찾다
백엔드 개발PHP 튜토리얼PHP와 Redis는 높은 동시성으로 긴급 구매 및 플래시 판매를 구현합니다.

이 기사에서는 플래시 세일과 플래시 세일을 높은 동시성으로 구현하는 방법에 대해 주로 PHP와 Redis에 대해 설명합니다. 플래시 세일과 플래시 세일은 인터뷰 중에 면접관이 자주 묻는 질문입니다. 예를 들어 Taobao에서 플래시 세일을 어떻게 구현하나요? 잠깐, 모두에게 도움이 되기를 바랍니다

급매와 반짝세일을 구현하는 것은 매우 간단하지만, 해결해야 할 몇 가지 문제가 있는데, 주로 두 가지 문제에 초점을 맞춥니다.

1. 높은 동시성으로 인한 압박.
2. 경쟁 상태에서 문제를 해결하는 방법 올바른 재고 감소("과매도" 문제)

첫 번째 질문은 PHP의 경우 매우 간단합니다. Memcache, Redis와 같은 캐싱 기술을 사용하여 데이터베이스 부담을 줄일 수 있습니다. 및 기타 캐싱 기술.
두 번째 질문은 더 복잡합니다.

기존 글쓰기:
해당 상품의 재고를 조회하여 0보다 큰지 확인한 후 주문 생성 등의 작업을 수행합니다. 0, 동시성이 높으면 문제가 발생하여 부정적인 재고 수준이 발생합니다.

<?php
$conn=mysql_connect("localhost","big","123456");
if(!$conn){
echo "connect failed";
exit;
}
mysql_select_db("big",$conn);
mysql_query("set names utf8");
$price=10;
$user_id=1;
$goods_id=1;
$sku_id=11;
$number=1;
//生成唯一订单
function build_order_no(){
return date(&#39;ymd&#39;).substr(implode(NULL, array_map(&#39;ord&#39;, str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog($event,$type=0){
global $conn;
$sql="insert into ih_log(event,type)
values(&#39;$event&#39;,&#39;$type&#39;)";
mysql_query($sql,$conn);
}
//模拟下单操作
//库存是否大于0
$sql="select number from ih_store where goods_id=&#39;$goods_id&#39; and sku_id=&#39;$sku_id&#39;";
//解锁 此时ih_store数据中goods_id=&#39;$goods_id&#39; and sku_id=&#39;$sku_id&#39; 的数据被锁住(注3),其它事务必须等待此次事务 提交后才能执行
$rs=mysql_query($sql,$conn);
$row=mysql_fetch_assoc($rs);
if($row[&#39;number&#39;]>0){//高并发下会导致超卖
$order_sn=build_order_no();
//生成订单
$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values(&#39;$order_sn&#39;,&#39;$user_id&#39;,&#39;$goods_id&#39;,&#39;$sku_id&#39;,&#39;$price&#39;)";
$order_rs=mysql_query($sql,$conn);
//库存减少
$sql="update ih_store set number=number-{$number} where sku_id=&#39;$sku_id&#39;";
$store_rs=mysql_query($sql,$conn);
if(mysql_affected_rows()){
insertLog(&#39;库存减少成功&#39;);
}else{
insertLog(&#39;库存减少失败&#39;);
}
}else{
insertLog(&#39;库存不够&#39;);
}
出现这种情况怎么办呢?来看几种优化方法:
优化方案1:将库存字段number字段设为unsigned,当库存为0时,因为字段不能为负数,将会返回false
//库存减少
$sql="update ih_store set number=number-{$number} where sku_id=&#39;$sku_id&#39; and number>0";
$store_rs=mysql_query($sql,$conn);
if(mysql_affected_rows()){
insertLog(&#39;库存减少成功&#39;);
}
优化方案2:使用MySQL的事务,锁住操作的行
<?php
$conn=mysql_connect("localhost","big","123456");
if(!$conn){
echo "connect failed";
exit;
}
mysql_select_db("big",$conn);
mysql_query("set names utf8");
$price=10;
$user_id=1;
$goods_id=1;
$sku_id=11;
$number=1;
//生成唯一订单号
function build_order_no(){
return date(&#39;ymd&#39;).substr(implode(NULL, array_map(&#39;ord&#39;, str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog($event,$type=0){
global $conn;
$sql="insert into ih_log(event,type)
values(&#39;$event&#39;,&#39;$type&#39;)";
mysql_query($sql,$conn);
}
//模拟下单操作
//库存是否大于0
mysql_query("BEGIN"); //开始事务
$sql="select number from ih_store where goods_id=&#39;$goods_id&#39; and sku_id=&#39;$sku_id&#39; FOR UPDATE";//此时这条记录被锁住,其它事务必须等待此次事务提交后才能执行
$rs=mysql_query($sql,$conn);
$row=mysql_fetch_assoc($rs);
if($row[&#39;number&#39;]>0){
//生成订单
$order_sn=build_order_no();
$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values(&#39;$order_sn&#39;,&#39;$user_id&#39;,&#39;$goods_id&#39;,&#39;$sku_id&#39;,&#39;$price&#39;)";
$order_rs=mysql_query($sql,$conn);
//库存减少
$sql="update ih_store set number=number-{$number} where sku_id=&#39;$sku_id&#39;";
$store_rs=mysql_query($sql,$conn);
if(mysql_affected_rows()){
insertLog(&#39;库存减少成功&#39;);
mysql_query("COMMIT");//事务提交即解锁
}else{
insertLog(&#39;库存减少失败&#39;);
}
}else{
insertLog(&#39;库存不够&#39;);
mysql_query("ROLLBACK");
}
优化方案3:使用非阻塞的文件排他锁
<?php
$conn=mysql_connect("localhost","root","123456");
if(!$conn){
echo "connect failed";
exit;
}
mysql_select_db("big-bak",$conn);
mysql_query("set names utf8");
$price=10;
$user_id=1;
$goods_id=1;
$sku_id=11;
$number=1;
//生成唯一订单号
function build_order_no(){
return date(&#39;ymd&#39;).substr(implode(NULL, array_map(&#39;ord&#39;, str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog($event,$type=0){
global $conn;
$sql="insert into ih_log(event,type)
values(&#39;$event&#39;,&#39;$type&#39;)";
mysql_query($sql,$conn);
}
$fp = fopen("lock.txt", "w+");
if(!flock($fp,LOCK_EX | LOCK_NB)){
echo "系统繁忙,请稍后再试";
return;
}
//下单
$sql="select number from ih_store where goods_id=&#39;$goods_id&#39; and sku_id=&#39;$sku_id&#39;";
$rs=mysql_query($sql,$conn);
$row=mysql_fetch_assoc($rs);
if($row[&#39;number&#39;]>0){//库存是否大于0
//模拟下单操作
$order_sn=build_order_no();
$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values(&#39;$order_sn&#39;,&#39;$user_id&#39;,&#39;$goods_id&#39;,&#39;$sku_id&#39;,&#39;$price&#39;)";
$order_rs=mysql_query($sql,$conn);
//库存减少
$sql="update ih_store set number=number-{$number} where sku_id=&#39;$sku_id&#39;";
$store_rs=mysql_query($sql,$conn);
if(mysql_affected_rows()){
insertLog(&#39;库存减少成功&#39;);
flock($fp,LOCK_UN);//释放锁
}else{
insertLog(&#39;库存减少失败&#39;);
}
}else{
insertLog(&#39;库存不够&#39;);
}
fclose($fp);
优化方案4:使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,推荐使用(mysql事务在高并发下性能下降很厉害,文件锁的方式也是)
先将商品库存如队列
<?php
$store=1000;
$redis=new Redis();
$result=$redis->connect(&#39;127.0.0.1&#39;,6379);
$res=$redis->llen(&#39;goods_store&#39;);
echo $res;
$count=$store-$res;
for($i=0;$i<$count;$i++){
$redis->lpush(&#39;goods_store&#39;,1);
}
echo $redis->llen(&#39;goods_store&#39;);
抢购、描述逻辑
<?php
$conn=mysql_connect("localhost","big","123456");
if(!$conn){
echo "connect failed";
exit;
}
mysql_select_db("big",$conn);
mysql_query("set names utf8");
$price=10;
$user_id=1;
$goods_id=1;
$sku_id=11;
$number=1;
//生成唯一订单号
function build_order_no(){
return date(&#39;ymd&#39;).substr(implode(NULL, array_map(&#39;ord&#39;, str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog($event,$type=0){
global $conn;
$sql="insert into ih_log(event,type)
values(&#39;$event&#39;,&#39;$type&#39;)";
mysql_query($sql,$conn);
}
//模拟下单操作
//下单前判断redis队列库存量
$redis=new Redis();
$result=$redis->connect(&#39;127.0.0.1&#39;,6379);
$count=$redis->lpop(&#39;goods_store&#39;);
if(!$count){
insertLog(&#39;error:no store redis&#39;);
return;
}
//生成订单
$order_sn=build_order_no();
$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values(&#39;$order_sn&#39;,&#39;$user_id&#39;,&#39;$goods_id&#39;,&#39;$sku_id&#39;,&#39;$price&#39;)";
$order_rs=mysql_query($sql,$conn);
//库存减少
$sql="update ih_store set number=number-{$number} where sku_id=&#39;$sku_id&#39;";
$store_rs=mysql_query($sql,$conn);
if(mysql_affected_rows()){
insertLog(&#39;库存减少成功&#39;);
}else{
insertLog(&#39;库存减少失败&#39;);
}

위는 높은 동시성에서 급하게 구매하는 간단한 시뮬레이션일 뿐입니다. 실제 시나리오는 이보다 훨씬 더 복잡합니다. 급하게 구매 페이지를 정적으로 만들고 Ajax를 통해 인터페이스를 호출하는 등 주의해야 할 사항이 많습니다. .

위의 내용을 따르면 한 명의 사용자가 여러 항목을 가져갈 수 있습니다. 아이디어는 다음과 같습니다.
대기 대기열, 구매 결과 대기열 및 인벤토리 대기열이 필요합니다. 동시성이 높은 경우 먼저 사용자를 대기열에 입력하고 스레드 루프를 사용하여 대기열에서 사용자를 제거한 다음 해당 사용자가 이미 급매수 결과 대기열에 있는지 확인합니다. 그렇지 않으면 스냅업되지 않고 인벤토리가 1만큼 줄어들며 데이터베이스는 사용자를 결과 대기열에 기록합니다.
저는 쇼핑몰 프로젝트를 진행하면서 플래쉬세일을 위해 redis를 직접 사용했는데, 이때 위의 방법들은 다르지만 모두 같은 목적을 달성하기 위해 살펴보았습니다. . 좋은.

관련 추천:

php+redis는 긴급 구매 기능을 구현합니다

PHP는 긴급 구매 기능에 대한 높은 동시 요청을 어떻게 처리합니까?

PHP는 잠금을 통해 동시 긴급 구매 기능을 구현합니다

위 내용은 PHP와 Redis는 높은 동시성으로 긴급 구매 및 플래시 판매를 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
교통량이 많은 웹 사이트를위한 PHP 성능 튜닝교통량이 많은 웹 사이트를위한 PHP 성능 튜닝May 14, 2025 am 12:13 AM

thesecrettokeepingAphp-poweredwebsiterunningsmoothlydlyUnderHeavyloadInvolvesEveralKeyStrategies : 1) ubstractOpCodeCachingWithOpCacheTecescripteExecutionTime, 2) usedatabasequeryCachingwithRedSendatabaseload, 3) LeverAgeCdnslikeCloudforforporerververforporporpin

PHP의 종속성 주입 : 초보자를위한 코드 예제PHP의 종속성 주입 : 초보자를위한 코드 예제May 14, 2025 am 12:08 AM

Code는 코드가 더 명확하고 유지 관리하기 쉽기 때문에 의존성 주입 (DI)에 관심을 가져야합니다. 1) DI는 클래스를 분리하여 더 모듈 식으로 만들고, 2) 테스트 및 코드 유연성의 편의성을 향상시키고, 3) DI 컨테이너를 사용하여 복잡한 종속성을 관리하지만 성능 영향 및 순환 종속성에주의를 기울이십시오. 4) 모범 사례는 추상 인터페이스에 의존하여 느슨한 커플 링을 달성하는 것입니다.

PHP 성능 : 응용 프로그램을 최적화 할 수 있습니까?PHP 성능 : 응용 프로그램을 최적화 할 수 있습니까?May 14, 2025 am 12:04 AM

예, PPAPPLICATIONISPOSSIBLEADESLESTION.1) INVERECINGUSINGAPCUTERODUCEDABASELOAD.2) INCODINCEDEXING, ENGICIONEQUERIES 및 CONNECTIONPOULING.3) 향상된 보드 바이어링, 플로 팅 포르코 잉을 피하는 최적화 된 APPCUTERODECEDATABASELOAD.2)

PHP 성능 최적화 : 궁극적 인 가이드PHP 성능 최적화 : 궁극적 인 가이드May 14, 2025 am 12:02 AM

theKeyStrategiesToSINCINTIFILINTINTIFILINTINTHPPORMATIONPERFORMANCEARE : 1) USEOPCODECACHING-CCHACHETEDECUTECUTINGTIME, 2) 최적화 된 ABESINSTEMENTEMENDSTEMENTEMENDSENDSTATEMENTENDS 및 PROPERINDEXING, 3) ConfigureWebSerVERSLIKENGINXXWITHPMFORBETPERMERCORMANCES, 4)

PHP 의존성 주입 컨테이너 : 빠른 시작PHP 의존성 주입 컨테이너 : 빠른 시작May 13, 2025 am 12:11 AM

aphpdectionenceindectioncontainerisatoolthatmanagesclassdependencies, 향상 Codemodularity, testability 및 maintainability.itactAsacentralHubForCreatingAndingDinjectingDingingDingingdecting.

PHP의 종속성 주입 대 서비스 로케이터PHP의 종속성 주입 대 서비스 로케이터May 13, 2025 am 12:10 AM

대규모 응용 프로그램의 경우 SELLENCIONINGESS (DI)를 선택하십시오. ServicElocator는 소규모 프로젝트 또는 프로토 타입에 적합합니다. 1) DI는 생성자 주입을 통한 코드의 테스트 가능성과 모듈성을 향상시킵니다. 2) Servicelocator는 센터 등록을 통해 서비스를 얻습니다. 이는 편리하지만 코드 커플 링이 증가 할 수 있습니다.

PHP 성능 최적화 전략.PHP 성능 최적화 전략.May 13, 2025 am 12:06 AM

phPapplicationSCanBeoptimizedForsPeedandefficiencyby : 1) ENABLEOPCACHEINPHP.INI, 2) PREPAREDSTATEMENTSWITHPDOFORDATABASEQUERIES 사용

PHP 이메일 검증 : 이메일이 올바르게 전송되도록합니다PHP 이메일 검증 : 이메일이 올바르게 전송되도록합니다May 13, 2025 am 12:06 AM

phpeMailValidationInvoLvestHreesteps : 1) formatValidationUsingRegularexpressionsTochemailformat; 2) dnsValidationToErethedomainHasaValidMxRecord; 3) smtpvalidation, theSTHOROUGHMETHOD, theCheckSiftheCefTHECCECKSOCCONNECTERTETETETETETETWERTETWERTETWER

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구