日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

管是哪一門語言,并發都是程序員們最為頭疼的部分。同樣,對于一個軟件而言也是這樣,你可以很快增刪改查做出一個秒殺系統,但是要讓它支持高并發訪問就沒那么容易了。比如說:

  • 如何讓系統面對百萬級的請求流量不出故障?
  • 如何保證高并發情況下數據的一致性寫?
  • 完全靠堆服務器來解決嗎?

基本原則

作為一個架構師,首先要勾勒出一個輪廓,如何構建一個超大流量并發讀寫、高性能,以及高可用的系統,這其中有哪些要素需要考慮。

  • 數據要盡量少:首先是指用戶請求的數據能少就少(請求的數據包括上傳給系統的數據和系統返回給用戶的數據),其次還要求系統依賴的數據能少就少(包括系統完成某些業務邏輯需要讀取和保存的數據,這些數據一般是和后臺服務以及數據庫打交道)。
  • 請求數要盡量少:用戶請求的頁面返回后,瀏覽器渲染這個頁面還要包含其他的額外請求,減少請求數最常用的一個實踐就是合并 css 和 JAVAScript 文件,把多個 JavaScript 文件合并成一個文件。
  • 路徑要盡量短:用戶發出請求到返回數據這個過程中,需求經過的中間的節點數。
  • 依賴要盡量少:要完成一次用戶請求必須依賴的系統或者服務,這里的依賴指的是強依賴。
  • 不要有單點:避免將服務的狀態和機器綁定,把服務無狀態化。

做好動靜分離

所謂“動靜分離”,其實就是把用戶請求的數據劃分為“動態數據”和“靜態數據”,動態數據還是靜態數據區分主要是:確認數據中是否含有和訪問者相關的個性化數據。

怎樣對靜態數據做緩存呢?

  1. 把靜態數據緩存到離用戶最近的地方。比如調用端,客戶端等等。
  2. 緩存靜態數據的方式也很重要。不同語言寫的 Cache 軟件處理緩存數據的效率也各不相同。以 Java 為例,因為 Java 系統本身也有其弱點(比如不擅長處理大量連接請求,每個連接消耗的內存較多,Servlet 容器解析 HTTP 協議較慢),所以你可以不在 Java 層做緩存,而是直接在 Web 服務器層上做,這樣你就可以屏蔽 Java 語言層面的一些弱點;而相比起來,Web 服務器(如 Nginx、Apache、Varnish)也更擅長處理大并發的靜態文件請求。

動態內容的處理通常有兩種方案:ESI(Edge Side Includes)方案和 CSI(Client Side Include)方案。

  1. ESI 方案(或者 SSI):即在 Web 代理服務器上做動態內容請求,并將請求插入到靜態頁面中,當用戶拿到頁面時已經是一個完整的頁面了。這種方式對服務端性能有些影響,但是用戶體驗較好。
  2. CSI 方案。即單獨發起一個異步 JavaScript 請求,向服務端獲取動態內容。這種方式服務端性能更佳,但是用戶端頁面可能會延時,體驗稍差。

針對性的處理系統“熱點數據”

熱點數據就是用戶的熱點請求對應的數據。而熱點數據又分為“靜態熱點數據”和“動態熱點數據”。“靜態熱點數據”,就是能夠提前預測的熱點數據;“動態熱點數據”,就是不能被提前預測到的,系統在運行過程中臨時產生的熱點。

由于熱點數據會引起大量的熱點操作,對系統產生很大的性能壓力,需要提前識別和處理。處理熱點數據通常有幾種思路:一是優化,二是限制,三是隔離。

  • 優化:優化熱點數據最有效的辦法就是緩存熱點數據,如果熱點數據做了動靜分離,那么可以長期緩存靜態數據。
  • 限制:限制更多的是一種保護機制,限制的辦法也有很多,例如對被訪問熱點數據的 ID 做一致性 Hash,然后根據 Hash 做分桶,每個分桶設置一個處理隊列,這樣可以把熱點限制在一個請求隊列里,防止因某些熱點占用太多的服務器資源,而使其他請求始終得不到服務器的處理資源。
  • 隔離:將這種熱點數據隔離出來,不要讓 1% 的請求影響到另外的 99%,隔離出來后也更方便對這 1% 的請求做針對性的優化。 業務隔離。把熱點做成一種營銷活動,請求方需要報名參加,從技術上來說,報名后對我們來說就有了已知熱點,因此可以提前做好預熱。 系統隔離。系統隔離更多的是運行時的隔離,可以通過分組部署的方式和另外 99% 分開。秒殺可以申請單獨的域名,目的也是讓請求落到不同的集群中。 數據隔離。秒殺所調用的數據大部分都是熱點數據,比如會啟用單獨的 Cache 集群或者 MySQL 數據庫來放熱點數據,目的也是不想 0.01% 的數據有機會影響 99.99% 數據。

流量削峰

我們知道服務器的處理資源是恒定的,你用或者不用它的處理能力都是一樣的,所以出現峰值的話,很容易導致忙到處理不過來,閑的時候卻又沒有什么要處理。但是由于要保證服務質量,我們的很多處理資源只能按照忙的時候來預估,而這會導致資源的一個浪費。

這就好比因為存在早高峰和晚高峰的問題,所以有了錯峰限行的解決方案。削峰的存在,一是可以讓服務端處理變得更加平穩,二是可以節省服務器的資源成本。針對熱點這一場景,削峰從本質上來說就是更多地延緩用戶請求的發出,以便減少和過濾掉一些無效請求,它遵從“請求數要盡量少”的原則。

流量削峰的一些操作思路:排隊、分層過濾。這幾種方式都是無損(即不會損失用戶的發出請求)的實現方案,當然還有些有損的實現方案,包括我們后面要介紹的關于穩定性的一些辦法,比如限流和機器負載保護等一些強制措施也能達到削峰保護的目的,當然這都是不得已的一些措施。

排隊

要對流量進行削峰,最容易想到的解決方案就是用消息隊列來緩沖瞬時流量,把同步的直接調用轉換成異步的間接推送,中間通過一個隊列在一端承接瞬時的流量洪峰,在另一端平滑地將消息推送出去。在這里,消息隊列就像“水庫”一樣,攔蓄上游的洪水,削減進入下游河道的洪峰流量,從而達到減免洪水災害的目的。

 

但是,如果流量峰值持續一段時間達到了消息隊列的處理上限,例如本機的消息積壓達到了存儲空間的上限,消息隊列同樣也會被壓垮,這樣雖然保護了下游的系統,但是和直接把請求丟棄也沒多大的區別。就像遇到洪水爆發時,即使是有水庫恐怕也無濟于事。

除了消息隊列,類似的排隊方式還有很多:

  • 利用線程池加鎖等待也是一種常用的排隊方式;
  • 先進先出、先進后出等常用的內存排隊算法的實現方式;
  • 把請求序列化到文件中,然后再順序地讀文件(例如基于 MySQL binlog 的同步機制)來恢復請求等方式。

這些方式都有一個共同特征,就是把“一步的操作”變成“兩步的操作”,其中增加的一步操作用來起到緩沖的作用。

分層過濾

對請求進行分層過濾,從而過濾掉一些無效的請求。分層過濾其實就是采用“漏斗”式設計來處理請求的,如下圖所示。

 

分層過濾的核心思想是:在不同的層次盡可能地過濾掉無效請求,讓“漏斗”最末端的才是有效請求。而要達到這種效果,我們就必須對數據做分層的校驗。

分層校驗的基本原則是:

  1. 將動態請求的讀數據緩存(Cache)在 Web 端,過濾掉無效的數據讀;
  2. 對讀數據不做強一致性校驗,減少因為一致性校驗產生瓶頸的問題;
  3. 對寫數據進行基于時間的合理分片,過濾掉過期的失效請求;
  4. 對寫請求做限流保護,將超出系統承載能力的請求過濾掉;
  5. 對寫數據進行強一致性校驗,只保留最后有效的數據。

如何提高系統的性能

對 Java 系統來說,可以優化的地方很多,這里我重點說一下比較有效的幾種手段,供你參考,它們是:減少編碼、減少序列化、Java 極致優化、并發讀優化。

  • 減少編碼:Java 的編碼運行比較慢,這是 Java 的一大硬傷。 在很多場景下,只要涉及字符串的操作(如輸入輸出操作、I/O 操作)都比較消耗 CPU 資源,不管它是磁盤 I/O 還是網絡 I/O,因為都需要將字符轉換成字節,而這個轉換必須編碼。那么如何才能減少編碼呢?例如,網頁輸出是可以直接進行流輸出的,即用 resp.getOutputStream() 函數寫數據,把一些靜態的數據提前轉化成字節,等到真正往外寫的時候再直接用 OutputStream() 函數寫,就可以減少靜態數據的編碼轉換。
  • 減少序列化:序列化也是 Java 性能的一大天敵,減少 Java 中的序列化操作也能大大提升性能。又因為序列化往往是和編碼同時發生的,所以減少序列化也就減少了編碼。 序列化大部分是在 RPC 中發生的,因此避免或者減少 RPC 就可以減少序列化,當然當前的序列化協議也已經做了很多優化來提升性能。有一種新的方案,就是可以將多個關聯性比較強的應用進行“合并部署”,而減少不同應用之間的 RPC 也可以減少序列化的消耗。
  • 并發讀優化:集中式緩存為了保證命中率一般都會采用一致性 Hash,所以同一個 key 會落到同一臺機器上。雖然單臺緩存機器也能支撐 30w/s 的請求,但還是遠不足以應對像“大秒”這種級別的熱點。采用應用層的 LocalCache,即在熱點系統的單機上緩存熱點相關的數據。

兜底方案

系統的高可用建設,它其實是一個系統工程,需要考慮到系統建設的各個階段,也就是說它其實貫穿了系統建設的整個生命周期。

 

在遇到大流量時,應該從哪些方面來保障系統的穩定運行,所以更多的是看如何針對運行階段進行處理,這就引出了接下來的內容:降級、限流和拒絕服務。

降級

所謂“降級”,就是當系統的容量達到一定程度時,限制或者關閉系統的某些非核心功能,從而把有限的資源保留給更核心的業務。

它是一個有目的、有計劃的執行過程,所以對降級我們一般需要有一套預案來配合執行。如果我們把它系統化,就可以通過預案系統和開關系統來實現降級。它分為兩部分,一部分是開關控制臺,它保存了開關的具體配置信息,以及具體執行開關所對應的機器列表;另一部分是執行下發開關數據的 Agent,主要任務就是保證開關被正確執行,即使系統重啟后也會生效。

 

執行降級無疑是在系統性能和用戶體驗之間選擇了前者,降級后肯定會影響一部分用戶的體驗。

限流

如果說降級是犧牲了一部分次要的功能和用戶的體驗效果,那么限流就是更極端的一種保護措施了。限流就是當系統容量達到瓶頸時,我們需要通過限制一部分流量來保護系統,并做到既可以人工執行開關,也支持自動化保護的措施。

總體來說,限流既可以是在客戶端限流,也可以是在服務端限流。此外,限流的實現方式既要支持 URL 以及方法級別的限流,也要支持基于 QPS 和線程的限流。

 

  • 客戶端限流,好處可以限制請求的發出,通過減少發出無用請求從而減少對系統的消耗。缺點就是當客戶端比較分散時,沒法設置合理的限流閾值:如果閾值設的太小,會導致服務端沒有達到瓶頸時客戶端已經被限制;而如果設的太大,則起不到限制的作用。
  • 服務端限流,好處是可以根據服務端的性能設置合理的閾值,而缺點就是被限制的請求都是無效的請求,處理這些無效的請求本身也會消耗服務器資源。

拒絕服務

如果限流還不能解決問題,最后一招就是直接拒絕服務了。

當系統負載達到一定閾值時,例如 CPU 使用率達到 90% 或者系統 load 值達到 2*CPU 核數時,系統直接拒絕所有請求,這種方式是最暴力但也最有效的系統保護方式。

拒絕服務可以說是一種不得已的兜底方案,用以防止最壞情況發生,防止因把服務器壓跨而長時間徹底無法提供服務。像這種系統過載保護雖然在過載時無法提供服務,但是系統仍然可以運作,當負載下降時又很容易恢復,所以每個系統和每個環節都應該設置這個兜底方案,對系統做最壞情況下的保護。

分享到:
標簽:并發
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定