版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
億級(無限級)并發(fā),沒那么難多大并發(fā)是高并發(fā)一、什么是高并發(fā)定義:
高并發(fā)(HighConcurrency)是使用技術(shù)手段使系統(tǒng)可以并行處理很多請求。
關(guān)鍵指標(biāo):-響應(yīng)時間(ResponseTime)-吞吐量(Throughput)-每秒查詢率QPS(QueryPerSecond)-每秒事務(wù)處理量TPS(TransactionPerSecond)-同時在線用戶數(shù)量
關(guān)鍵指標(biāo)的維度:-平均,如:小時平均、日平均、月平均-Top百分?jǐn)?shù)TP(TopPercentile),如:TP50、TP90、TP99、TP4個9-最大值-趨勢
「并發(fā)」由于在互聯(lián)網(wǎng)架構(gòu)中,已經(jīng)從機(jī)器維度上升到了系統(tǒng)架構(gòu)層面,所以和「并行」已經(jīng)沒有清晰的界限。「并」(同時)是其中的關(guān)鍵。由于「同時」會引發(fā)多久才叫同時的問題,將時間擴(kuò)大,又根據(jù)不同業(yè)務(wù)關(guān)注點不同,引申出了引申指標(biāo)。引申指標(biāo):-活躍用戶數(shù),如:日活DAU(DailyActiveUser)、月活MAU(MonthlyActiveUsers)-點擊量PV(PageView)-訪問某站點的用戶數(shù)UV(UniqueVisitor)-獨(dú)立IP數(shù)IP(InternetProtocol)-日單量
二、多大算高并發(fā)
這個問題的答案不是一個數(shù)字。來看兩個場景:場景1:
木頭同學(xué)去一家創(chuàng)業(yè)公司面試。這個公司做的產(chǎn)品還沒有上線,面試官小熊之前就職過公司的產(chǎn)品都沒有什么量。小熊:“有高并發(fā)經(jīng)驗嗎?”木頭:“我們服務(wù)單機(jī)QPS2000+,線上有4臺機(jī)器負(fù)載均衡?!边@時候小熊心里的表情大概是:
但是如果小熊就職的公司是美團(tuán)之類的。那這這時候小熊心里的表情大概是:
場景2:固態(tài)硬盤SSD(SolidStateDisk)說:我讀取和寫入高達(dá)1000MB/秒mysql說:我單機(jī)TPS10000+nginx說:我單機(jī)QPS10W+靜兒說:給我一臺56核200G高配物理機(jī),我可以創(chuàng)建一個單機(jī)QPS1000W
不在同一維度,沒有任何前提,無法比較誰更牛?!拔业南到y(tǒng)算不算高并發(fā)?”這個問題就如同一個女孩子愛問的問題:“我美不美?”
三、高并發(fā)是解決問題的方式
俗話說:「沒有對比就沒有傷害」。算不算高并發(fā),這個問題的答案需要加對比和前提。
對比包括:-業(yè)界:在業(yè)界同類產(chǎn)品中并發(fā)量處于什么位置。舉個栗子??,美團(tuán)外賣的日單量是千萬級別,一個系統(tǒng)日單量在百萬,雖然差一個數(shù)量級,但是相比大多數(shù)公司已經(jīng)很不錯。-自身:在自身系統(tǒng)中,并發(fā)問題是否已經(jīng)是系統(tǒng)的瓶頸?如果是,這么這個瓶頸怎么打破?如果不是,那當(dāng)初架構(gòu)設(shè)計的時候是怎么保證并發(fā)不是問題的?(別告訴我:是通過系統(tǒng)沒有訪問量來保證的[擦汗])。
前提包括:-業(yè)務(wù)復(fù)雜度:舉個栗子??,訪問百度首頁的時間基本就是看自己家的網(wǎng)速,通常情況下都是點一下就看到結(jié)果了。而掃描二維碼支付,通常需要等很久,雖然這可能已經(jīng)是業(yè)界最牛的支付公司出品了。-配置:用高配物理機(jī)得出的數(shù)據(jù)和最老最低配的虛擬器上的出來的結(jié)果是無法比較的。通常的配置有:cpu、內(nèi)存、磁盤、帶寬、網(wǎng)卡
高并發(fā)的本質(zhì)不是「多大算高并發(fā)」的一個數(shù)字,而是從架構(gòu)上、設(shè)計上、編碼上怎么來保證或者解決由并發(fā)引起的問題。當(dāng)別人問你:“做過高并發(fā)嗎?”回答者完全可以描述自己系統(tǒng)的各項指標(biāo),然后開始敘述自己對系統(tǒng)中對預(yù)防、解決并發(fā)問題作出的思考和行動。這里就有一個非常重要的概念要講一下了,經(jīng)常面試官問,你們系統(tǒng)是多大并發(fā),我說單臺2000,面試官就會問2000QPS,還是PV秒懂QPS、TPS、PV、UV、IPQPS、TPS、PV、UV、GMV、IP、RPS等各種名詞,外行看起來很牛X,實際上每個程序員都是必懂知識點。下面我來一一解釋一下。QPSQueriesPerSecond,每秒查詢數(shù)。每秒能夠響應(yīng)的查詢次數(shù)。QPS是對一個特定的查詢服務(wù)器在規(guī)定時間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn),在因特網(wǎng)上,作為域名系統(tǒng)服務(wù)器的機(jī)器的性能經(jīng)常用每秒查詢率來衡量。每秒的響應(yīng)請求數(shù),也即是最大吞吐能力。TPSTransactionsPerSecond的縮寫,每秒處理的事務(wù)數(shù)目。一個事務(wù)是指一個客戶機(jī)向服務(wù)器發(fā)送請求然后服務(wù)器做出反應(yīng)的過程。客戶機(jī)在發(fā)送請求時開始計時,收到服務(wù)器響應(yīng)后結(jié)束計時,以此來計算使用的時間和完成的事務(wù)個數(shù),最終利用這些信息作出的評估分。TPS的過程包括:客戶端請求服務(wù)端、服務(wù)端內(nèi)部處理、服務(wù)端返回客戶端。例如,訪問一個Index頁面會請求服務(wù)器3次,包括一次html,一次css,一次js,那么訪問這一個頁面就會產(chǎn)生一個“T”,產(chǎn)生三個“Q”。PVPV(pageview)即頁面瀏覽量,通常是衡量一個網(wǎng)絡(luò)新聞頻道或網(wǎng)站甚至一條網(wǎng)絡(luò)新聞的主要指標(biāo)。PV
即pageview,頁面瀏覽量。用戶每一次對網(wǎng)站中的每個頁面訪問均被記錄1次。用戶對同一頁面的多次刷新,訪問量累計。根據(jù)這個特性,刷網(wǎng)站的PV就很好刷了。與PV相關(guān)的還有
RV,即重復(fù)訪問者數(shù)量(repeatvisitors)。UVUV
訪問數(shù)(UniqueVisitor)指獨(dú)立訪客訪問數(shù),統(tǒng)計1天內(nèi)訪問某站點的用戶數(shù)(以cookie為依據(jù)),一臺電腦終端為一個訪客。IPIP(InternetProtocol)獨(dú)立IP數(shù),是指1天內(nèi)多少個獨(dú)立的IP瀏覽了頁面,即統(tǒng)計不同的IP瀏覽用戶數(shù)量。同一IP不管訪問了幾個頁面,獨(dú)立IP數(shù)均為1;不同的IP瀏覽頁面,計數(shù)會加1。IP是基于用戶廣域網(wǎng)IP地址來區(qū)分不同的訪問者的,所以,多個用戶(多個局域網(wǎng)IP)在同一個路由器(同一個廣域網(wǎng)IP)內(nèi)上網(wǎng),可能被記錄為一個獨(dú)立IP訪問者。如果用戶不斷更換IP,則有可能被多次統(tǒng)計。GMVGMV,是GrossMerchandiseVolume的簡稱。只要是訂單,不管消費(fèi)者是否付款、賣家是否發(fā)貨、是否退貨,都可放進(jìn)GMV。RPSRPS
代表吞吐率,即RequestsPerSecond的縮寫。吞吐率是服務(wù)器并發(fā)處理能力的量化描述,單位是reqs/s,指的是某個并發(fā)用戶數(shù)下單位時間內(nèi)處理的請求數(shù)。
某個并發(fā)用戶數(shù)下單位時間內(nèi)能處理的最大的請求數(shù),稱之為最大吞吐率。有人把RPS說等效于QPS。其實可以看作同一個統(tǒng)計方式,只是叫法不同而已。RPS/QPS,可以使用apcheab工具進(jìn)行測量。承載高并發(fā)系統(tǒng)的本質(zhì)小編剛上班的時候聽到高并發(fā)也是熱血沸騰,呼啦啦的看各個廠的架構(gòu),恨不得一下吃完,后面越看越多,發(fā)現(xiàn)怎么各家都一樣的?;ヂ?lián)網(wǎng)架構(gòu)的三架馬車屢試不爽,提供了非常強(qiáng)大簡易的標(biāo)準(zhǔn)化解決方案:微服務(wù)、消息隊列、定時任務(wù)那么高并發(fā)系統(tǒng)的本質(zhì)是什么呢,第一個:這么多請求來了,要在你機(jī)器里跑,是不是需要網(wǎng)絡(luò)流量,網(wǎng)絡(luò)流量太大是不是把你的程序都卡了?那么就出現(xiàn)了把占流量的圖片資源靜態(tài)資源分析,再CDN一下,你的代碼可以更安心的跑了;第二個就是:這么多請求來了,每個來的請求都是帶著一堆數(shù)據(jù)過來的,第一層要對數(shù)據(jù)做處理,處理完又要存儲,最后的處理都是把數(shù)據(jù)放到內(nèi)存里,內(nèi)存遞給cpu來處理,而內(nèi)存數(shù)據(jù)有時又需要從硬盤拿,這就變成了內(nèi)存,硬盤,cpu這三者之間的關(guān)系了,我們來看看這幾者之間的關(guān)系計算機(jī)為什么要并發(fā)?
為什么要并發(fā)?因為人類的貪婪!因為人類想要向計算機(jī)索取更多!人類想要一步,進(jìn)一步的壓榨計算機(jī)。所以,為了更高效的利用計算機(jī)的計算能力,人類想出來了讓計算機(jī)并發(fā)執(zhí)行多個任務(wù)的辦法!
高速處理器與低速存儲之間的矛盾
我們都知道,計算機(jī)中的處理器決定了計算機(jī)的處理速度,現(xiàn)代處理器的計算速度是驚人的。但是,處理器并不能自己單獨(dú)工作,至少在進(jìn)行運(yùn)算時需要與進(jìn)行內(nèi)存交互,讀取數(shù)據(jù),或是寫入數(shù)據(jù)。內(nèi)存這種存儲設(shè)備的速度是沒有辦法和處理器相比的,這就造成了造成了處理器計算能力的浪費(fèi)。這種矛盾就猶如人民日益增長的美好生活需要和不平衡不充分的發(fā)展之間的矛盾一樣,需要聰明的程序員去解決!
調(diào)和處理器與內(nèi)存的矛盾
聰明的人類想到一個辦法,他們在處理器與內(nèi)存中間,增加一層高速緩存,這層緩存作為處理器與內(nèi)存之間的緩沖區(qū)。將需要處理的數(shù)據(jù)放入高速緩存,處理結(jié)束后再重新放入到內(nèi)存中,這樣就處理器就不需要無盡的等待與內(nèi)存之間的交互。這樣一波操作看似十分的完美!但是,請往下看!
高速緩存帶來的并發(fā)問題
高速緩存看似完美的解決了高速的處理器與低速緩存之間的矛盾。但是,問題確被復(fù)雜化了。在多處理器的系統(tǒng)中,每個處理器都會有自己的高速緩存,數(shù)據(jù)都會被復(fù)制到高速緩存中處理,處理后再放回主內(nèi)存。由于主內(nèi)存是共享的,如果不同處理器高速緩存中的數(shù)據(jù)不同,這樣就會造成緩存不一致的問題!
解決并發(fā)問題高速緩存并發(fā)問題
高速緩存的數(shù)據(jù)不一致,這種現(xiàn)象就像鄰居家的小孩子吵架,吵到最后就需要家長出面,把矛盾化解掉。對于計算機(jī)來說,這個家長就是緩存一致性協(xié)議,在讀寫操作時按照協(xié)議來操作,避免并發(fā)問題。這樣,就完美的解決了所有的問題!處理器、高速緩存、緩存一致性協(xié)議、主內(nèi)存計算機(jī)高效并發(fā)的其他操作
除了高效緩存機(jī)制外,還有一些其他的操作也可以提高效率。例如,與Java的指令重排序一樣,處理器也會根據(jù)執(zhí)行效率,將代碼進(jìn)行重新排序進(jìn)行執(zhí)行。有同學(xué)可能是我有多線程,我有緩存,我還有神器redis,那才是高并發(fā),沒錯,盡可能高的提高cpu的利用率,把數(shù)據(jù)都放在內(nèi)存里進(jìn)行,最靠近cpu的地方,所以我們的所有的互聯(lián)網(wǎng)高并發(fā)架構(gòu)無非都是把數(shù)據(jù)更可能的不從磁盤里讀取和運(yùn)算,更多的放入內(nèi)存,同時通過多線程等方式提高cpu的利用率,哈哈,就是監(jiān)控你cpu有沒有偷懶的時候,壓榨cpu呀;cpu內(nèi)存總有忙不過來的時候,這個時候怎么辦呢,就是等你不忙的時候來個定時任務(wù)或者跑到另外一臺機(jī)器的隊列來執(zhí)行。實在單機(jī)扛不過來的時候,就喊人來幫忙,于是有了集群;有的單元模塊嫌棄另外的單元模塊影響我運(yùn)行,于是有了微服務(wù)。于是我們看到了大多數(shù)互聯(lián)網(wǎng)架構(gòu)都是往內(nèi)存里塞數(shù)據(jù),親切的稱之為緩存,通過優(yōu)化算法減少程序的執(zhí)行時間,實在不行來個磁盤順序?qū)?,如kfaka和mysql的redolog,每次都寫數(shù)據(jù)都嫌累,就有了redispipeline,mysqlredolog組提交這樣的操作在高并發(fā)場景下,有時又需要讀的同時又在寫,怎么避免讀取到臟數(shù)據(jù)呢,這是大多數(shù)中間件要考慮的事情,而大多數(shù)中間件其實是C語言寫的,在這種情況下C一般會干什么事呢,修改數(shù)據(jù)的時原內(nèi)存塊我不動你,我新在已經(jīng)分配好的內(nèi)存塊里找一個地方去修改數(shù)據(jù),修改完了,再重新拷貝過去另外一塊就是網(wǎng)絡(luò)請求的處理方式,epoll,poll,select,java的nio了,
由于這塊相對比較比較重要,稍微展開一下:用戶空間以及內(nèi)核空間概念我們知道現(xiàn)在操作系統(tǒng)都是采用虛擬存儲器,那么對32位操作系統(tǒng)而言,它的尋址空間(虛擬存儲空間)為4G(2的32次方)。操心系統(tǒng)的核心是內(nèi)核,獨(dú)立于普通的應(yīng)用程序,可以訪問受保護(hù)的內(nèi)存空間,也有訪問底層硬件設(shè)備的所有權(quán)限。為了保證用戶進(jìn)程不能直接操作內(nèi)核,保證內(nèi)核的安全,操心系統(tǒng)將虛擬空間劃分為兩部分,一部分為內(nèi)核空間,一部分為用戶空間。針對linux操作系統(tǒng)而言,將最高的1G字節(jié)(從虛擬地址0xC0000000到0xFFFFFFFF),供內(nèi)核使用,稱為內(nèi)核空間,而將較低的3G字節(jié)(從虛擬地址0x00000000到0xBFFFFFFF),供各個進(jìn)程使用,稱為用戶空間。每個進(jìn)程可以通過系統(tǒng)調(diào)用進(jìn)入內(nèi)核,因此,Linux內(nèi)核由系統(tǒng)內(nèi)的所有進(jìn)程共享。于是,從具體進(jìn)程的角度來看,每個進(jìn)程可以擁有4G字節(jié)的虛擬空間??臻g分配如下圖所示:有了用戶空間和內(nèi)核空間,整個linux內(nèi)部結(jié)構(gòu)可以分為三部分,從最底層到最上層依次是:硬件-->內(nèi)核空間-->用戶空間。如下圖所示:需要注意的細(xì)節(jié)問題,從上圖可以看出內(nèi)核的組成:內(nèi)核空間中存放的是內(nèi)核代碼和數(shù)據(jù),而進(jìn)程的用戶空間中存放的是用戶程序的代碼和數(shù)據(jù)。不管是內(nèi)核空間還是用戶空間,它們都處于虛擬空間中。Linux使用兩級保護(hù)機(jī)制:0級供內(nèi)核使用,3級供用戶程序使用。Linux網(wǎng)絡(luò)I/O模型我們都知道,為了OS的安全性等的考慮,進(jìn)程是無法直接操作I/O設(shè)備的,其必須通過系統(tǒng)調(diào)用請求內(nèi)核來協(xié)助完成I/O動作,而內(nèi)核會為每個I/O設(shè)備維護(hù)一個buffer。如下圖所示:整個請求過程為:用戶進(jìn)程發(fā)起請求,內(nèi)核接受到請求后,從I/O設(shè)備中獲取數(shù)據(jù)到buffer中,再將buffer中的數(shù)據(jù)copy到用戶進(jìn)程的地址空間,該用戶進(jìn)程獲取到數(shù)據(jù)后再響應(yīng)客戶端。在整個請求過程中,數(shù)據(jù)輸入至buffer需要時間,而從buffer復(fù)制數(shù)據(jù)至進(jìn)程也需要時間。因此根據(jù)在這兩段時間內(nèi)等待方式的不同,I/O動作可以分為以下五種模式:阻塞I/O(BlockingI/O)非阻塞I/O(Non-BlockingI/O)I/O復(fù)用(I/OMultiplexing)信號驅(qū)動的I/O(SignalDrivenI/O)異步I/O(AsynchrnousI/O)
說明:如果像了解更多可能需要linux/unix方面的知識了,可自行去學(xué)習(xí)一些網(wǎng)絡(luò)編程原理應(yīng)該有詳細(xì)說明,不過對大多數(shù)java程序員來說,不需要了解底層細(xì)節(jié),知道個概念就行,知道對于系統(tǒng)而言,底層是支持的。本文最重要的參考文獻(xiàn)是RichardStevens的“UNIX?NetworkProgrammingVolume1,ThirdEdition:TheSocketsNetworking”,6.2節(jié)“I/OModels”,公眾號【肉眼品世界】回復(fù):linuxsocket或者linux001
,獲取該資料,建議電腦下載(比較大以及chm格式),本文中的流程圖也是截取自中。記住這兩點很重要1等待數(shù)據(jù)準(zhǔn)備(Waitingforthedatatobeready)2將數(shù)據(jù)從內(nèi)核拷貝到進(jìn)程中(Copyingthedatafromthekerneltotheprocess)阻塞I/O(BlockingI/O)在linux中,默認(rèn)情況下所有的socket都是blocking,一個典型的讀操作流程大概是這樣:當(dāng)用戶進(jìn)程調(diào)用了recvfrom這個系統(tǒng)調(diào)用,內(nèi)核就開始了IO的第一個階段:等待數(shù)據(jù)準(zhǔn)備。對于networkio來說,很多時候數(shù)據(jù)在一開始還沒有到達(dá)(比如,還沒有收到一個完整的UDP包),這個時候內(nèi)核就要等待足夠的數(shù)據(jù)到來。而在用戶進(jìn)程這邊,整個進(jìn)程會被阻塞。當(dāng)內(nèi)核一直等到數(shù)據(jù)準(zhǔn)備好了,它就會將數(shù)據(jù)從內(nèi)核中拷貝到用戶內(nèi)存,然后內(nèi)核返回結(jié)果,用戶進(jìn)程才解除block的狀態(tài),重新運(yùn)行起來。所以,blockingIO的特點就是在IO執(zhí)行的兩個階段都被block了。非阻塞I/O(Non-BlockingI/O)linux下,可以通過設(shè)置socket使其變?yōu)閚on-blocking。當(dāng)對一個non-blockingsocket執(zhí)行讀操作時,流程是這個樣子:當(dāng)用戶進(jìn)程調(diào)用recvfrom時,系統(tǒng)不會阻塞用戶進(jìn)程,而是立刻返回一個ewouldblock錯誤,從用戶進(jìn)程角度講,并不需要等待,而是馬上就得到了一個結(jié)果。用戶進(jìn)程判斷標(biāo)志是ewouldblock時,就知道數(shù)據(jù)還沒準(zhǔn)備好,于是它就可以去做其他的事了,于是它可以再次發(fā)送recvfrom,一旦內(nèi)核中的數(shù)據(jù)準(zhǔn)備好了。并且又再次收到了用戶進(jìn)程的systemcall,那么它馬上就將數(shù)據(jù)拷貝到了用戶內(nèi)存,然后返回。當(dāng)一個應(yīng)用程序在一個循環(huán)里對一個非阻塞調(diào)用recvfrom,我們稱為輪詢。應(yīng)用程序不斷輪詢內(nèi)核,看看是否已經(jīng)準(zhǔn)備好了某些操作。這通常是浪費(fèi)CPU時間,但這種模式偶爾會遇到。I/O復(fù)用(I/OMultiplexing)IOmultiplexing這個詞可能有點陌生,但是如果我說select,epoll,大概就都能明白了。有些地方也稱這種IO方式為eventdrivenIO。我們都知道,select/epoll的好處就在于單個process就可以同時處理多個網(wǎng)絡(luò)連接的IO。它的基本原理就是select/epoll這個function會不斷的輪詢所負(fù)責(zé)的所有socket,當(dāng)某個socket有數(shù)據(jù)到達(dá)了,就通知用戶進(jìn)程。它的流程如圖:當(dāng)用戶進(jìn)程調(diào)用了select,那么整個進(jìn)程會被block,而同時,內(nèi)核會“監(jiān)視”所有select負(fù)責(zé)的socket,當(dāng)任何一個socket中的數(shù)據(jù)準(zhǔn)備好了,select就會返回。這個時候用戶進(jìn)程再調(diào)用read操作,將數(shù)據(jù)從內(nèi)核拷貝到用戶進(jìn)程。這個圖和blockingIO的圖其實并沒有太大的不同,事實上,還更差一些。因為這里需要使用兩個systemcall(select和recvfrom),而blockingIO只調(diào)用了一個systemcall(recvfrom)。但是,用select的優(yōu)勢在于它可以同時處理多個connection。(多說一句。所以,如果處理的連接數(shù)不是很高的話,使用select/epoll的webserver不一定比使用multi-threading+blockingIO的webserver性能更好,可能延遲還更大。select/epoll的優(yōu)勢并不是對于單個連接能處理得更快,而是在于能處理更多的連接。)在IOmultiplexingModel中,實際中,對于每一個socket,一般都設(shè)置成為non-blocking,但是,如上圖所示,整個用戶的process其實是一直被block的。只不過process是被select這個函數(shù)block,而不是被socketIO給block。文件描述符fdLinux的內(nèi)核將所有外部設(shè)備都可以看做一個文件來操作。那么我們對與外部設(shè)備的操作都可以看做對文件進(jìn)行操作。我們對一個文件的讀寫,都通過調(diào)用內(nèi)核提供的系統(tǒng)調(diào)用;內(nèi)核給我們返回一個filedescriptor(fd,文件描述符)。而對一個socket的讀寫也會有相應(yīng)的描述符,稱為socketfd(socket描述符)。描述符就是一個數(shù)字,指向內(nèi)核中一個結(jié)構(gòu)體(文件路徑,數(shù)據(jù)區(qū),等一些屬性)。那么我們的應(yīng)用程序?qū)ξ募淖x寫就通過對描述符的讀寫完成。select基本原理:select函數(shù)監(jiān)視的文件描述符分3類,分別是writefds、readfds、和exceptfds。調(diào)用后select函數(shù)會阻塞,直到有描述符就緒(有數(shù)據(jù)可讀、可寫、或者有except),或者超時(timeout指定等待時間,如果立即返回設(shè)為null即可),函數(shù)返回。當(dāng)select函數(shù)返回后,可以通過遍歷fdset,來找到就緒的描述符。缺點:1、select最大的缺陷就是單個進(jìn)程所打開的FD是有一定限制的,它由FDSETSIZE設(shè)置,32位機(jī)默認(rèn)是1024個,64位機(jī)默認(rèn)是2048。一般來說這個數(shù)目和系統(tǒng)內(nèi)存關(guān)系很大,”具體數(shù)目可以cat/proc/sys/fs/file-max察看”。32位機(jī)默認(rèn)是1024個。64位機(jī)默認(rèn)是2048.2、對socket進(jìn)行掃描時是線性掃描,即采用輪詢的方法,效率較低。當(dāng)套接字比較多的時候,每次select()都要通過遍歷FDSETSIZE個Socket來完成調(diào)度,不管哪個Socket是活躍的,都遍歷一遍。這會浪費(fèi)很多CPU時間?!比绻芙o套接字注冊某個回調(diào)函數(shù),當(dāng)他們活躍時,自動完成相關(guān)操作,那就避免了輪詢”,這正是epoll與kqueue做的。3、需要維護(hù)一個用來存放大量fd的數(shù)據(jù)結(jié)構(gòu),這樣會使得用戶空間和內(nèi)核空間在傳遞該結(jié)構(gòu)時復(fù)制開銷大。poll基本原理:poll本質(zhì)上和select沒有區(qū)別,它將用戶傳入的數(shù)組拷貝到內(nèi)核空間,然后查詢每個fd對應(yīng)的設(shè)備狀態(tài),如果設(shè)備就緒則在設(shè)備等待隊列中加入一項并繼續(xù)遍歷,如果遍歷完所有fd后沒有發(fā)現(xiàn)就緒設(shè)備,則掛起當(dāng)前進(jìn)程,直到設(shè)備就緒或者主動超時,被喚醒后它又要再次遍歷fd。這個過程經(jīng)歷了多次無謂的遍歷。它沒有最大連接數(shù)的限制,原因是它是基于鏈表來存儲的,但是同樣有一個缺點:1、大量的fd的數(shù)組被整體復(fù)制于用戶態(tài)和內(nèi)核地址空間之間,而不管這樣的復(fù)制是不是有意義。2、poll還有一個特點是“水平觸發(fā)”,如果報告了fd后,沒有被處理,那么下次poll時會再次報告該fd。注意:從上面看,select和poll都需要在返回后,通過遍歷文件描述符來獲取已經(jīng)就緒的socket。事實上,同時連接的大量客戶端在一時刻可能只有很少的處于就緒狀態(tài),因此隨著監(jiān)視的描述符數(shù)量的增長,其效率也會線性下降。epollepoll是在2.6內(nèi)核中提出的,是之前的select和poll的增強(qiáng)版本。相對于select和poll來說,epoll更加靈活,沒有描述符限制。epoll使用一個文件描述符管理多個描述符,將用戶關(guān)系的文件描述符的事件存放到內(nèi)核的一個事件表中,這樣在用戶空間和內(nèi)核空間的copy只需一次。基本原理:epoll支持水平觸發(fā)和邊緣觸發(fā),最大的特點在于邊緣觸發(fā),它只告訴進(jìn)程哪些fd剛剛變?yōu)榫途w態(tài),并且只會通知一次。還有一個特點是,epoll使用“事件”的就緒通知方式,通過epollctl注冊fd,一旦該fd就緒,內(nèi)核就會采用類似callback的回調(diào)機(jī)制來激活該fd,epollwait便可以收到通知。epoll的優(yōu)點:1、沒有最大并發(fā)連接的限制,能打開的FD的上限遠(yuǎn)大于1024(1G的內(nèi)存上能監(jiān)聽約10萬個端口)。2、效率提升,不是輪詢的方式,不會隨著FD數(shù)目的增加效率下降。只有活躍可用的FD才會調(diào)用callback函數(shù);即Epoll最大的優(yōu)點就在于它只管你“活躍”的連接,而跟連接總數(shù)無關(guān),因此在實際的網(wǎng)絡(luò)環(huán)境中,Epoll的效率就會遠(yuǎn)遠(yuǎn)高于select和poll。3、內(nèi)存拷貝,利用mmap()文件映射內(nèi)存加速與內(nèi)核空間的消息傳遞;即epoll使用mmap減少復(fù)制開銷。JDK1.5_update10版本使用epoll替代了傳統(tǒng)的select/poll,極大的提升了NIO通信的性能。備注:JDKNIO的BUG,例如臭名昭著的epollbug,它會導(dǎo)致Selector空輪詢,最終導(dǎo)致CPU100%。官方聲稱在JDK1.6版本的update18修復(fù)了該問題,但是直到JDK1.7版本該問題仍舊存在,只不過該BUG發(fā)生概率降低了一些而已,它并沒有被根本解決。這個可以在后續(xù)netty系列里面進(jìn)行說明下。信號驅(qū)動的I/O(SignalDrivenI/O)由于signaldrivenIO在實際中并不常用,所以簡單提下。很明顯可以看出用戶進(jìn)程不是阻塞的。首先用戶進(jìn)程建立SIGIO信號處理程序,并通過系統(tǒng)調(diào)用sigaction執(zhí)行一個信號處理函數(shù),這時用戶進(jìn)程便可以做其他的事了,一旦數(shù)據(jù)準(zhǔn)備好,系統(tǒng)便為該進(jìn)程生成一個SIGIO信號,去通知它數(shù)據(jù)已經(jīng)準(zhǔn)備好了,于是用戶進(jìn)程便調(diào)用recvfrom把數(shù)據(jù)從內(nèi)核拷貝出來,并返回結(jié)果。異步I/O一般來說,這些函數(shù)通過告訴內(nèi)核啟動操作并在整個操作(包括內(nèi)核的數(shù)據(jù)到緩沖區(qū)的副本)完成時通知我們。這個模型和前面的信號驅(qū)動I/O模型的主要區(qū)別是,在信號驅(qū)動的I/O中,內(nèi)核告訴我們何時可以啟動I/O操作,但是異步I/O時,內(nèi)核告訴我們何時I/O操作完成。當(dāng)用戶進(jìn)程向內(nèi)核發(fā)起某個操作后,會立刻得到返回,并把所有的任務(wù)都交給內(nèi)核去完成(包括將數(shù)據(jù)從內(nèi)核拷貝到用戶自己的緩沖區(qū)),內(nèi)核完成之后,只需返回一個信號告訴用戶進(jìn)程已經(jīng)完成就可以了。5中I/O模型的對比結(jié)果表明:前四個模型之間的主要區(qū)別是第一階段,四個模型的第二階段是一樣的:過程受阻在調(diào)用recvfrom當(dāng)數(shù)據(jù)從內(nèi)核拷貝到用戶緩沖區(qū)。然而,異步I/O處理兩個階段,與前四個不同。從同步、異步,以及阻塞、非阻塞兩個維度來劃分來看:零拷貝CPU不執(zhí)行拷貝數(shù)據(jù)從一個存儲區(qū)域到另一個存儲區(qū)域的任務(wù),這通常用于在網(wǎng)絡(luò)上傳輸文件時節(jié)省CPU周期和內(nèi)存帶寬。緩存IO緩存IO又被稱作標(biāo)準(zhǔn)IO,大多數(shù)文件系統(tǒng)的默認(rèn)IO操作都是緩存IO。在Linux的緩存IO機(jī)制中,操作系統(tǒng)會將IO的數(shù)據(jù)緩存在文件系統(tǒng)的頁緩存(pagecache)中,也就是說,數(shù)據(jù)會先被拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中,然后才會從操作系統(tǒng)內(nèi)核的緩沖區(qū)拷貝到應(yīng)用程序的地址空間。緩存IO的缺點:數(shù)據(jù)在傳輸過程中需要在應(yīng)用程序地址空間和內(nèi)核進(jìn)行多次數(shù)據(jù)拷貝操作,這些數(shù)據(jù)拷貝操作所帶來的CPU以及內(nèi)存開銷是非常大的。零拷貝技術(shù)分類零拷貝技術(shù)的發(fā)展很多樣化,現(xiàn)有的零拷貝技術(shù)種類也非常多,而當(dāng)前并沒有一個適合于所有場景的零拷貝技術(shù)的出現(xiàn)。對于Linux來說,現(xiàn)存的零拷貝技術(shù)也比較多,這些零拷貝技術(shù)大部分存在于不同的Linux內(nèi)核版本,有些舊的技術(shù)在不同的Linux內(nèi)核版本間得到了很大的發(fā)展或者已經(jīng)漸漸被新的技術(shù)所代替。本文針對這些零拷貝技術(shù)所適用的不同場景對它們進(jìn)行了劃分。概括起來,Linux中的零拷貝技術(shù)主要有下面這幾種:直接I/O:對于這種數(shù)據(jù)傳輸方式來說,應(yīng)用程序可以直接訪問硬件存儲,操作系統(tǒng)內(nèi)核只是輔助數(shù)據(jù)傳輸:這類零拷貝技術(shù)針對的是操作系統(tǒng)內(nèi)核并不需要對數(shù)據(jù)進(jìn)行直接處理的情況,數(shù)據(jù)可以在應(yīng)用程序地址空間的緩沖區(qū)和磁盤之間直接進(jìn)行傳輸,完全不需要Linux操作系統(tǒng)內(nèi)核提供的頁緩存的支持。在數(shù)據(jù)傳輸?shù)倪^程中,避免數(shù)據(jù)在操作系統(tǒng)內(nèi)核地址空間的緩沖區(qū)和用戶應(yīng)用程序地址空間的緩沖區(qū)之間進(jìn)行拷貝。有的時候,應(yīng)用程序在數(shù)據(jù)進(jìn)行傳輸?shù)倪^程中不需要對數(shù)據(jù)進(jìn)行訪問,那么,將數(shù)據(jù)從Linux的頁緩存拷貝到用戶進(jìn)程的緩沖區(qū)中就可以完全避免,傳輸?shù)臄?shù)據(jù)在頁緩存中就可以得到處理。在某些特殊的情況下,這種零拷貝技術(shù)可以獲得較好的性能。Linux中提供類似的系統(tǒng)調(diào)用主要有mmap(),sendfile()以及splice()。對數(shù)據(jù)在Linux的頁緩存和用戶進(jìn)程的緩沖區(qū)之間的傳輸過程進(jìn)行優(yōu)化。該零拷貝技術(shù)側(cè)重于靈活地處理數(shù)據(jù)在用戶進(jìn)程的緩沖區(qū)和操作系統(tǒng)的頁緩存之間的拷貝操作。這種方法延續(xù)了傳統(tǒng)的通信方式,但是更加靈活。在Linux中,該方法主要利用了寫時復(fù)制技術(shù)。前兩類方法的目的主要是為了避免應(yīng)用程序地址空間和操作系統(tǒng)內(nèi)核地址空間這兩者之間的緩沖區(qū)拷貝操作。這兩類零拷貝技術(shù)通常適用在某些特殊的情況下,比如要傳送的數(shù)據(jù)不需要經(jīng)過操作系統(tǒng)內(nèi)核的處理或者不需要經(jīng)過應(yīng)用程序的處理。第三類方法則繼承了傳統(tǒng)的應(yīng)用程序地址空間和操作系統(tǒng)內(nèi)核地址空間之間數(shù)據(jù)傳輸?shù)母拍?,進(jìn)而針對數(shù)據(jù)傳輸本身進(jìn)行優(yōu)化。我們知道,硬件和軟件之間的數(shù)據(jù)傳輸可以通過使用DMA來進(jìn)行,DMA進(jìn)行數(shù)據(jù)傳輸?shù)倪^程中幾乎不需要CPU參與,這樣就可以把CPU解放出來去做更多其他的事情,但是當(dāng)數(shù)據(jù)需要在用戶地址空間的緩沖區(qū)和Linux操作系統(tǒng)內(nèi)核的頁緩存之間進(jìn)行傳輸?shù)臅r候,并沒有類似DMA這種工具可以使用,CPU需要全程參與到這種數(shù)據(jù)拷貝操作中,所以這第三類方法的目的是可以有效地改善數(shù)據(jù)在用戶地址空間和操作系統(tǒng)內(nèi)核地址空間之間傳遞的效率。注意,對于各種零拷貝機(jī)制是否能夠?qū)崿F(xiàn)都是依賴于操作系統(tǒng)底層是否提供相應(yīng)的支持。當(dāng)應(yīng)用程序訪問某塊數(shù)據(jù)時,操作系統(tǒng)首先會檢查,是不是最近訪問過此文件,文件內(nèi)容是否緩存在內(nèi)核緩沖區(qū),如果是,操作系統(tǒng)則直接根據(jù)read系統(tǒng)調(diào)用提供的buf地址,將內(nèi)核緩沖區(qū)的內(nèi)容拷貝到buf所指定的用戶空間緩沖區(qū)中去。如果不是,操作系統(tǒng)則首先將磁盤上的數(shù)據(jù)拷貝的內(nèi)核緩沖區(qū),這一步目前主要依靠DMA來傳輸,然后再把內(nèi)核緩沖區(qū)上的內(nèi)容拷貝到用戶緩沖區(qū)中。接下來,write系統(tǒng)調(diào)用再把用戶緩沖區(qū)的內(nèi)容拷貝到網(wǎng)絡(luò)堆棧相關(guān)的內(nèi)核緩沖區(qū)中,最后socket再把內(nèi)核緩沖區(qū)的內(nèi)容發(fā)送到網(wǎng)卡上。從上圖中可以看出,共產(chǎn)生了四次數(shù)據(jù)拷貝,即使使用了DMA來處理了與硬件的通訊,CPU仍然需要處理兩次數(shù)據(jù)拷貝,與此同時,在用戶態(tài)與內(nèi)核態(tài)也發(fā)生了多次上下文切換,無疑也加重了CPU負(fù)擔(dān)。在此過程中,我們沒有對文件內(nèi)容做任何修改,那么在內(nèi)核空間和用戶空間來回拷貝數(shù)據(jù)無疑就是一種浪費(fèi),而零拷貝主要就是為了解決這種低效性。###讓數(shù)據(jù)傳輸不需要經(jīng)過userspace,使用mmap我們減少拷貝次數(shù)的一種方法是調(diào)用mmap()來代替read調(diào)用:buf=mmap(diskfd,len);write(sockfd,buf,len);應(yīng)用程序調(diào)用mmap(),磁盤上的數(shù)據(jù)會通過DMA被拷貝的內(nèi)核緩沖區(qū),接著操作系統(tǒng)會把這段內(nèi)核緩沖區(qū)與應(yīng)用程序共享,這樣就不需要把內(nèi)核緩沖區(qū)的內(nèi)容往用戶空間拷貝。應(yīng)用程序再調(diào)用write(),操作系統(tǒng)直接將內(nèi)核緩沖區(qū)的內(nèi)容拷貝到socket緩沖區(qū)中,這一切都發(fā)生在內(nèi)核態(tài),最后,socket緩沖區(qū)再把數(shù)據(jù)發(fā)到網(wǎng)卡去。同樣的,看圖很簡單:使用mmap替代read很明顯減少了一次拷貝,當(dāng)拷貝數(shù)據(jù)量很大時,無疑提升了效率。但是使用mmap是有代價的。當(dāng)你使用mmap時,你可能會遇到一些隱藏的陷阱。例如,當(dāng)你的程序map了一個文件,但是當(dāng)這個文件被另一個進(jìn)程截斷(truncate)時,write系統(tǒng)調(diào)用會因為訪問非法地址而被SIGBUS信號終止。SIGBUS信號默認(rèn)會殺死你的進(jìn)程并產(chǎn)生一個coredump,如果你的服務(wù)器這樣被中止了,那會產(chǎn)生一筆損失。通常我們使用以下解決方案避免這種問題:為SIGBUS信號建立信號處理程序
當(dāng)遇到
SIGBUS信號時,信號處理程序簡單地返回,
write系統(tǒng)調(diào)用在被中斷之前會返回已經(jīng)寫入的字節(jié)數(shù),并且
errno會被設(shè)置成success,但是這是一種糟糕的處理辦法,因為你并沒有解決問題的實質(zhì)核心。使用文件租借鎖
通常我們使用這種方法,在文件描述符上使用租借鎖,我們?yōu)槲募騼?nèi)核申請一個租借鎖,當(dāng)其它進(jìn)程想要截斷這個文件時,內(nèi)核會向我們發(fā)送一個實時的
RT_SIGNAL_LEASE信號,告訴我們內(nèi)核正在破壞你加持在文件上的讀寫鎖。這樣在程序訪問非法內(nèi)存并且被
SIGBUS殺死之前,你的
write系統(tǒng)調(diào)用會被中斷。
write會返回已經(jīng)寫入的字節(jié)數(shù),并且置
errno為success。
我們應(yīng)該在
mmap文件之前加鎖,并且在操作完文件后解鎖:if(fcntl(diskfd,F_SETSIG,RT_SIGNAL_LEASE)==-1){
perror("kernelleasesetsignal");
return-1;}/*l_typecanbeF_RDLCKF_WRLCK
加鎖*//*l_typecanbe
F_UNLCK解鎖*/if(fcntl(diskfd,F_SETLEASE,l_type)){
perror("kernelleasesettype");
return-1;}關(guān)于更多零拷貝的問題可以查看《如何理解Linux的零拷貝技術(shù)?》所以,我們可以看到高并發(fā)的本質(zhì)是通過軟件層編碼的方法充分使用內(nèi)存和cpu,這是單機(jī),再加集群就是無限級了,當(dāng)然集群的管理和監(jiān)控也是相當(dāng)重要的組成部分這里面最重要的部分就是1:充分利用內(nèi)存,壓榨cpu2:處理好網(wǎng)絡(luò)IO,socketfd這東西在貫穿網(wǎng)絡(luò)的主要核心,了解了socketfd就基本了解了外界于linux打交道的原理,至于怎么打交道就是poll,select,epoll的事情了3:算法,算法也是軟件編碼層的充分使用硬件相對獨(dú)立的一個分支,關(guān)于算法相關(guān)內(nèi)容可以參考:《十大經(jīng)典排序算法(動圖演示,收藏好文)》《一遍記住Java面試中常用的八種排序算法與代碼實現(xiàn)!》主宰這個世界的10種算法已經(jīng)絕版的《數(shù)據(jù)結(jié)構(gòu)和算法(第二版)》高清電子書!(附下載)435頁經(jīng)典書籍《算法心得:高效算法的奧秘(第2版)》【干貨】350+頁的《數(shù)據(jù)結(jié)構(gòu)與算法》pdf一致性哈希算法在分布式場景中的應(yīng)用今日頭條、抖音推薦算法原理全文詳解基于以上三點又構(gòu)建了諸如docker,nginxserver,lvs,redis,多線程語言,數(shù)據(jù)庫,分布式存儲的一系列應(yīng)用,至于其他,小編也在射射發(fā)抖的學(xué)習(xí)...如何構(gòu)建高并發(fā)系統(tǒng)知道了高并發(fā)系統(tǒng)的相關(guān)實質(zhì),那么我們還得會使用前輩們造好的輪子來搭配好,平時我們所說的高并發(fā)系統(tǒng)更多的是用工具來組合形成一個穩(wěn)定高效的系統(tǒng),也就是所謂的高并發(fā)高可用,如果并發(fā)太大又需要對前輩們造的輪子做改造,而大多數(shù)組件是C語言寫的,所以做架構(gòu)能會C,能了解到相關(guān)組件的源碼并在需要的情況下做修改是架構(gòu)師向更高層次發(fā)展需要具備的要素,大佬們造的那些輪子也是支撐高并發(fā)系統(tǒng)的核心要素,如redis,lvs,nginx,mysql,感謝開源,站在巨人的肩膀上做架構(gòu)竟然變得如何美好;高可用是伴隨高并發(fā)而產(chǎn)生的,前面說過高并發(fā),這里又有一個高可用,什么是高可用呢1、什么是高可用高可用指系統(tǒng)的可用程度。沒有100%的可用性。打個夸張的比方說,部署在全球的所有機(jī)房都同時停電了,那么系統(tǒng)就不能再提供服務(wù)。一般我們只需要做到4個9就已經(jīng)很不錯了,如下圖:2、高可用分類按照業(yè)務(wù)=邏輯+數(shù)據(jù)來分,高可用分為計算高可用和存儲高可用,邏輯即數(shù)據(jù),數(shù)據(jù)即存儲。2.1計算高可用常見的計算高可用架構(gòu)分為主備、主從、對稱集群、非對稱集群。主備:主從:對稱集群:非對稱集群:2.2存儲高可用常見的存儲高可用有主備、主從、主備/主從切換,主主,集群(數(shù)據(jù)集中集群和數(shù)據(jù)分散集群),分區(qū)(洲際、國家、城市、同城分區(qū))。主備:主從:數(shù)據(jù)集中式集群:主主集群:數(shù)據(jù)分散集群:
比如HDFS的架構(gòu)。在存儲界,還有一個比較有名的組件FastDFS,基本設(shè)計也是類似,關(guān)于高可用的知識圖譜,可以作為參考:往往我們開始做系統(tǒng)時,并不是一開始就設(shè)計這么復(fù)雜的架構(gòu),架構(gòu)核心的內(nèi)容是大道至簡,架構(gòu)也是根據(jù)需要一步步演進(jìn)而來的,一般目前的架構(gòu)要比現(xiàn)在實際用戶量并發(fā)量至少高一個層級,創(chuàng)業(yè)公司剛上來也沒必要搞那么復(fù)雜的系統(tǒng),關(guān)于基礎(chǔ)的技術(shù)選型可以查看《創(chuàng)業(yè)公司技術(shù)選型與管理注意事項》,一個springboot跑起來再說,夠你玩好久了,等你量達(dá)到那種程度了;但對于技術(shù)來說,還是能夠提前做到心中有數(shù)比較好某些App怎么扛住1分鐘10億請求?架構(gòu)的演進(jìn)路線百萬級并發(fā):1秒100萬次請求。千萬級并發(fā):一分鐘6億次請求,差不多就是需求的極限。架構(gòu)的設(shè)計和架構(gòu)優(yōu)化要符合需求本身,不能無限制優(yōu)化。基本概念(1)分布式(系統(tǒng)中,多個模塊在不同服務(wù)器上部署)(2)集群(一個軟件部署在多臺服務(wù)器,并作為一個整體,提供一類服務(wù))(3)高可用(系統(tǒng)中部分節(jié)點失效,其他節(jié)點能夠接替它繼續(xù)工作或有相應(yīng)的處理預(yù)案)(4)負(fù)載均衡(把請求均勻的發(fā)到多個節(jié)點上)架構(gòu)演進(jìn):1
單機(jī)架構(gòu)DNS服務(wù)器,做域名解析的服務(wù)器,作用是,經(jīng)過DNS將這類的域名轉(zhuǎn)換為實際IP地址,瀏覽器轉(zhuǎn)而訪問這個IP對應(yīng)的tomcat。如果是單機(jī)一般用服務(wù)商自己的DNS解析即可,如果是多機(jī)DNSPOD在域名輪詢層就是不錯解決方案;java用tomcat,php用nginx,springboot這騷貨還自帶tomcat,你要嫌麻煩直接啟動springboot也是可以的瓶頸:用戶增長,java(php)代碼、靜態(tài)資源和數(shù)據(jù)庫之間競爭資源,單機(jī)性能不足以支撐業(yè)務(wù),萬一哪臺機(jī)器內(nèi)存突然出點兒狀況,你的服務(wù)也就不可用了。2
第一次演進(jìn):動靜分離、代碼與數(shù)據(jù)庫分離java(php,go)代碼和數(shù)據(jù)庫分別獨(dú)占服務(wù)器資源,顯著提高兩者各自性能,這個時候也可以把html和圖片靜態(tài)文件資源分離,目前大多數(shù)情況下是前后端分離的,創(chuàng)業(yè)公司用vue把打包過后的文件單獨(dú)部署一個域名,隨時可以通過jenkins部署到新服務(wù)器(tomcat服務(wù)器找一個內(nèi)存大的,DB服務(wù)器找一個硬盤大的,帶寬更寬的)。瓶頸:用戶量增長,數(shù)據(jù)庫并發(fā)讀寫,尤其是讀,成為瓶頸。注意,不會通過數(shù)據(jù)庫集群解決3
第二次演進(jìn):引進(jìn)CDN,緩存甚至分布式緩存在Tomcat服務(wù)器上(Java程序所在的地方)加入緩存,可以把絕大多數(shù)請求(尤其是查詢)在訪問數(shù)據(jù)庫前攔截掉。如果你的服務(wù)器是nginx或者有nginx代理層,nginx可以直接訪問和刷新緩存的Redis一般放在單獨(dú)的服務(wù)器上,也可以多弄幾臺Redis服務(wù)器,配置成主從同步(提升可用性可以加上哨兵)。
redis的進(jìn)群解決方案一般有Codis,RedisCluster,twemproxy,redis主從,這幾種都各有優(yōu)缺點,如果你的redis集群量不大,搞個主從就可以了;提到天貓和redis,自然少不了秒殺場景,秒殺場景可以參考《解密Redis助力雙11背后電商秒殺系統(tǒng)》的一些做法當(dāng)然,這個時候消息隊列也可以出現(xiàn)在系統(tǒng)里了,開始用redis也可以抗一陣兒,金融場景RocketMQ是不錯的選擇,kafka追求高吞吐量,起源的時候是用于海量日志傳輸,但是隨著版本的越來越完善,可靠性也在不斷提高,據(jù)說(沒親眼見代碼)某滴滴公司消息推送就使用kafka了瓶頸:用戶數(shù)量增長,并發(fā)壓力主要在單機(jī)的tomcat+java上,響應(yīng)逐漸變慢。單機(jī)java變慢還可以優(yōu)化呀,每個api接口的時間監(jiān)控起來,mysql慢查詢監(jiān)控起來,推薦一款阿里問題定位神器《阿里問題定位神器Arthas的騷操作,定位線上BUG,超給力》4
第三次演進(jìn):引入反向代理和負(fù)載均衡使用反向代理,將大量的用戶請求,均勻分發(fā)到每個java應(yīng)用程序中。關(guān)于nginx為什么能支撐這么大并發(fā)可以閱讀《只知道Nginx牛逼,卻不知道它怎么支持百萬并發(fā)?》瓶頸:應(yīng)用服務(wù)器可支持的并發(fā)量大大增加,緩存能力也可以輕易擴(kuò)展,并發(fā)量增長意味著更多請求穿透到數(shù)據(jù)庫,單機(jī)的數(shù)據(jù)庫最終成為瓶頸。靜態(tài)文件大幅度訪問影響5
第四次演進(jìn):數(shù)據(jù)庫讀寫分離把數(shù)據(jù)庫劃分為讀庫和寫庫,讀庫可以有多個,通過同步機(jī)制把寫庫的數(shù)據(jù)同步到讀庫,使用數(shù)據(jù)庫中間件(Mycat),通過它來組織數(shù)據(jù)庫的分離讀寫。php用mysqlnd或者在代碼里來個讀寫分離,讀寫分離如何做呢,就是在執(zhí)行sql前,匹配是delete,insert,update,replace操作就讀主庫,select等就讀從庫瓶頸:業(yè)務(wù)逐漸變多,不同業(yè)務(wù)之間的訪問量差距較大,不同業(yè)務(wù)直接競爭數(shù)據(jù)庫,相互影響性能。6
第五次演進(jìn):數(shù)據(jù)庫按業(yè)務(wù)分庫把不同的業(yè)務(wù)數(shù)據(jù)保存到不同的數(shù)據(jù)庫中,業(yè)務(wù)之間的資源競爭降低,訪問量大的業(yè)務(wù)可以部署更多的服務(wù)器。用戶中心一般是首先需要獨(dú)立出來的,對應(yīng)的應(yīng)用也可以獨(dú)立部署瓶頸:用戶數(shù)量增長,單機(jī)的寫庫會逐漸達(dá)到性能瓶頸。7
第六次演進(jìn):把數(shù)據(jù)庫的大表拆成小表比如針對訂單生成,可以按照月份,甚至小時創(chuàng)建表。到底是1000萬還是2000萬數(shù)據(jù)分表的時候,這個需要看你這張表字段多少,和每個字段存儲的量和你機(jī)器的配置,一般存一兩千萬沒什么問題,跑得呼呼的;分表分庫方法分幾種,可以參考《不用找了,大廠在用的分庫分表方案,都在這了!》這種做法可以稱作分布式數(shù)據(jù)庫,但邏輯上仍然是一個完整的數(shù)據(jù)庫整體,現(xiàn)在有一種架構(gòu)叫MPP(大規(guī)模并行處理),針對于各種這類問題的使用場景。分表分庫倒是分好了,你查詢寫入和數(shù)據(jù)合并的時候麻煩了,常用的分表分庫中間件有如下幾種,各有優(yōu)缺點,一般大廠都是自己根據(jù)業(yè)務(wù)場景獨(dú)立開發(fā)的,百度用的Heisenberg,/brucexx/heisenberg(開源版已停止維護(hù))支撐天貓?zhí)詫氈Ц秾毮敲创罅髁恳彩侨巳馐止し直矸謳靻幔繘]有,阿里大多數(shù)場景用了他們自己的oceanbase數(shù)據(jù)庫,oceanbase數(shù)據(jù)庫也是有一層自己的OBproxy代理的,只是沒有這層代理oceanbase也能跑得不錯的;可以發(fā)現(xiàn)要深入的做架構(gòu),需要對相關(guān)組件能根據(jù)業(yè)務(wù)做相應(yīng)的改造,這個時候linux系統(tǒng),c語言,數(shù)據(jù)結(jié)構(gòu)就變得非常重要了,而人的精力有限,樣樣都精不可能,這個時候你就需要團(tuán)隊協(xié)作了,深入研究一個點兒,其他地方也會發(fā)現(xiàn)差不多。瓶頸:數(shù)據(jù)庫和tomcat都可以大規(guī)模水平擴(kuò)展,最終單機(jī)的nginx會成為瓶頸。8
第七次演進(jìn):使用LVS讓多個Nginx負(fù)載均衡LVS是軟件,運(yùn)行在操作系統(tǒng)內(nèi)核態(tài),可以對TCP請求或高層網(wǎng)絡(luò)協(xié)議進(jìn)行轉(zhuǎn)發(fā),分發(fā)的性能遠(yuǎn)高于Nginx,大概十幾萬。F5是硬件,跟LVS做的事情類似,但性能更高,而且價格昂貴。這種方式,用戶可達(dá)千萬或上億級別。瓶頸:LVS達(dá)到瓶頸,或用戶分布在不同的地區(qū),與服務(wù)器機(jī)房的距離不同,導(dǎo)致訪問延遲的不同。9
第八次演進(jìn):智能DNS輪詢實現(xiàn)機(jī)房間的負(fù)載均衡別說,DNSPOD還挺好用的,不同機(jī)房ip智能解析,響應(yīng)速度也不錯,當(dāng)然還有收費(fèi)版的,功能更多(這不是騰訊的廣告)在DNS中配置一個域名對應(yīng)多個IP。每個IP地址對應(yīng)到不同的機(jī)房里的虛擬IP。做到機(jī)房級別的水平擴(kuò)展,已經(jīng)是從請求并發(fā)量來講,過億的處理方案,十幾億或幾十億的并發(fā),暫時沒人考慮。瓶頸:檢索,分析的需求越來越多,單靠數(shù)據(jù)庫無法解決各種各樣的需求。10
第九次演進(jìn):引入NoSQL數(shù)據(jù)庫和搜索引擎數(shù)據(jù)量多到一定規(guī)模的時候,關(guān)系型數(shù)據(jù)庫不再適用,而且數(shù)據(jù)量較大的查詢,MySQL不一定能運(yùn)行出結(jié)果,對于海量數(shù)據(jù)的處理,通過分布式文件系統(tǒng)HDFS來存儲,對于key-value類型的數(shù)據(jù),通過HBase、Redis等處理,對于抓取查詢,可以通過ES等解決,對于多維分析,通過kylin、Druid等解決。阿里云上有各種時序數(shù)據(jù)庫,圖數(shù)據(jù)庫,表格數(shù)據(jù)庫,還有HybridDBforMySQL,支持OLTP和OLAP,tidb也干這活兒,是個不錯的選擇,也是近年以來發(fā)展不錯的數(shù)據(jù)庫廠商,有大廠給你當(dāng)靠山,億級流量就變得比以前更容易了引入更多的組件同時必然極大的提高系統(tǒng)復(fù)雜度,不同的組件的數(shù)據(jù)還需要同步,需要考慮一致性問題。11
第十次演進(jìn):數(shù)據(jù)兩地三中心一般來說目前比較流行的災(zāi)備體系是至少建設(shè)三個數(shù)據(jù)中心,其中:主中心:正常情況下全面提供業(yè)務(wù)服務(wù)。同城中心:一般使用同步復(fù)制的方式來向同城災(zāi)備中心傳輸數(shù)據(jù),保證同城中心數(shù)據(jù)復(fù)本為最新,隨時可以接管業(yè)務(wù),以保證RTO的指標(biāo)。但是同城中心無法應(yīng)對此類刪庫事件。異地中心:一般使用延時異步復(fù)制(延時時間一般為30分鐘左右)的方式向異地災(zāi)備中心傳輸數(shù)據(jù),其中同步復(fù)制的好處是一旦主中心被人工破壞,那么不會立刻涉及異地中心以保證RPO的指標(biāo)。一句話總結(jié)災(zāi)備體系的最佳實踐就是兩地三中心;同城保證業(yè)務(wù)連續(xù)性,優(yōu)先負(fù)責(zé)用戶體驗;異地保證數(shù)據(jù)連續(xù)性,確保企業(yè)生存底線。而針對行為及日志等重要性等級不高的數(shù)據(jù),一般采用異地磁帶備份的方式。具體方式如下:解決方案有商用的也有開源的,商用的華為SAN3DC方案的不錯,mysql開源的可以嘗試一下阿里的canal:跨地域
MySQLbinlog增量訂閱&消費(fèi)組件不過從目前情況看不少企業(yè)尤其是創(chuàng)業(yè)型企業(yè),都沒有百年老店的觀念,因此在異地中心的建設(shè)上投入還不夠,不過這樣的模式缺點也很明顯,一旦發(fā)生這種刪庫事件就影響就是致命的。12
第十一次演進(jìn):大應(yīng)用拆為小應(yīng)用按照業(yè)務(wù)板塊來劃分應(yīng)用,使單個應(yīng)用的職責(zé)更清晰,相互之間可以做到獨(dú)立升級迭代,甚至可以做到部分功能關(guān)閉。瓶頸:不同應(yīng)用之間,存在公用的模塊,導(dǎo)致包含公共功能的部分在升級時,全部相關(guān)代碼都要跟著升級。13
第十一次演進(jìn):微服務(wù)、servicemesh“微服務(wù)架構(gòu)是一種架構(gòu)模式,它提倡將單一應(yīng)用程序劃分成一組小的服務(wù),服務(wù)之間相互協(xié)調(diào)、互相配合,為用戶提供最終價值。每個服務(wù)運(yùn)行在其獨(dú)立的進(jìn)程中,服務(wù)和服務(wù)之間采用輕量級的通信機(jī)制相互溝通(通常是基于HTTP的RestfulAPI).每個服務(wù)都圍繞著具體的業(yè)務(wù)進(jìn)行構(gòu)建,并且能夠被獨(dú)立的部署到生產(chǎn)環(huán)境、類生產(chǎn)環(huán)境等。(知乎華為云技術(shù)宅基地)微服務(wù)架構(gòu):類
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 外墻施工后期維護(hù)方案
- 醫(yī)院智能排班系統(tǒng)方案
- 保溫材料市場調(diào)研方案
- 地下車庫消防設(shè)施設(shè)計方案
- 心梗急救知識分享
- 為社區(qū)文藝晚會策劃節(jié)目征集方案舞臺設(shè)計與宣傳策略
- 施工現(xiàn)場交通組織管理方案
- 水電工程管道鋪設(shè)管理方案
- 婦幼保健院醫(yī)務(wù)人員培訓(xùn)方案
- 地基處理與加固技術(shù)方案
- 河北省邢臺市2025-2026學(xué)年七年級上學(xué)期期末考試歷史試卷(含答案)
- 2026屆南通市高二數(shù)學(xué)第一學(xué)期期末統(tǒng)考試題含解析
- 寫字樓保潔培訓(xùn)課件
- 2026中國電信四川公用信息產(chǎn)業(yè)有限責(zé)任公司社會成熟人才招聘備考題庫有完整答案詳解
- 計量宣貫培訓(xùn)制度
- 2026中國電信四川公用信息產(chǎn)業(yè)有限責(zé)任公司社會成熟人才招聘備考題庫有答案詳解
- 《老年服務(wù)禮儀與溝通技巧》-《老年服務(wù)禮儀與溝通技巧》-老年服務(wù)禮儀與溝通技巧
- 社會學(xué)概論(第2版)PPT完整全套教學(xué)課件
- RB/T 208-2016化學(xué)實驗室內(nèi)部質(zhì)量控制比對試驗
- GB/T 37898-2019風(fēng)力發(fā)電機(jī)組吊裝安全技術(shù)規(guī)程
- GB/T 32893-201610 kV及以上電力用戶變電站運(yùn)行管理規(guī)范
評論
0/150
提交評論