秒殺系統難作,是由於庫存有限,不少人會在集中的時間內讀寫有限的數據,在短期內,系統會面臨成千上萬倍的流量進入。那麼如何能作好秒殺系統呢?我認爲核心思想有這麼兩點:前端
-
將請求儘可能的在上游環節就攔截住(不要輕易到數據庫這一級)nginx
-
充分利用緩存redis
那麼這兩點如何實現呢,下面詳細說說:spring
-
最上層是客戶端層,常見的都是瀏覽器訪問。點擊一次【秒殺按鈕】,而後再點一次【秒殺按鈕】,那麼是訪問了兩次後端系統麼?若是用戶手速快一些的話,或者用第三方插件不停的點擊,那麼豈不是多出來不少請求。從產品層面,咱們會設置點擊一次按鈕後,將按鈕置灰,從技術角度,咱們能夠經過JS控制幾秒內只能提交一次請求。看,這就是「將請求儘可能的在上游環節就攔截住」。數據庫
-
固然客戶端層作限制,對於在座的程序猿們都是小意思,由於一抓包,請求長什麼樣子一清二楚,而後寫個腳本,循環調用就行了;爲了防止這樣的狀況發生,後端的服務須要作去重的工做。好比按照用戶名去重,在N秒內,只容許1個請求訪問進來,而後作頁面緩存;好比10秒內發送了一萬次請求,其中1次請求訪問成功並返回了頁面,將這個頁面進行緩存,剩餘9999次請求直接返回這個緩存頁面。後端
-
再往下走,10秒內一個客戶只有一次請求進來,可是若是同時有一百萬個客戶,那麼這10秒內也有有一百萬次訪問,那麼如何應對呢?用【消息隊列】,全部的請求過來,都排隊吧,每次只讓有限的請求去訪問數據。瀏覽器
-
固然訪問數據也不是直接去讀寫數據庫,這裏還有一層數據緩存,好比可使用Memcached或者Redis緩存庫存剩餘,一般在秒殺系統中,這個「庫存」能夠是粗粒度的,也就是說這個數字能夠是不許確的,客戶關心的是買到仍是買不到,而不會關心剩餘數量究竟是20件仍是10件;數據讀操做也能夠放在緩存中,再由緩存和數據庫作數據同步。緩存
-
上面幾步已經攔截了大多數的請求,到DB這一層的時候,基本上沒有什麼壓力了。網絡
秒殺是電商企業最吸引流量,也是最考驗技術的場景!異步
秒殺的系統設計其實遵循「倒金字塔」原理,就是從前端頁面,網絡,到後端服務,數據庫,一一的將請求濾掉,最終讓落在數據庫的數據都是知足要求的有效數據,假設是100萬人參加1000臺機器的秒殺,便是設計100萬-->1000的過濾系統;
要達到這樣的目的一般有下列的手段:
①,前端頁面防重複刷:點擊一次後,按鈕置灰,在指定時間內只容許搶一次!
②,控制網絡流量暴增:將前端頁面放置在CDN節點,防止網絡流量壓力快速增大;
網關進行限流:使用nginx 進行網關限流!
經過設置nginx參數limit_conn_zone ,limit_req_zone ,ngx_http_upstream_module進行限流!
③,後端應用服務:
1,若是沒有使用nginx限流,可以使用spring-cloud-zuul進行網關限流!
2,異步處理 :防止同步調用帶來的阻塞,包括數據落庫等均可以使用異步調用!
3,緩存: 最重要的一步,能夠事先將要秒殺的商品id進行緩存,使用分佈式鎖獲取到id和對應的userid進行綁定,纔算秒殺成功,而後異步保存數據!
使用redis的watch對同一個帳號進行限制;
④,數據庫系統: 使用讀寫分離 ,分庫分表 等手段提高數據庫系統的吞吐量!