1. 程式人生 > >秒殺系統設計優化

秒殺系統設計優化

 

https://www.cnblogs.com/luyucheng/p/6340758.html

12306搶票,票是有限的,庫存一份,瞬時流量非常多,都讀相同的庫存,讀寫衝突,鎖非常嚴重;
小米手機每週二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾百幾千萬;
這是秒殺業務難的地方。那我們怎麼優化秒殺系統呢?

一、難點

(1)高併發
使用者在秒殺開始前,通過不停重新整理瀏覽器頁面以保證不會錯過秒殺,這些請求如果按照一般的網站應用架構,訪問應用伺服器、連線資料庫,會對應用伺服器和資料庫伺服器造成負載壓力。
(2)超賣
由於庫存併發更新的問題,導致在實際庫存已經不足的情況下,庫存依然在減,導致賣家的商品賣得件數超過秒殺的預期。

二、架構

常見的站點架構基本是這樣的:
(1)瀏覽器端,最上層,會執行到一些JS程式碼
(2)站點層,這一層會訪問後端資料,拼HTML頁面返回給瀏覽器
(3)服務層,向上遊遮蔽底層資料細節,提供資料訪問
(4)資料層,最終的庫存是存在這裡的

三、思路

(1)將請求儘量攔截在上游:傳統秒殺系統之所以掛,請求都壓倒了後端資料層,資料庫讀寫鎖衝突嚴重,導致響應慢,下單基本不能成功
(2)利用快取:這是一個典型的讀多些少的應用場景,非常適合使用快取

四、解決方案

(1)瀏覽器層請求攔截
1.產品層面,使用者點選“查詢”或“購票”後,按鈕置灰,禁止使用者重複提交請求
2.js層面,限制使用者在n秒之內只能提交一次請求
(2)站點層請求攔截與頁面快取
1.靜態化,將活動頁面上的所有可以靜態的元素全部靜態化,並儘量減少動態元素
2.限頻率,同一個UID,限制訪問頻率,做頁面快取,n秒內到達站點層的請求,均返回同一頁面
(3)服務層請求攔截與資料快取
1.對於寫請求,將所有寫請求在快取(Redis或Memcached)中,做請求單佇列排隊,每次只透過有限的寫請求非同步寫入到資料層,如果均成功再放下一批,如果庫存不夠則佇列裡的寫請求全部返回“已售完”
2.對於讀請求,用Redis或Memcached
快取寫效能和讀效能都遠高於MySQL,只有非常少的寫和讀快取的請求會透到資料層去
(4)資料層
1.嘗試扣減庫存,扣減庫存成功才會進行下單邏輯(由於MySQL事務的特性,不可能完全避免超賣)

UPDATE table_name SET n=n-1 WHERE n>1;

2.扣減庫存後進行檢查,保證減完不能等於負數
檢視更多:
開發一個微信小程式例項教程
HTTP協議整理
PHP安全之Web攻擊
MySQL優化
Linux下常見的IO模型
參考資料:
https://my.oschina.net/xianggao/blog/524943
http://www.infoq.com/cn/articles/flash-deal-architecture-optimization

https://www.cnblogs.com/luyucheng/p/6340758.html

12306搶票,票是有限的,庫存一份,瞬時流量非常多,都讀相同的庫存,讀寫衝突,鎖非常嚴重;
小米手機每週二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾百幾千萬;
這是秒殺業務難的地方。那我們怎麼優化秒殺系統呢?

一、難點

(1)高併發
使用者在秒殺開始前,通過不停重新整理瀏覽器頁面以保證不會錯過秒殺,這些請求如果按照一般的網站應用架構,訪問應用伺服器、連線資料庫,會對應用伺服器和資料庫伺服器造成負載壓力。
(2)超賣
由於庫存併發更新的問題,導致在實際庫存已經不足的情況下,庫存依然在減,導致賣家的商品賣得件數超過秒殺的預期。

二、架構

常見的站點架構基本是這樣的:
(1)瀏覽器端,最上層,會執行到一些JS程式碼
(2)站點層,這一層會訪問後端資料,拼HTML頁面返回給瀏覽器
(3)服務層,向上遊遮蔽底層資料細節,提供資料訪問
(4)資料層,最終的庫存是存在這裡的

三、思路

(1)將請求儘量攔截在上游:傳統秒殺系統之所以掛,請求都壓倒了後端資料層,資料庫讀寫鎖衝突嚴重,導致響應慢,下單基本不能成功
(2)利用快取:這是一個典型的讀多些少的應用場景,非常適合使用快取

四、解決方案

(1)瀏覽器層請求攔截
1.產品層面,使用者點選“查詢”或“購票”後,按鈕置灰,禁止使用者重複提交請求
2.js層面,限制使用者在n秒之內只能提交一次請求
(2)站點層請求攔截與頁面快取
1.靜態化,將活動頁面上的所有可以靜態的元素全部靜態化,並儘量減少動態元素
2.限頻率,同一個UID,限制訪問頻率,做頁面快取,n秒內到達站點層的請求,均返回同一頁面
(3)服務層請求攔截與資料快取
1.對於寫請求,將所有寫請求在快取(Redis或Memcached)中,做請求單佇列排隊,每次只透過有限的寫請求非同步寫入到資料層,如果均成功再放下一批,如果庫存不夠則佇列裡的寫請求全部返回“已售完”
2.對於讀請求,用Redis或Memcached
快取寫效能和讀效能都遠高於MySQL,只有非常少的寫和讀快取的請求會透到資料層去
(4)資料層
1.嘗試扣減庫存,扣減庫存成功才會進行下單邏輯(由於MySQL事務的特性,不可能完全避免超賣)

UPDATE table_name SET n=n-1 WHERE n>1;

2.扣減庫存後進行檢查,保證減完不能等於負數
檢視更多:
開發一個微信小程式例項教程
HTTP協議整理
PHP安全之Web攻擊
MySQL優化
Linux下常見的IO模型
參考資料:
https://my.oschina.net/xianggao/blog/524943
http://www.infoq.com/cn/articles/flash-deal-architecture-optimization