架構設計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;