php无法下单功能,PHP如何解决并发下单问题?(不一定是下单,举个例)
我們知道數據庫處理sql是一條條處理的,假設購買商品的流程是這樣的:
sql1:查詢商品庫存
if(庫存數量 > 0)
{
//生成訂單...
sql2:庫存-1
}
當沒有并發時,上面的流程看起來是如此完美,假設同時兩個人下單,而庫存只有1個了,在sql1階段兩個人查詢到的庫存都是>0的,于是最終都執行了sql2,庫存最后變為-1,超售了,要么補庫存,要么等用戶投訴吧。
解決這個問題比較好的方法是什么呢?
回復內容:
我們知道數據庫處理sql是一條條處理的,假設購買商品的流程是這樣的:
sql1:查詢商品庫存
if(庫存數量 > 0)
{
//生成訂單...
sql2:庫存-1
}
當沒有并發時,上面的流程看起來是如此完美,假設同時兩個人下單,而庫存只有1個了,在sql1階段兩個人查詢到的庫存都是>0的,于是最終都執行了sql2,庫存最后變為-1,超售了,要么補庫存,要么等用戶投訴吧。
解決這個問題比較好的方法是什么呢?
用事務處理機制
數據表加鎖也行(如果你用InnoDB引擎就用行鎖;如果你用MyISAM引擎就用表鎖)
庫存字段改成unsigned int。
這樣的話不會<0,頂多就SQL執行出錯。
也可以用memcached/redis來緩存結果,從緩存中查詢。
1.MySQL數據庫加鎖,樂觀鎖 和 悲觀鎖
2.用隊列,排隊逐一去生成訂單
庫存緩存一般都是 有的吧,如果有并發需求。 還有就是加鎖,或者放到隊列執行sql。
有種很笨的方法,已樓主的假設為例:
sql1:查詢商品庫存 (假設查出的庫存為10)
if(10 > 0)
{
//生成訂單...
sql2: 10 - 1 (此時庫存為9了)
//再校驗庫存
sql3: 查詢商品庫存 == 9 (如果此時有并發情況,那查出來的庫存可能為8、7等,這時拋出異常,事務回滾,該筆訂單無效。)
}
處理高并發一般來說都會用到Redis,使用Redis的list數據結構(高并發當然要異步隊列咯)來存儲請求過來的訂單信息,然后啟用redis的事務機制(見:http://redis.io/topics/transactions),加入指定key的list前,判斷該list等長度是否超過redis中保存的指定商品庫存值,如果超過則不操作,如果不超過,則進行插入,插入之后,再次判斷該list的長度是否超過redis中保存的指定商品的庫存值,如果超過則回滾,否則提交。
想問一下,并發量大的情況下,是怎么做的呢?
1.用事務保持操作原子性,
2.在修改庫存的時候先用select...for update把數據鎖好
update table set n = n-x where n >= x
不需要事務,直接獲取affected row count來判斷是否扣成功,后到的那一條因為n=0,affected row肯定為0
相關標簽:php 并發
本文原創發布php中文網,轉載請注明出處,感謝您的尊重!
總結
以上是生活随笔為你收集整理的php无法下单功能,PHP如何解决并发下单问题?(不一定是下单,举个例)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php制作曲线柱形图的框架,用GD图库生
- 下一篇: php扩展库加密如何解密,如何利用Mcr