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

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

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

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

  • 如何讓系統(tǒng)面對(duì)百萬(wàn)級(jí)的請(qǐng)求流量不出故障?
  • 如何保證高并發(fā)情況下數(shù)據(jù)的一致性寫?
  • 完全靠堆服務(wù)器來解決嗎?

基本原則

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

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

做好動(dòng)靜分離

所謂“動(dòng)靜分離”,其實(shí)就是把用戶請(qǐng)求的數(shù)據(jù)劃分為“動(dòng)態(tài)數(shù)據(jù)”和“靜態(tài)數(shù)據(jù)”,動(dòng)態(tài)數(shù)據(jù)還是靜態(tài)數(shù)據(jù)區(qū)分主要是:確認(rèn)數(shù)據(jù)中是否含有和訪問者相關(guān)的個(gè)性化數(shù)據(jù)。

怎樣對(duì)靜態(tài)數(shù)據(jù)做緩存呢?

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

動(dòng)態(tài)內(nèi)容的處理通常有兩種方案:ESI(Edge Side Includes)方案和 CSI(Client Side Include)方案。

  1. ESI 方案(或者 SSI):即在 Web 代理服務(wù)器上做動(dòng)態(tài)內(nèi)容請(qǐng)求,并將請(qǐng)求插入到靜態(tài)頁(yè)面中,當(dāng)用戶拿到頁(yè)面時(shí)已經(jīng)是一個(gè)完整的頁(yè)面了。這種方式對(duì)服務(wù)端性能有些影響,但是用戶體驗(yàn)較好。
  2. CSI 方案。即單獨(dú)發(fā)起一個(gè)異步 JavaScript 請(qǐng)求,向服務(wù)端獲取動(dòng)態(tài)內(nèi)容。這種方式服務(wù)端性能更佳,但是用戶端頁(yè)面可能會(huì)延時(shí),體驗(yàn)稍差。

針對(duì)性的處理系統(tǒng)“熱點(diǎn)數(shù)據(jù)”

熱點(diǎn)數(shù)據(jù)就是用戶的熱點(diǎn)請(qǐng)求對(duì)應(yīng)的數(shù)據(jù)。而熱點(diǎn)數(shù)據(jù)又分為“靜態(tài)熱點(diǎn)數(shù)據(jù)”和“動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)”。“靜態(tài)熱點(diǎn)數(shù)據(jù)”,就是能夠提前預(yù)測(cè)的熱點(diǎn)數(shù)據(jù);“動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)”,就是不能被提前預(yù)測(cè)到的,系統(tǒng)在運(yùn)行過程中臨時(shí)產(chǎn)生的熱點(diǎn)。

由于熱點(diǎn)數(shù)據(jù)會(huì)引起大量的熱點(diǎn)操作,對(duì)系統(tǒng)產(chǎn)生很大的性能壓力,需要提前識(shí)別和處理。處理熱點(diǎn)數(shù)據(jù)通常有幾種思路:一是優(yōu)化,二是限制,三是隔離。

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

流量削峰

我們知道服務(wù)器的處理資源是恒定的,你用或者不用它的處理能力都是一樣的,所以出現(xiàn)峰值的話,很容易導(dǎo)致忙到處理不過來,閑的時(shí)候卻又沒有什么要處理。但是由于要保證服務(wù)質(zhì)量,我們的很多處理資源只能按照忙的時(shí)候來預(yù)估,而這會(huì)導(dǎo)致資源的一個(gè)浪費(fèi)。

這就好比因?yàn)榇嬖谠绺叻搴屯砀叻宓膯栴},所以有了錯(cuò)峰限行的解決方案。削峰的存在,一是可以讓服務(wù)端處理變得更加平穩(wěn),二是可以節(jié)省服務(wù)器的資源成本。針對(duì)熱點(diǎn)這一場(chǎng)景,削峰從本質(zhì)上來說就是更多地延緩用戶請(qǐng)求的發(fā)出,以便減少和過濾掉一些無效請(qǐng)求,它遵從“請(qǐng)求數(shù)要盡量少”的原則。

流量削峰的一些操作思路:排隊(duì)、分層過濾。這幾種方式都是無損(即不會(huì)損失用戶的發(fā)出請(qǐng)求)的實(shí)現(xiàn)方案,當(dāng)然還有些有損的實(shí)現(xiàn)方案,包括我們后面要介紹的關(guān)于穩(wěn)定性的一些辦法,比如限流和機(jī)器負(fù)載保護(hù)等一些強(qiáng)制措施也能達(dá)到削峰保護(hù)的目的,當(dāng)然這都是不得已的一些措施。

排隊(duì)

要對(duì)流量進(jìn)行削峰,最容易想到的解決方案就是用消息隊(duì)列來緩沖瞬時(shí)流量,把同步的直接調(diào)用轉(zhuǎn)換成異步的間接推送,中間通過一個(gè)隊(duì)列在一端承接瞬時(shí)的流量洪峰,在另一端平滑地將消息推送出去。在這里,消息隊(duì)列就像“水庫(kù)”一樣,攔蓄上游的洪水,削減進(jìn)入下游河道的洪峰流量,從而達(dá)到減免洪水災(zāi)害的目的。

 

但是,如果流量峰值持續(xù)一段時(shí)間達(dá)到了消息隊(duì)列的處理上限,例如本機(jī)的消息積壓達(dá)到了存儲(chǔ)空間的上限,消息隊(duì)列同樣也會(huì)被壓垮,這樣雖然保護(hù)了下游的系統(tǒng),但是和直接把請(qǐng)求丟棄也沒多大的區(qū)別。就像遇到洪水爆發(fā)時(shí),即使是有水庫(kù)恐怕也無濟(jì)于事。

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

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

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

分層過濾

對(duì)請(qǐng)求進(jìn)行分層過濾,從而過濾掉一些無效的請(qǐng)求。分層過濾其實(shí)就是采用“漏斗”式設(shè)計(jì)來處理請(qǐng)求的,如下圖所示。

 

分層過濾的核心思想是:在不同的層次盡可能地過濾掉無效請(qǐng)求,讓“漏斗”最末端的才是有效請(qǐng)求。而要達(dá)到這種效果,我們就必須對(duì)數(shù)據(jù)做分層的校驗(yàn)。

分層校驗(yàn)的基本原則是:

  1. 將動(dòng)態(tài)請(qǐng)求的讀數(shù)據(jù)緩存(Cache)在 Web 端,過濾掉無效的數(shù)據(jù)讀;
  2. 對(duì)讀數(shù)據(jù)不做強(qiáng)一致性校驗(yàn),減少因?yàn)橐恢滦孕r?yàn)產(chǎn)生瓶頸的問題;
  3. 對(duì)寫數(shù)據(jù)進(jìn)行基于時(shí)間的合理分片,過濾掉過期的失效請(qǐng)求;
  4. 對(duì)寫請(qǐng)求做限流保護(hù),將超出系統(tǒng)承載能力的請(qǐng)求過濾掉;
  5. 對(duì)寫數(shù)據(jù)進(jìn)行強(qiáng)一致性校驗(yàn),只保留最后有效的數(shù)據(jù)。

如何提高系統(tǒng)的性能

對(duì) Java 系統(tǒng)來說,可以優(yōu)化的地方很多,這里我重點(diǎn)說一下比較有效的幾種手段,供你參考,它們是:減少編碼、減少序列化、Java 極致優(yōu)化、并發(fā)讀優(yōu)化。

  • 減少編碼:Java 的編碼運(yùn)行比較慢,這是 Java 的一大硬傷。 在很多場(chǎng)景下,只要涉及字符串的操作(如輸入輸出操作、I/O 操作)都比較消耗 CPU 資源,不管它是磁盤 I/O 還是網(wǎng)絡(luò) I/O,因?yàn)槎夹枰獙⒆址D(zhuǎn)換成字節(jié),而這個(gè)轉(zhuǎn)換必須編碼。那么如何才能減少編碼呢?例如,網(wǎng)頁(yè)輸出是可以直接進(jìn)行流輸出的,即用 resp.getOutputStream() 函數(shù)寫數(shù)據(jù),把一些靜態(tài)的數(shù)據(jù)提前轉(zhuǎn)化成字節(jié),等到真正往外寫的時(shí)候再直接用 OutputStream() 函數(shù)寫,就可以減少靜態(tài)數(shù)據(jù)的編碼轉(zhuǎn)換。
  • 減少序列化:序列化也是 Java 性能的一大天敵,減少 Java 中的序列化操作也能大大提升性能。又因?yàn)樾蛄谢呛途幋a同時(shí)發(fā)生的,所以減少序列化也就減少了編碼。 序列化大部分是在 RPC 中發(fā)生的,因此避免或者減少 RPC 就可以減少序列化,當(dāng)然當(dāng)前的序列化協(xié)議也已經(jīng)做了很多優(yōu)化來提升性能。有一種新的方案,就是可以將多個(gè)關(guān)聯(lián)性比較強(qiáng)的應(yīng)用進(jìn)行“合并部署”,而減少不同應(yīng)用之間的 RPC 也可以減少序列化的消耗。
  • 并發(fā)讀優(yōu)化:集中式緩存為了保證命中率一般都會(huì)采用一致性 Hash,所以同一個(gè) key 會(huì)落到同一臺(tái)機(jī)器上。雖然單臺(tái)緩存機(jī)器也能支撐 30w/s 的請(qǐng)求,但還是遠(yuǎn)不足以應(yīng)對(duì)像“大秒”這種級(jí)別的熱點(diǎn)。采用應(yīng)用層的 LocalCache,即在熱點(diǎn)系統(tǒng)的單機(jī)上緩存熱點(diǎn)相關(guān)的數(shù)據(jù)。

兜底方案

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

 

在遇到大流量時(shí),應(yīng)該從哪些方面來保障系統(tǒng)的穩(wěn)定運(yùn)行,所以更多的是看如何針對(duì)運(yùn)行階段進(jìn)行處理,這就引出了接下來的內(nèi)容:降級(jí)、限流和拒絕服務(wù)。

降級(jí)

所謂“降級(jí)”,就是當(dāng)系統(tǒng)的容量達(dá)到一定程度時(shí),限制或者關(guān)閉系統(tǒng)的某些非核心功能,從而把有限的資源保留給更核心的業(yè)務(wù)。

它是一個(gè)有目的、有計(jì)劃的執(zhí)行過程,所以對(duì)降級(jí)我們一般需要有一套預(yù)案來配合執(zhí)行。如果我們把它系統(tǒng)化,就可以通過預(yù)案系統(tǒng)和開關(guān)系統(tǒng)來實(shí)現(xiàn)降級(jí)。它分為兩部分,一部分是開關(guān)控制臺(tái),它保存了開關(guān)的具體配置信息,以及具體執(zhí)行開關(guān)所對(duì)應(yīng)的機(jī)器列表;另一部分是執(zhí)行下發(fā)開關(guān)數(shù)據(jù)的 Agent,主要任務(wù)就是保證開關(guān)被正確執(zhí)行,即使系統(tǒng)重啟后也會(huì)生效。

 

執(zhí)行降級(jí)無疑是在系統(tǒng)性能和用戶體驗(yàn)之間選擇了前者,降級(jí)后肯定會(huì)影響一部分用戶的體驗(yàn)。

限流

如果說降級(jí)是犧牲了一部分次要的功能和用戶的體驗(yàn)效果,那么限流就是更極端的一種保護(hù)措施了。限流就是當(dāng)系統(tǒng)容量達(dá)到瓶頸時(shí),我們需要通過限制一部分流量來保護(hù)系統(tǒng),并做到既可以人工執(zhí)行開關(guān),也支持自動(dòng)化保護(hù)的措施。

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

 

  • 客戶端限流,好處可以限制請(qǐng)求的發(fā)出,通過減少發(fā)出無用請(qǐng)求從而減少對(duì)系統(tǒng)的消耗。缺點(diǎn)就是當(dāng)客戶端比較分散時(shí),沒法設(shè)置合理的限流閾值:如果閾值設(shè)的太小,會(huì)導(dǎo)致服務(wù)端沒有達(dá)到瓶頸時(shí)客戶端已經(jīng)被限制;而如果設(shè)的太大,則起不到限制的作用。
  • 服務(wù)端限流,好處是可以根據(jù)服務(wù)端的性能設(shè)置合理的閾值,而缺點(diǎn)就是被限制的請(qǐng)求都是無效的請(qǐng)求,處理這些無效的請(qǐng)求本身也會(huì)消耗服務(wù)器資源。

拒絕服務(wù)

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

當(dāng)系統(tǒng)負(fù)載達(dá)到一定閾值時(shí),例如 CPU 使用率達(dá)到 90% 或者系統(tǒng) load 值達(dá)到 2*CPU 核數(shù)時(shí),系統(tǒng)直接拒絕所有請(qǐng)求,這種方式是最暴力但也最有效的系統(tǒng)保護(hù)方式。

拒絕服務(wù)可以說是一種不得已的兜底方案,用以防止最壞情況發(fā)生,防止因把服務(wù)器壓跨而長(zhǎng)時(shí)間徹底無法提供服務(wù)。像這種系統(tǒng)過載保護(hù)雖然在過載時(shí)無法提供服務(wù),但是系統(tǒng)仍然可以運(yùn)作,當(dāng)負(fù)載下降時(shí)又很容易恢復(fù),所以每個(gè)系統(tǒng)和每個(gè)環(huán)節(jié)都應(yīng)該設(shè)置這個(gè)兜底方案,對(duì)系統(tǒng)做最壞情況下的保護(hù)。

分享到:
標(biāo)簽:并發(fā)
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定