PHP如何解決並發下單問題?(不一定是下單,舉個例)

來源:互聯網
上載者:User
關鍵字 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

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.