關於PHP高併發搶購系統設計

內容
併發搶購系統注意事項
高併發架構設計描述
程序端核心代碼實現
訂單流程mysql 端併發解決方案


注意事項
(1)高併發環境下,對於服務器cup、內存、網絡寬帶使用率會瞬間暴漲,須要注意對同服務器上其餘應用的影響。(項目解耦,高併發應用獨立部署)
(2)服務器高負載運行,容易出現死機,重啓服務器場景,要提早考慮內存(redis)數據備份與恢復,防止用戶搶購數據丟失.
(3)高併發應用首先要注重穩定性,其次是性能上優化.


(4) 一臺服務器可以支持多少併發量
nginx服務爲例:
worker_processes 8;
worker_rlimit_nofile 102400;
use epoll;
worker_connections 102400;
ulimit -n
cat /proc/sys/fs/file-max 


架構設計php

(1)LVS服務, 作負載均衡調度, 採用RD模式, 經過股修改數據包的目的MAC地址實現轉發,該方式性能好, 對併發高應用,適合大規模部署負載均衡機器;抗負載能力強、是工做在網絡4層僅做分發之用,沒有流量的產生;工做穩定,自身有完整的雙機熱備方案 (2)keepalive(vrrp協議方式) 作心跳檢測,支持應用具備高可用性。 (3)nginx工做在網絡的7層,因此它能夠針對http應用自己來作分流策略, 可用說對LVS負載的補充。nginx高效處理高併發請求在於採用異步非阻塞工做方式和epoll IO 模型。   (4)頁面動態數據,用戶數據,搶購商品數據採用Redis存儲。 (5)用戶搶購記錄標識存儲在Redis服務器端。在nginx負載均衡端,應用lua腳本作用戶搶購記錄過濾。 (6)real server端部署 nginx與php, 同時 real server 能夠參與負載端調度。 (7)mysql server cluster 端採用一主多從部署,master負載數據寫及同步到slave, slave負責數據讀取。推薦應用mysql代理組件atlas, 實現對php端對mysql讀寫透明操做。 核心代碼實現 背景 假設每一個用戶只容許搶購一件商品。 預備數據 搶購商品總數存入redis中, 好比十萬個數據 $redisObj = new redis(); $redisObj->set('goods_amount', 1000000); $redis->watch('goods_amount'); //應用redis watch 樂觀鎖 $amount = $redis->get('goods_amount'); if($amount > 0) {  $userInfo = $reids->get('user_info_crc32(url_token)', array('userId'=>120, '....'));      if(empty($userInfo)){                $ret = $redis->multi() ->decr('goods_amount') ->exec();       if($ret){ $reids->set('user_info_crc32(url_token)', array('userId'=>120, '....'));         根據crc32(url_token)惟一索引建立改用戶已搶過商品的標識。(同時標識能夠設置一段時間有效期,例如10分鐘);      write("user_id", {user_id}_success.log);       }else {                 //提示搶購失敗      }  } else {     $redis->unwatch(‘goods_amount');     //提示搶購失敗  } else {     //搶購結束, 封閉入口 } } (1)下一個搶購請求到來時,在nginx服務器lua端,檢查googs_amount搶購商品數量,判斷搶購有沒有結束,在判斷user_info_crc32(url_token)有沒有搶過成功,若是成功跳轉到下單頁面,不然執行搶過流程。 (2)搶購首頁直接高併發靜態資源存儲在cdn 服務端, 來減輕服務端訪問請求的壓力 mysql端併發解決 (1)搶購商品數據預熱,提早存儲在redis中,好比商品名稱,屬性等等。 (2)採用innodb 數據庫引擎,在高併發場景讀操做有優點,合理建立表結構,儘量的減小鏈表查,能夠適當設計表中冗餘字段,sql查詢可以必須走索引。 (3)用戶瀏覽商品詳情頁(須要在redis端作動態數據緩存)  (4)用戶點擊購買跳轉到訂單詳情頁(包括用戶基本信息,商品信息,支付方式,積分消費等數據考慮對數據庫併發查詢壓力,要採用redis緩存策略) (5)訂單數據提早生成,user_id留空,同時經過redis lpush,把連續訂單id,提早同步到redis分佈式集羣,redis集羣支持心調檢測,可以自動作服務奔潰切換。 (6)用戶提交訂單後,  在redis服務lpop拿到一個訂單id, 根據訂單id條件更新用戶user_id等信息。    begin;    update mt_account set user_id=100 where order_id=$orderId and user_id=0 li mit 1;    commit;
相關文章
相關標籤/搜索