背景介紹:
對於一個互聯網平台來說,高並發是經常會遇到的場景。最有代表性的比如秒殺和搶購。高並發會出現三個特點:
1、高並發讀取
2、高並發寫入(一致性)
3、出現超賣問題
如何有效的解決這三個問題是應對高並發的關鍵。
一般系統都分為前端和后端。
前端如何應對?
1、緩存靜態數據,例如圖片,html頁面,js等
2、搭建負載均衡集群,目前采用較多的為nginx
3、進行ip限制,限制同一個ip單位時間內發起的請求數量。或者建立ip黑名單,避免惡意攻擊
4、考慮系統降級。比如當達到系統負載的時候返回一個靜態處理頁面
后端如何應對?
1、采用mysql讀寫分離,但是當高並發的時候mysql性能會降低。 一般來說,MySQL的處理性能會隨着並發thread上升而上升,但是到了一定的並發度之后會出現明顯的拐點,之后一路下降,最終甚至會比單thread的性能還要差。比如加減庫存的操作,通常並發量不高的做法為:update xxx set count=count-xx where curcount>xx;這樣可以充分利用mysql的事務鎖來避免出現超賣的情況。但是並發量上了后,會因為排他鎖等待而大大降低性能。
2、采用redis數據庫,前置到mysql。思路如下:
2.1系統啟動后,初始化sku信息到redis數據庫,記錄其可用量和鎖定量
2.2使用樂觀鎖,采用redis的watch機制。邏輯為:
1.定義門票號變量,設置初始值為0。watchkey
2.watch該變量,watch(watchkey);
3.使用redis事務加減庫存。首先獲取可用量和搶購量比較,如果curcount>buycount,那么正常執行減庫存和加鎖定量操作:
multi;
redis incr watchkey;
redis decrby curcount buycount;
redis incrby lockcount buycount;
exec;
由於上述操作都在事務內進行,一旦watchkey被其他的事務修改過,那么exec將返回nil,如此就放棄本次請求。一般都是在循環中重復嘗試直到成功或沒有可用量。
最后通過訂單信息流,保證mysql數據庫的最終一致性。
3、其他方式希望大家補充!