前言 ~
? ? ? ? 我們知道現(xiàn)在的京東、淘寶、以及類似購物的一些項目,他們都會定期或者不定期的舉行秒殺活動,以次來提高消費者的購買力,但是我們知道秒殺這個功能怎么實現(xiàn)的嘛?實現(xiàn)過程會遇到什么難題嘛?現(xiàn)在跟隨小編的腳步,讓我們一起邁進秒殺系統(tǒng)的實現(xiàn)分析。
一、秒殺系統(tǒng)業(yè)務流程

? ? ? ? 這一流程雖然看似簡單,但是里面還是存在著問題的,因為我們知道秒殺活動不是只有一個人在對該商品進行操作,而是上萬、上十萬以上的消費者在對一類商品進行操作,這樣就會產(chǎn)生高并發(fā)的問題,并且假如有10萬個消費者在對一類商品進行秒殺購買,那么請求接口的次數(shù)就不止是10萬那么少了,可能是50萬,也可能更高,因為所有人在參與點擊秒殺時候,都會嘗試多次點擊,期待增加成功的機會。
? ? ? ? 解決這一問題,我們可以在前端進行按鈕頻繁點擊操作的限制,防止重復提交,減少90%的重復請求。就是讓用戶點擊一次后,就不讓他點擊了。如圖類似:

? ? ? ? 就算對前端頁面按鈕操作進行了控制,那么也會有很大的接口請求量涌入,此時如果如此巨大的接口請求量必定會對服務器產(chǎn)生巨大的損害。
? ? ? ?解決這一問題,就要考慮到負載均衡了,負載均衡簡單來說就是將多個請求平均分發(fā)給多臺服務器,由這些服務器共同處理用戶請求,到達減緩服務器負載的效果。負載均衡有硬件和軟件的解決方案,硬件可以使用lvs、F5、Radware等,軟件可以使用nginx,可以實現(xiàn)多個tomcat的負載均衡。除了此方式,還可以使用限制流量、分散流量等操作。

? ? ? 修改庫表,主要是修改該商品作為秒殺商品提供總的商品數(shù)量,但是畢竟是秒殺活動,所以該商品的數(shù)量是固定的,而如此大用戶量的秒殺,可能會造成商品數(shù)據(jù)呈現(xiàn)負數(shù)的情況。
? ? ? ?解決這一問題,可以使用分布式鎖,分布式鎖是一種悲觀鎖的形式,有些情況下也可以使用樂觀鎖。可以給sql一個條件,當商品數(shù)量減一的結果大于或者等于0的時候,才給予修改商品數(shù)量,如果小于0,則不給予修改。
? ? ?例如該SQL:update tb_miaosha set goods_num=goods_num-1 where goods_code='' and?goods_num>=0.
? ? ? ?將用戶信息和商品信息添加到秒殺表,這里又會出現(xiàn)一個問題,可能會產(chǎn)生,同一類商品,均由同一個用戶購買,那么一起來參加秒殺的小伙伴們可能不樂意啦,一起來秒殺商品的,憑什么都由你一個人購買了。
? ? ? 解決這一問題,而前臺我們可以使用nginx進行ip限制,后臺代碼就要使用到redis-------key-value型的非關系型數(shù)據(jù)庫了,對用戶進行限制,比如限制該用戶20秒之內(nèi),只能秒殺一次,從而解決這一問題,如果redis中沒有這個key,那么就設置,并且設置過期時間,如果redis中存在這個key,那么就不進行設置。組合命令 set key valye EX time NX
EX:設置過期時間
time:過期時間
NX:判斷redis數(shù)據(jù)庫中是否有這個key
? ?后臺代碼:jedis.set("要設置的key","該key的值","NX","EX",10);
? ? ? ? 如果使用了redis進行用戶的限制,但還是會出現(xiàn)數(shù)據(jù)庫還承受不了過濾之后的請求量,這時候,應該怎么辦勒?這時候肯定會有小伙伴提出弄個數(shù)據(jù)庫集群呀,這種方法是好,但是有沒有不用花錢買服務器弄數(shù)據(jù)庫集群就可以實現(xiàn)的呢?辦法還是有的。
? ? ? ?解決方法,可以使用令牌機制,?我們知道商品數(shù)量是有限的,能秒殺成功的請求較少,我們可以預先(異步)初始化一個和商品數(shù)量相同的令牌池放入到內(nèi)存中,當用戶發(fā)來請求,就去令牌池中取令牌,令牌數(shù)量有限,先到先得,拿到令牌的可以請求操作數(shù)據(jù)庫,從而減緩數(shù)據(jù)庫的壓力。
? ? ? ? 當用戶登陸的時候,讓客戶端攜帶token,發(fā)送請求到服務器端,驗證成功后讓用戶登錄成功,當用戶進入到秒殺頁面,用戶點擊秒殺按鈕的時候,讓客戶端也攜帶token,并且在服務器端設置一個令牌池,令牌池數(shù)量為秒殺商品數(shù)量,當用戶每點擊秒殺按鈕,就去令牌池中去令牌,先到先得,直到令牌池數(shù)量為空。

非常感謝騰訊課堂的Tony老師視頻教材?。。?!