PHP解決搶購、秒殺、搶樓、抽獎等阻塞式高并發庫存防控超量的思路方法

轉載鏈接:http://www.4u4v.net/thinking-approach-to-buy-spike-grab-floor-sweepstakes-and-other-high-concurrent-blocking-prevention-excess-inventory-solve-php.html


如今在電商行業里,秒殺搶購活動已經是商家常用促銷手段。但是庫存數量有限,而同時下單人數超過了庫存量,就會導致商品超賣甚至庫存變負數的問題。
又比如:搶購火車票、論壇搶樓、抽獎乃至爆紅微博評論等也會引發阻塞式高并發問題。如果不做任何措施可能在高瞬間造成服務器癱瘓,如何解決這個問題呢?
這里提出個人認為比較可行的幾個思路方法:

方案一:使用消息隊列來實現

可以基于例如MemcacheQ等這樣的消息隊列,具體的實現方案這么表述吧
比如有100張票可供用戶搶,那么就可以把這100張票放到緩存中,讀寫時不要加鎖。 當并發量大的時候,可能有500人左右搶票成功,這樣對于500后面的請求可以直接轉到活動結束的靜態頁面。進去的500個人中有400個人是不可能獲得商品的。所以可以根據進入隊列的先后順序只能前100個人購買成功。后面400個人就直接轉到活動結束頁面。當然進去500個人只是舉個例子,至于多少可以自己調整。而活動結束頁面一定要用靜態頁面,不要用數據庫。這樣就減輕了數據庫的壓力。

方案二:當有多臺服務器時,可以采用分流的形式實現

假設有m張票, 有n臺產品服務器接收請求,有x個請求路由服務器隨機轉發
直接給每臺產品服務器分配 m/n張票
每臺產品服務器內存做計數器,比如允許m/n*(1+0.1)個人進來。
當內存計數器已滿:
后面進的人, 直接跳到到轉到活動結束的靜態頁面,
通知路由服務器,不在路由到這臺服務器(這個值得商討)。
所有產品服務器進來的m/n*(1+0.1)個人再全部轉發到一臺付款服務器上,進入付款環節,看誰手快了,這時候人少,加鎖什么的就簡單的。

方案三、如果是單服務器,可以使用Memcache鎖來實現

product_key 為票的key
product_lock_key 為票鎖key
當product_key存在于memcached中時,所有用戶都可以進入下單流程。
當進入支付流程時,首先往memcached存放add(product_lock_key, “1″),
如果返回成功,進入支付流程。
如果不成,則說明已經有人進入支付流程,則線程等待N秒,遞歸執行add操作。

方案四、借助文件排他鎖

在處理下單請求的時候,用flock鎖定一個文件,如果鎖定失敗說明有其他訂單正在處理,此時要么等待要么直接提示用戶"服務器繁忙"
本文要說的是第4種方案,大致代碼如下

阻塞(等待)模式:

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

非阻塞模式:
<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX | LOCK_NB))
{//..處理訂單flock($fp,LOCK_UN);
}
else
{echo "系統繁忙,請稍后再試";
}fclose($fp);
?>

方案五、管道鎖與庫存控制

入口我們看做一個管道(tube),假定每一個購票者給大概5分鐘可以完成購票,那么超過5分鐘后或者已經買到票,就會讓出位置讓后面的人進入售票大廳,當然這是理想化想法,但至少我們把壓力控制在我們可以處理的能力之內,要不然服務器宕機,欲哭無淚。

創建管道:
/**
* 創建管道 默認30個入口
* @param string $tubeName
* @param int $max
* @return bool
*/
static public function createTube($tubeName, $max = 30) {if (!$beanstalk = Common::getBeanstalkHandle()) return false;$beanstalk->use_tube($tubeName);$i = 0;while ($i < $max) {$beanstalk->put(1);$i++;}return true;
}

實現管道鎖
/**
* 采用管道方式進行加鎖,以限制同時進行某個流程的并發數
* @param string $name 管道名稱
* @param int $delay 出管理延遲時間默認為5秒
* @return bool
*/
public function tubeLock($name, $delay = 5) {$beanstalk = Common::getBeanstalkHandle();$beanstalk->watch($name);$return = false;$job = $beanstalk->reserve_with_timeout();if ($job['id'] > 0) $return = $beanstalk->release($job['id'], 1024, $delay);$beanstalk->ignore($name);return $return;
}


提前創建好管道,在并發流程中:


到此為止,如我們所愿,我們已經控制了并發,我們已經把我們能力范圍內可以控制的人放進來了,其它人只能繼續等待...
剩下就是庫存問題了,庫存控制原則:

庫存數不能<0,否則問題大了,商品超賣了,用戶下了單,但沒貨發給賣家,那你就等著投訴吧。

請看下面一個sql(數據庫是InnoDB):
/**
*
* 更新庫存
* @param int $num
* @param int $id
*/
public function updateQuantity($num, $<span style="background-color: rgb(255, 255, 255); ">goodsid</span>) {$sqlPart = $num < 0 ? ' AND quantity >= ' . abs($num) : '';$sql = 'UPDATE %s SET quantity = quantity + ?, sale_num = sale_num - ? WHERE id = ?' . $sqlPart;return $this->_update($sql, array(intval($num), intval($num), intval($goodsid));
}


重點看sqlPart部分,這里巧妙和利用mysql的行級鎖,把庫存不可能為0的控制權交給了mysql來處理,此乃點晴之筆。

補充說明:
我通過你的問題,想象了一下你的環境。
可能會有100張票,但1萬人搶。
你可以在服務器上做一個消息列隊。不論多少人搶票,都先放入消息列隊中。這樣,我們就把高并發,變成了統一的單線程。
這時候一切都好辦了。優點是緩解了MYSQL的瞬時壓力
但缺點是,如果1秒內1萬人點擊搶票。有可能會造成瞬時用戶訪問困難。(因為大家都在列隊)
如果你覺得慢了幾百毫秒不能忍,那你就需要換一個做法:
做一個競爭鎖,防止多個用戶同時獲取一張票。(票在MYSQL中)
在內存中存入一個標簽,來確定是否還有票。
當內存標簽說:沒有票了。 剩下的用戶一律歇菜。
這樣的優點是不論MYSQL,還是用戶,都很輕松。
缺點是,稍微有點小麻煩。 看你具體需求了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276045.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276045.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276045.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

看了就會的 Node.js 三大基礎模塊常用 API

大家好&#xff0c;我是若川。歡迎加我微信 ruochuan12&#xff0c;加群交流學習。今天分享一篇nodejs基礎的文章。點擊下方卡片關注我&#xff0c;或者查看源碼等系列文章。在日常使用 Node 進行開發的時候&#xff0c;會使用到一些文件系統、路徑操作等基礎 API&#xff0c;這…

vue-cli3插件初體驗

vue-cli3發布自2018年8月&#xff0c;距離現在還不是特別久&#xff0c;最好搭建項目剛好用到&#xff0c;所以寫下這篇文章&#xff0c;記錄一下踩坑經歷。vue的作者說過&#xff0c;vue-cli的本質是模版的拉取&#xff0c;太多的配置導致了模版的難以維護&#xff0c;所以重構…

ios設計登錄功能_親愛的產品設計師,這是iOS 14的新功能

ios設計登錄功能On June 22, 2020 Apple previewed iOS 14 for the first time. As always there are quite some changes you should know about as a product designer like widgets, pickers, app clips, permissions and more.2020年6月22日&#xff0c;Apple首次預覽iOS 1…

c++ int 轉 short_C/C++結構體內存對齊

在面試或工作中&#xff0c;經常會遇到內存對齊的問題。這里結合我的理解談一談對內存對齊的理解。1. 為什么要內存對齊&#xff0c;不對齊會怎么樣&#xff1f;內存中存放數據是為了給CPU使用&#xff0c;CPU訪問內存數據時會受到地址總線寬度的限制&#xff0c;也就是一次能從…

對于日訪問量達到1W IP的處理方法

轉自&#xff1a;http://www.java123.net/56026-2.html 對于日訪問量達到1W IP的處理方法 一、1萬ip真是不高&#xff1a; 1.常用數據用緩存&#xff0c;減輕數據庫壓力。 2.詳細頁數據生成靜態頁面。 二、10000算是相當小的了,不需要什么特殊的處理機制,只要符合最一般的…

數據契約(DataContract)

WCF第一要素就是契約: 服務契約用于聲明可用于遠程訪問的類型。在Interface或class開始處使用服務契約標簽. [ServiceContract] Public interface Iservice { } 接口調用契約的好處: 1. 同一服務類型可以實現多個不相干的服務契約. 2. 有利于版本升級 3. 按照…

jakob slam_Jakob Nielsen針對用戶界面設計的第二種可用性啟發法

jakob slamIn the pursuit of providing great user experiences, it’s imperative that digital products are evaluated. A 為了提供出色的用戶體驗&#xff0c;必須對數字產品進行評估。 一個 heuristic evaluation is essential to delivering great user experiences. I…

微軟Office 365正式上架Mac App Store

今天&#xff0c;Office 365正式在Mac App Store上架&#xff0c;Mac用戶可以輕松下載Word&#xff0c;Outlook&#xff0c;Excel&#xff0c;PowerPoint&#xff0c;OneNote以及整套微軟的熱門應用程序。用戶還可以從應用程序內訂購Office 365。蘋果全球開發者關系高級主管Sha…

一文搞懂瀏覽器原理

大家好&#xff0c;我是若川。最近這幾年&#xff0c;云計算的普及和 HTML5 技術的快速發展&#xff0c;越來越多的應用轉向了瀏覽器 / 服務器&#xff08;B/S&#xff09;架構&#xff0c;這種改變讓瀏覽器的重要性與日俱增&#xff0c;視頻、音頻、游戲幾大核心場景也都在逐漸…

python處理excel可視化_python如何將excel數據處理可視化

python將excel數據處理可視化的方法&#xff1a;首先安裝xlrd與xlwt庫&#xff0c;進行表格讀取&#xff1b;然后使用pyecharts生成Echarts圖表的類庫&#xff1b;最后安裝Echarts讀取Excel數據及顯示即可。python將excel數據處理可視化的方法&#xff1a;Excel表操作python操作…

dataframe中將一列數據切分成多列

為什么80%的碼農都做不了架構師&#xff1f;>>> 原sheet中數據 目的 將【備注】列切分成【key】列和【value】列 Python sheet[key] sheet[備注].str.extract(r(_.*(?\u503c))) sheet[value] sheet[備注].str.extract(r((?<).*))結果 參考 pandas.Series.st…

matplotlib可視化_EDA:Geopandas,Matplotlib和Bokeh中的可視化

matplotlib可視化Nowadays, everyone is immersed with plenty of data from news sources, cellphones, laptops, workplaces, and so on. Data conveys with tons of information from different data variables like date, string, numeric, and geographical format. How t…

(轉)結婚那天,媽問我:坐在角落里象兩個要飯模樣的人是誰?

人人看到的文章 很感人~~~~結婚那天&#xff0c;媽問我&#xff1a;坐在角落里象兩個要飯模樣的人是誰&#xff1f; 我看過去的時候&#xff0c;有個老頭正盯著我&#xff0c;旁邊還有個老太太&#xff0c;發現我看著他們時趕忙低下頭。我不認識他們但也不象要飯的&#xff0c;…

nginx-1.13.x源碼安裝

Nginx 安裝配置【依賴庫】[ zlib ]&#xff08;下載&#xff09;http://download.chinaunix.net/download.php?id24013&ResourceID12241 [ pcre ]apt-get install libpcre-dev[ openssl ]&#xff08;下載&#xff09;http://download.chinaunix.net/download.php?id3937…

小技巧!CSS 整塊文本溢出省略特性探究

大家好&#xff0c;我是若川。歡迎加我微信 ruochuan12&#xff0c;長期交流學習。今天的文章很有意思&#xff0c;講一講整塊文本溢出省略打點的一些有意思的細節。點擊下方卡片關注我&#xff0c;或者查看源碼系列文章。文本超長打點我們都知道&#xff0c;到今天&#xff08…

linux配置ip地址 suse_SUSE Linux下設置IP的兩種方法

第一種SUSE Linux IP設置方法ifconfig eth0 192.168.1.22 netmask 255.255.255.0 uproute add default gw 192.168.1.2釋義&#xff1a;#IP配置&#xff0c;包括子網掩碼,看情況修改eth0和192.168.1.22#網關修改 ,看情況修改192.168.1.2第二種SUSE Linux IP設置方法在suse操作系…

寒假作業3:抓老鼠啊

7-1 抓老鼠啊~虧了還是賺了&#xff1f; &#xff08;20 分&#xff09; 某地老鼠成災&#xff0c;現懸賞抓老鼠&#xff0c;每抓到一只獎勵10元&#xff0c;于是開始跟老鼠斗智斗勇&#xff1a;每天在墻角可選擇以下三個操作&#xff1a;放置一個帶有一塊奶酪的捕鼠夾(T)&…

筆記本移交_創建完美的設計移交

筆記本移交重點 (Top highlight)Design specifications (specs) are guidelines that developers will use to implement a design. Think of an architect providing building blueprints to the construction team. Many designers think of specs as mindless zombie work. …

大手筆,送¥1599的Apple AirPods Pro和獨家禮物等

大家好&#xff0c;我是若川。為感謝公眾號讀者們長久以來的支持&#xff0c;本次我聯合幾位前端界大佬給大家送超級福利了。除了聯合福利之外&#xff0c;每位前端大佬還帶了專屬禮品送給大家&#xff0c;所有抽獎均可重復參與、可重復中獎&#xff0c;詳情見下文每個公眾號的…

jQuery1.4新特性

1. 傳參給 jQuery(…) 之前&#xff0c;jQuery可以通過 attr 方法設置元素的屬性&#xff0c;既可傳屬性的名和值&#xff0c;也可以是包含幾組特定 屬性名值對 的 對象。在 jQuery 1.4 中&#xff0c;你可以把一個參數對象作為第二個參數傳給 jQuery 函數本身&#xff0c;同時…