Java電商項目,秒殺,搶購等高併發場景的具體場景和一些概念以及處理思路

這裏我借鑑了網上其餘大佬的觀點:前端

一:
高併發帶來的挑戰
  緣由:秒殺搶購會常常會帶來每秒幾萬的高併發場景,爲了更快的返回結果給用戶。
  吞吐量指標QPS(每秒處理請求數),假設一個業務請求響應耗時爲100ms,咱們有10臺Web服務器,每臺給它最大鏈接數500。
  理想化計算方式:
  10 * 500/0.1 = 50000
  難道咱們真的有處理5萬併發?
  否則。高併發場景下,Web服務器打開了越多的鏈接進程,CPU切換上下文的也越多。會增長CPU的壓力,致使CPU業務請求響應耗時 會超出預期不少。可能你的系統只能承受2萬的併發了。
  這個時候咱們須要怎麼作?數據庫

  答:一、請求的接口須要設計合理,怎麼作?
    動靜分離,靜態HTML能夠經過Ng部署。
    核心瓶頸在後臺接口上,高併發狀況下存儲壓力大,MySQL不合適,用Redis內存讀寫快。
    二、重啓與過載保護
    若是你2萬的併發硬抗3萬流量,致使服務器沒有鏈接進程可用,系統就要陷入異常狀態了,響應時間極慢。當系統響應時間好久 ,有些用戶越喜歡頻繁點擊。惡性循環致使「雪崩」,致使整個系統垮掉,就算重啓服務也無濟於事。
    怎麼作?
    過載保護,若是檢測到系統滿載狀態,拒絕請求自我保護。
    (1)前端過濾簡單方式
    (2)過載保護設置在CGI入口層,將客戶端的請求直接返回緩存

二:
高併發下的數據安全
  多線程寫入同一個文件的時候,會出現「線程安全問題」。高併發的數據安全就是這個道理。好比有可能會出現超發。
  方案:
  悲觀鎖思路:修改數據時,鎖定狀態,排斥外部請求的修改。
  缺點:
  高併發下某些線程可能永遠都搶不到這個「鎖」,請求就會死在那裏。堆積到必定程度,鏈接數被耗盡,系統異常。
  FIFO隊列思路:請求都排好隊,不會致使某些請求永遠拿不到鎖。
  缺點:
  高併發可能致使隊列內存「撐爆」,若是設置一個極大的內存隊列,系統處理請求的速度根本跟不上不斷快速涌入的請求。越積 越多,仍是會致使響應變慢,系統陷入異常。
  樂觀鎖思路:
  跟悲觀鎖相比,樂觀鎖都有資格去執行請求,但會得到一個版本號,符合版本號的纔算更新成功。
  缺點:
  加大計算機CPU計算的開銷,可是這是一個比較好的解決方案。
  緩存服務器思路:
  Redis分佈式要保證數據都能可以平均的緩存到每一臺機器,首先想到的作法是對數據進行分片,由於Redis是key-value存儲的, 首先想到的是Hash分片,可能的作法是對key進行哈希運算,獲得一 個             long值對分佈式的數量取模會獲得一個一個對應數據庫的一 個映射,沒有讀取就能夠定位到這臺數據庫

三:
高併發下的水分與查殺。
  緣由:秒殺或是搶購等海量請求有時候並非真正的用戶在發送請求,有些爲了「搶」到商品會使用一些「刷票」等相似的工具。這種作 法是幫助他們發送更多的請求到服務器。更高級的還製做一些自動請求            腳本。這些作法都是使本身的請求數佔比多,成功率高。
        這些很顯然都是屬於做弊行爲,不過,咱們也有一些解決方案。
  答:分爲如下幾種狀況
  一、同一個帳號,一次性發送多個請求。
  高併發有可能會致使跳過某些邏輯判斷。
  方案:程序入口處,一個用戶只容許一次請求,其餘過濾。能夠經過Redis內存緩存服務,寫入一個標誌位(只容許一個請求成功 ,結合watch樂觀鎖的特性)
  二、多個帳號,一次性發送多個請求
  不少早期註冊功能沒有限制,致使一些特殊的工做室經過編寫自動註冊腳本註冊一大批「殭屍帳號」。專門作各類刷的行爲,以 及一些轉發抽獎活動,大大提高本身中獎的機率。
  方案:檢測指定機器IP請求頻率,若是一個IP的請求頻率異常的高。給它彈出一個驗證碼或者禁止它的請求。
  三、多個帳號,不一樣IP發送不一樣請求
  有一些機構本身獨佔一批IP,而後作成一個隨機代理IP的服務,有償提供給這些「工做室」使用。還有一些直接黑掉用戶電腦, 轉發IP包,使普通用戶的電腦變成IP代理出口。
  方案:難以分辨了,容易「誤傷」。能夠經過高門檻的業務,或者經過「數據挖掘」來提早清理。安全

我的整理併發解決方案。服務器

a.應用層面:讀寫分離、緩存、隊列、集羣、令牌、系統拆分、隔離、系統升級(可水平擴容方向)。多線程

b.時間換空間:下降單次請求時間,這樣在單位時間內系統併發就會提高。併發

c.空間換時間:拉長總體處理業務時間,換取後臺系統容量空間。分佈式

相關文章
相關標籤/搜索