成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識庫 > 美團點評對于網(wǎng)站性能優(yōu)化的經(jīng)驗總結(jié)

美團點評對于網(wǎng)站性能優(yōu)化的經(jīng)驗總結(jié)

熱門標簽:開地圖標注公司掙錢嘛 canvas世界地圖標注點線 蘭州銷售外呼系統(tǒng)加盟 寧夏手機自動外呼系統(tǒng)好用嗎 合肥機器人外呼系統(tǒng) 地圖標注新地點 地圖標注難民 電銷機器人用戶反饋 沈陽電話電銷機器人官網(wǎng)

性能優(yōu)化涉及面很廣。一般而言,性能優(yōu)化指降低響應時間和提高系統(tǒng)吞吐量兩個方面,但在流量高峰時候,性能問題往往會表現(xiàn)為服務可用性下降,所以性能優(yōu)化也可以包括提高服務可用性。在某些情況下,降低響應時間、提高系統(tǒng)吞吐量和提高服務可用性三者相互矛盾,不可兼得。例如:增加緩存可以降低平均響應時間,但是處理線程數(shù)量會因為緩存過大而有所限制,從而降低系統(tǒng)吞吐量;為了提高服務可用性,對異常請求重復調(diào)用是一個常用的做法,但是這會提高響應時間并降低系統(tǒng)吞吐量。

對于很多像美團這樣的公司,它們的系統(tǒng)會面臨如下三個挑戰(zhàn):1. 日益增長的用戶數(shù)量,2. 日漸復雜的業(yè)務,3. 急劇膨脹的數(shù)據(jù)。這些挑戰(zhàn)對于性能優(yōu)化而言表現(xiàn)為:在保持和降低系統(tǒng)TP95響應時間(指的是將一段時間內(nèi)的請求響應時間從低到高排序,高于95%請求響應時間的下確界)的前提下,不斷提高系統(tǒng)吞吐量,提升流量高峰時期的服務可用性。這種場景下,三者的目標和改進方法取得了比較好的一致。本文主要目標是為類似的場景提供優(yōu)化方案,確保系統(tǒng)在流量高峰時期的快速響應和高可用。

文章第一部分是介紹,包括采用模式方式講解的優(yōu)點,文章所采用案例的說明,以及后面部分用到的一些設計原則;第二部分介紹幾種典型的“性能惡化模式”,闡述導致系統(tǒng)性能惡化,服務可用性降低的典型場景以及形成惡化循環(huán)的過程;第三部分是文章重點,闡述典型的“性能優(yōu)化模式”,這些模式或者可以使服務遠離“惡化模式”,或者直接對服務性能進行優(yōu)化;文章最后一部分進行總結(jié),并對未來可能出現(xiàn)的新模式進行展望。

介紹
模式講解方式
關(guān)于性能優(yōu)化的文章和圖書已有很多,但就我所知,還沒有采用模式的方式去講解的。本文借鑒《設計模式》("Design Patterns-Elements of Reusable Object-Oriented Software")對設計模式的闡述方式,首先為每一種性能優(yōu)化模式取一個貼切的名字,便于讀者快速理解和深刻記憶,接著講解該模式的動機和原理,然后結(jié)合作者在美團的具體工作案例進行深度剖析,最后總結(jié)采用該模式的優(yōu)點以及需要付出的代價。簡而言之,本文采用“命名-->原理和動機-->具體案例-->缺點和優(yōu)點”的四階段方式進行性能優(yōu)化模式講解。與其他方式相比,采用模式進行講解有兩個方面的優(yōu)點:一方面,讀者不僅僅能夠掌握優(yōu)化手段,而且能夠了解采用該手段進行性能優(yōu)化的場景以及所需付出的代價,這有利于讀者全面理解和靈活應用;另一方面,模式解決的是特定應用場景下的一類問題,所以應用場景描述貫穿于模式講解之中。如此,即使讀者對原理不太了解,只要碰到的問題符合某個特定模式的應用場景(這往往比理解原理要簡單),就可以采用對應的手段進行優(yōu)化,進一步促進讀者對模式的理解和掌握。

案例說明
文章的所有案例都來自于美團的真實項目。出于兩方面的考慮,作者做了一定的簡化和抽象:一方面,系統(tǒng)可以優(yōu)化的問題眾多,而一個特定的模式只能解決幾類問題,所以在案例分析過程中會突出與模式相關(guān)的問題;另一方面,任何一類問題都需要多維度數(shù)據(jù)去描述,而應用性能優(yōu)化模式的前提是多維度數(shù)據(jù)的組合值超過了某個臨界點,但是精確定義每個維度數(shù)值的臨界點是一件很難的事情,更別說多維度數(shù)據(jù)組合之后臨界點。因此有必要對案例做一些簡化,確保相關(guān)取值范圍得到滿足?;谝陨弦约捌渌?,作者所給出的解決方案只是可行性方案,并不保證其是所碰到問題的最佳解決方案。

案例涉及的所有項目都是基于Java語言開發(fā)的,嚴格地講,所有模式適用的場景是基于Java語言搭建的服務。從另外一方面講,Java和C++的主要區(qū)別在于垃圾回收機制,所以,除去和垃圾回收機制緊密相關(guān)的模式之外,文章所描述的模式也適用于采用C++語言搭建的服務。對于基于其他語言開發(fā)的服務,讀者在閱讀以及實踐的過程中需要考慮語言之間的差別。

設計原則
必須說明,本文中各種模式所要解決的問題之所以會出現(xiàn),部分是因為工程師運用了某些深層次的設計原則。有些設計原則看上去和優(yōu)秀的設計理念相悖,模式所解決的問題似乎完全可以避免,但是它們卻被廣泛使用。“存在即合理”,世界上沒有完美的設計方案,任何方案都是一系列設計原則的妥協(xié)結(jié)果,所以本文主要關(guān)注點是解決所碰到的問題而不是如何繞過這些設計原則。下面對文中重要的設計原則進行詳細闡述,在后面需要運用該原則時將不再解釋。

最小可用原則
最小可用原則(快速接入原則)有兩個關(guān)注點:1. 強調(diào)快速接入,快速完成;2. 實現(xiàn)核心功能可用。這是一個被普遍運用的原則,其目標是縮短測試周期,增加試錯機會,避免過度設計。為了快速接入就必須最大限度地利用已有的解決方案或系統(tǒng)。從另外一個角度講,一個解決方案或系統(tǒng)只要能夠滿足基本需求,就滿足最小可用原則的應用需求。過度強調(diào)快速接入原則會導致重構(gòu)風險的增加,原則上講,基于該原則去設計系統(tǒng)需要為重構(gòu)做好準備。

經(jīng)濟原則
經(jīng)濟原則關(guān)注的是成本問題,看起來很像最小可用原則,但是它們之間關(guān)注點不同。最小可用原則的目標是通過降低開發(fā)周期,快速接入而實現(xiàn)風險可控,而快速接入并不意味著成本降低,有時候為了實現(xiàn)快速接入可能需要付出巨大的成本。軟件項目的生命周期包括:預研、設計、開發(fā)、測試、運行、維護等階段。最小可用原則主要運用在預研階段,而經(jīng)濟原則可以運用在整個軟件生命周期里,也可以只關(guān)注某一個或者幾個階段。例如:運行時經(jīng)濟原則需要考慮的系統(tǒng)成本包括單次請求的CPU、內(nèi)存、網(wǎng)絡、磁盤消耗等;設計階段的經(jīng)濟原則要求避免過度設計;開發(fā)階段的經(jīng)濟原則可能關(guān)注代碼復用,工程師資源復用等。

代碼復用原則
代碼復用原則分為兩個層次:第一個層次使用已有的解決方案或調(diào)用已存在的共享庫(Shared Library),也稱為方案復用;第二個層次是直接在現(xiàn)有的代碼庫中開發(fā),也稱之為共用代碼庫。

方案復用是一個非常實用主義的原則,它的出發(fā)點就是最大限度地利用手頭已有的解決方案,即使這個方案并不好。方案的形式可以是共享庫,也可以是已存在的服務。方案復用的例子參見避免蚊子大炮模式的具體案例。用搜索引擎服務來解決查找附近商家的問題是一個性能很差的方案,但仍被很多工程師使用。方案復用原則的一個顯著優(yōu)點就是提高生產(chǎn)效率,例如:Java之所以能夠得到如此廣泛應用,原因之一就是有大量可以重復利用的開源庫。實際上“Write once, run anywhere”是Java語言最核心的設計理念之一?;贘ava語言開發(fā)的代碼庫因此得以在不同硬件平臺、不同操作系統(tǒng)上更廣泛地使用。

共用代碼庫要求在同一套代碼庫中完成所有功能開發(fā)。采用這個原則,代碼庫中的所有功能編譯時可見,新功能代碼可以無邊界的調(diào)用老代碼。另外,原代碼庫已存在的各種運行、編譯、測試、配置環(huán)境可復用。主要有兩個方面地好處:1. 充分利用代碼庫中已有的基礎設施,快速接入新業(yè)務;2. 直接調(diào)用原代碼中的基礎功能或原語,避免網(wǎng)絡或進程間調(diào)用開銷,性能更佳。共用代碼庫的例子參見垂直分割模式的具體案例。

從設計的角度上講,方案復用類似于微服務架構(gòu)(Microservice Architecture,有些觀點認為這是一種形式的SOA),而共用代碼庫和Monolithic Architecture很接近??偟膩碚f,微服務傾向于面向接口編程,要求設計出可重用性的組件(Library或Service),通過分層組織各層組件來實現(xiàn)良好的架構(gòu)。與之相對應,Monolith Architecture則希望盡可能在一套代碼庫中開發(fā),通過直接調(diào)用代碼中的基礎功能或原語而實現(xiàn)性能的優(yōu)化和快速迭代。使用Monolith Architecture有很大的爭議,被認為不符合“設計模式”的理念。參考文獻[4],Monolithic Design主要的缺點包括:1. 缺乏美感;2. 很難重構(gòu);3. 過早優(yōu)化(參見文獻[6]Optimize judiciously); 4. 不可重用;5. 限制眼界。微服務架構(gòu)是很多互聯(lián)網(wǎng)公司的主流架構(gòu),典型的運用公司包括Amazon、美團等。Monolithic Architecture也有其忠實的粉絲,例如:Tripadvisor的全球網(wǎng)站就共用一套代碼庫;基于性能的考慮,Linux最終選擇的也是Monolithic kernel的模式。

奧卡姆剃刀原則
系統(tǒng)設計以及代碼編寫要遵循奧卡姆剃刀原則:Entities should not be multiplied unnecessarily。一般而言,一個系統(tǒng)的代碼量會隨著其功能增加而變多。系統(tǒng)的健壯性有時候也需要通過編寫異常處理代碼來實現(xiàn)。異常考慮越周全,異常處理代碼量越大。但是隨著代碼量的增大,引入Bug的概率也就越大,系統(tǒng)也就越不健壯。從另外一個角度來講,異常流程處理代碼也要考慮健壯性問題,這就形成了無限循環(huán)。所以在系統(tǒng)設計和代碼編寫過程中,奧卡姆剃刀原則要求:一個功能模塊如非必要,就不要;一段代碼如非必寫,就不寫。

奧卡姆剃刀原則和最小可用原則有所區(qū)別。最小可用原則主要運用于產(chǎn)品MVP階段,本文所指的奧卡姆剃刀原則主要指系統(tǒng)設計和代碼編寫兩個方面,這是完全不同的兩個概念。MVP包含系統(tǒng)設計和代碼編寫,但同時,系統(tǒng)設計和代碼編寫也可以發(fā)生在成熟系統(tǒng)的迭代階段。

性能惡化模式
在講解性能優(yōu)化模式之前,有必要先探討一下性能惡化模式,因為:

很多性能優(yōu)化模式的目標之一就是避免系統(tǒng)進入性能惡化模式;
不同性能優(yōu)化模式可能是避免同一種性能惡化模式;
同一種性能優(yōu)化模式可能在不同階段避免不同的性能惡化模式。
在此統(tǒng)一闡述性能惡化模式,避免下文重復解釋。為了便于讀者清晰識別惡化模式和優(yōu)化模式,惡化模式采用“XXX反模式”的方式進行命名。
長請求擁塞反模式(High Latency Invocating AntiPattern)
這是一種單次請求時延變長而導致系統(tǒng)性能惡化甚至崩潰的惡化模式。對于多線程服務,大量請求時間變長會使線程堆積、內(nèi)存使用增加,最終可能會通過如下三種方式之一惡化系統(tǒng)性能:

線程數(shù)目變多導致線程之間CPU資源使用沖突,反過來進一步延長了單次請求時間;
線程數(shù)量增多以及線程中緩存變大,內(nèi)存消耗隨之劇增,對于基于Java語言的服務而言,又會更頻繁地full GC,反過來單次請求時間會變得更長;
內(nèi)存使用增多,會使操作系統(tǒng)內(nèi)存不足,必須使用Swap,可能導致服務徹底崩潰。
典型惡化流程圖如下圖:

長請求擁塞反模式所導致的性能惡化現(xiàn)象非常普遍,所以識別該模式非常重要。典型的場景如下:某復雜業(yè)務系統(tǒng)依賴于多個服務,其中某個服務的響應時間變長,隨之系統(tǒng)整體響應時間變長,進而出現(xiàn)CPU、內(nèi)存、Swap報警。系統(tǒng)進入長請求擁塞反模式的典型標識包括:被依賴服務可用性變低、響應時間變長、服務的某段計算邏輯時間變長等。

多次請求杠桿反模式(Levered Multilayer Invocating AntiPattern)
客戶端一次用戶點擊行為往往會觸發(fā)多次服務端請求,這是一次請求杠桿;每個服務端請求進而觸發(fā)多個更底層服務的請求,這是第二次請求杠桿。每一層請求可能導致一次請求杠桿,請求層級越多,杠桿效應就越大。在多次請求杠桿反模式下運行的分布式系統(tǒng),處于深層次的服務需要處理大量請求,容易會成為系統(tǒng)瓶頸。與此同時,大量請求也會給網(wǎng)絡帶來巨大壓力,特別是對于單次請求數(shù)據(jù)量很大的情況,網(wǎng)絡可能會成為系統(tǒng)徹底崩潰的導火索。典型惡化流程圖如下圖:

多次請求杠桿所導致的性能惡化現(xiàn)象非常常見,例如:對于美團推薦系統(tǒng),一個用戶列表請求會有多個算法參與,每個算法會召回多個列表單元(商家或者團購),每個列表單元有多種屬性和特征,而這些屬性和特征數(shù)據(jù)服務又分布在不同服務和機器上面,所以客戶端的一次用戶展現(xiàn)可能導致了成千上萬的最底層服務調(diào)用。對于存在多次請求杠桿反模式的分布式系統(tǒng),性能惡化與流量之間往往遵循指數(shù)曲線關(guān)系。這意味著,在平常流量下正常運行服務系統(tǒng),在流量高峰時通過線性增加機器解決不了可用性問題。所以,識別并避免系統(tǒng)進入多次請求杠桿反模式對于提高系統(tǒng)可用性而言非常關(guān)鍵。

反復緩存反模式(Recurrent Caching AntiPattern)
為了降低響應時間,系統(tǒng)往往在本地內(nèi)存中緩存很多數(shù)據(jù)。緩存數(shù)據(jù)越多,命中率就越高,平均響應時間就越快。為了降低平均響應時間,有些開發(fā)者會不加限制地緩存各種數(shù)據(jù),在正常流量情況下,系統(tǒng)響應時間和吞吐量都有很大改進。但是當流量高峰來臨時,系統(tǒng)內(nèi)存使用開始增多,觸發(fā)了JVM進行full GC,進而導致大量緩存被釋放(因為主流Java內(nèi)存緩存都采用SoftReference和WeakReference所導致的),而大量請求又使得緩存被迅速填滿,這就是反復緩存。反復緩存導致了頻繁的full GC,而頻繁full GC往往會導致系統(tǒng)性能急劇惡化。典型惡化流程圖如下圖:

反復緩存所導致性能惡化的原因是無節(jié)制地使用緩存。緩存使用的指導原則是:工程師們在使用緩存時必須全局考慮,精細規(guī)劃,確保數(shù)據(jù)完全緩存的情況下,系統(tǒng)仍然不會頻繁full GC。為了確保這一點,對于存在多種類型緩存以及系統(tǒng)流量變化很大的系統(tǒng),設計者必須嚴格控制緩存大小,甚至廢除緩存(這是典型為了提高流量高峰時可用性,而降低平均響應時間的一個例子)。反復緩存反模式往往發(fā)生在流量高峰時候,通過線性增加機器和提高機器內(nèi)存可以大大減少系統(tǒng)崩潰的概率。

性能優(yōu)化模式
水平分割模式(Horizontal partitioning Pattern)
原理和動機
典型的服務端運行流程包含四個環(huán)節(jié):接收請求、獲取數(shù)據(jù)、處理數(shù)據(jù)、返回結(jié)果。在一次請求中,獲取數(shù)據(jù)和處理數(shù)據(jù)往往多次發(fā)生。在完全串行運行的系統(tǒng)里,一次請求總響應時間滿足如下公式:

一次請求總耗時=解析請求耗時 + ∑(獲取數(shù)據(jù)耗時+處理數(shù)據(jù)耗時) + 組裝返回結(jié)果耗時

大部分耗時長的服務主要時間都花在中間兩個環(huán)節(jié),即獲取數(shù)據(jù)和處理數(shù)據(jù)環(huán)節(jié)。對于非計算密集性的系統(tǒng),主要耗時都用在獲取數(shù)據(jù)上面。獲取數(shù)據(jù)主要有三個來源:本地緩存,遠程緩存或者數(shù)據(jù)庫,遠程服務。三者之中,進行遠程數(shù)據(jù)庫訪問或遠程服務調(diào)用相對耗時較長,特別是對于需要進行多次遠程調(diào)用的系統(tǒng),串行調(diào)用所帶來的累加效應會極大地延長單次請求響應時間,這就增大了系統(tǒng)進入長請求擁塞反模式的概率。如果能夠?qū)Σ煌臉I(yè)務請求并行處理,請求總耗時就會大大降低。例如下圖中,Client需要對三個服務進行調(diào)用,如果采用順序調(diào)用模式,系統(tǒng)的響應時間為18ms,而采用并行調(diào)用只需要7ms。

水平分割模式首先將整個請求流程切分為必須相互依賴的多個Stage,而每個Stage包含相互獨立的多種業(yè)務處理(包括計算和數(shù)據(jù)獲取)。完成切分之后,水平分割模式串行處理多個Stage,但是在Stage內(nèi)部并行處理。如此,一次請求總耗時等于各個Stage耗時總和,每個Stage所耗時間等于該Stage內(nèi)部最長的業(yè)務處理時間。

水平分割模式有兩個關(guān)鍵優(yōu)化點:減少Stage數(shù)量和降低每個Stage耗時。為了減少Stage數(shù)量,需要對一個請求中不同業(yè)務之間的依賴關(guān)系進行深入分析并進行解耦,將能夠并行處理的業(yè)務盡可能地放在同一個Stage中,最終將流程分解成無法獨立運行的多個Stage。降低單個Stage耗時一般有兩種思路:1. 在Stage內(nèi)部再嘗試水平分割(即遞歸水平分割),2. 對于一些可以放在任意Stage中進行并行處理的流程,將其放在耗時最長的Stage內(nèi)部進行并行處理,避免耗時較短的Stage被拉長。

水平分割模式不僅可以降低系統(tǒng)平均響應時間,而且可以降低TP95響應時間(這兩者有時候相互矛盾,不可兼得)。通過降低平均響應時間和TP95響應時間,水平分割模式往往能夠大幅度提高系統(tǒng)吞吐量以及高峰時期系統(tǒng)可用性,并大大降低系統(tǒng)進入長請求擁塞反模式的概率。

具體案例:
我們的挑戰(zhàn)來自為用戶提供高性能的優(yōu)質(zhì)個性化列表服務,每一次列表服務請求會有多個算法參與,而每個算法基本上都采用“召回->特征獲取->計算”的模式。 在進行性能優(yōu)化之前,算法之間采用順序執(zhí)行的方式。伴隨著算法工程師的持續(xù)迭代,算法數(shù)量越來越多,隨之而來的結(jié)果就是客戶端響應時間越來越長,系統(tǒng)很容易進入長請求擁塞反模式。曾經(jīng)有一段時間,一旦流量高峰來臨,出現(xiàn)整條服務鏈路的機器CPU、內(nèi)存報警。在對系統(tǒng)進行分析之后,我們采取了如下三個優(yōu)化措施,最終使得系統(tǒng)TP95時間降低了一半:

算法之間并行計算;
每個算法內(nèi)部,多次特征獲取進行了并行處理;
在調(diào)度線程對工作線程進行調(diào)度的時候,耗時最長的線程最先調(diào)度,最后處理。
缺點和優(yōu)點
對成熟系統(tǒng)進行水平切割,意味著對原系統(tǒng)的重大重構(gòu),工程師必須對業(yè)務和系統(tǒng)非常熟悉,所以要謹慎使用。水平切割主要有兩方面的難點:

并行計算將原本單一線程的工作分配給多線程處理,提高了系統(tǒng)的復雜度。而多線程所引入的安全問題讓系統(tǒng)變得脆弱。與此同時,多線程程序測試很難,因此重構(gòu)后系統(tǒng)很難與原系統(tǒng)在業(yè)務上保持一致。
對于一開始就基于單線程處理模式編寫的系統(tǒng),有些流程在邏輯上能夠并行處理,但是在代碼層次上由于相互引用已經(jīng)難以分解。所以并行重構(gòu)意味著對共用代碼進行重復撰寫,增大系統(tǒng)的整體代碼量,違背奧卡姆剃刀原則。
對于上面提到的第二點,舉例如下:A和B是邏輯可以并行處理的兩個流程,基于單線程設計的代碼,假定處理完A后再處理B。在編寫處理B邏輯代碼時候,如果B需要的資源已經(jīng)在處理A的過程中產(chǎn)生,工程師往往會直接使用A所產(chǎn)生的數(shù)據(jù),A和B之間因此出現(xiàn)了緊耦合。并行化需要對它們之間的公共代碼進行拆解,這往往需要引入新的抽象,更改原數(shù)據(jù)結(jié)構(gòu)的可見域。
在如下兩種情況,水平切割所帶來的好處不明顯:

一個請求中每個處理流程需要獲取和緩存的數(shù)據(jù)量很大,而不同流程之間存在大量共享的數(shù)據(jù),但是請求之間數(shù)據(jù)共享卻很少。在這種情況下,流程處理完之后,數(shù)據(jù)和緩存都會清空。采用順序處理模式,數(shù)據(jù)可以被緩存在線程局部存儲(ThreadLocal)中而減少重復獲取數(shù)據(jù)的成本;如果采用水平切割的模式,在一次請求中,不同流程會多次獲取并緩存的同一類型數(shù)據(jù),對于內(nèi)存原本就很緊張的系統(tǒng),可能會導致頻繁full GC,進入反復緩存反模式。
某一個處理流程所需時間遠遠大于其他所有流程所需時間的總和。這種情況下,水平切割不能實質(zhì)性地降低請求響應時間。
采用水平切割的模式可以降低系統(tǒng)的平均響應時間和TP95響應時間,以及流量高峰時系統(tǒng)崩潰的概率。雖然進行代碼重構(gòu)比較復雜,但是水平切割模式非常容易理解,只要熟悉系統(tǒng)的業(yè)務,識別出可以并行處理的流程,就能夠進行水平切割。有時候,即使少量的并行化也可以顯著提高整體性能。對于新系統(tǒng)而言,如果存在可預見的性能問題,把水平分割模式作為一個重要的設計理念將會大大地提高系統(tǒng)的可用性、降低系統(tǒng)的重構(gòu)風險??偟膩碚f,雖然存在一些具體實施的難點,水平分割模式是一個非常有效、容易識別和理解的模式。

垂直分割模式(Vertical partitioning Pattern)
原理和動機:
對于移動互聯(lián)網(wǎng)節(jié)奏的公司,新需求往往是一波接一波。基于代碼復用原則,工程師們往往會在一個系統(tǒng)實現(xiàn)大量相似卻完全不相干的功能。伴隨著功能的增強,系統(tǒng)實際上變得越來越脆弱。這種脆弱可能表現(xiàn)在系統(tǒng)響應時間變長、吞吐量降低或者可用性降低。導致系統(tǒng)脆弱原因主要來自兩方面的沖突:資源使用沖突和可用性不一致沖突。

資源使用沖突是導致系統(tǒng)脆弱的一個重要原因。不同業(yè)務功能并存于同一個運行系統(tǒng)里面意味著資源共享,同時也意味著資源使用沖突。可能產(chǎn)生沖突的資源包括:CPU、內(nèi)存、網(wǎng)絡、I/O等。例如:一種業(yè)務功能,無論其調(diào)用量多么小,都有一些內(nèi)存開銷。對于存在大量緩存的業(yè)務功能,業(yè)務功能數(shù)量的增加會極大地提高內(nèi)存消耗,從而增大系統(tǒng)進入反復緩存反模式的概率。對于CPU密集型業(yè)務,當產(chǎn)生沖突的時候,響應時間會變慢,從而增大了系統(tǒng)進入長請求擁塞反模式的可能性。

不加區(qū)別地將不同可用性要求的業(yè)務功能放入一個系統(tǒng)里,會導致系統(tǒng)整體可用性變低。當不同業(yè)務功能糅合在同一運行系統(tǒng)里面的時候,在運維和機器層面對不同業(yè)務的可用性、可靠性進行調(diào)配將會變得很困難。但是,在高峰流量導致系統(tǒng)瀕臨崩潰的時候,最有效的解決手段往往是運維,而最有效手段的失效也就意味著核心業(yè)務的可用性降低。

垂直分割思路就是將系統(tǒng)按照不同的業(yè)務功能進行分割,主要有兩種分割模式:部署垂直分割和代碼垂直分割。部署垂直分割主要是按照可用性要求將系統(tǒng)進行等價分類,不同可用性業(yè)務部署在不同機器上,高可用業(yè)務單獨部署;代碼垂直分割就是讓不同業(yè)務系統(tǒng)不共享代碼,徹底解決系統(tǒng)資源使用沖突問題。

具體案例:
我們的挑戰(zhàn)來自于美團推薦系統(tǒng),美團客戶端的多個頁面都有推薦列表。雖然不同的推薦產(chǎn)品需求來源不同,但是為了實現(xiàn)快速的接入,基于共用代碼庫原則,所有的推薦業(yè)務共享同一套推薦代碼,同一套部署。在一段時間內(nèi),我們發(fā)現(xiàn)push推薦和首頁“猜你喜歡推薦”的資源消耗巨大。特別是在push推薦的高峰時刻,CPU和內(nèi)存頻繁報警,系統(tǒng)不停地full GC,造成美團用戶進入客戶端時,首頁出現(xiàn)大片空白。

在對系統(tǒng)進行分析之后,得出兩個結(jié)論:

首頁“猜你喜歡”對用戶體驗影響更大,應該給予最高可用性保障,而push推薦給予較低可用性保障;
首頁“猜你喜歡”和push推薦都需要很大的本地緩存,有較大的內(nèi)存使用沖突,并且響應時間都很長,有嚴重的CPU使用沖突。
因此我們采取了如下措施,一方面,解決了首頁“猜你喜歡”的可用性低問題,減少了未來出現(xiàn)可用性問題的概率,最終將其TP95響應時間降低了40%;另一方面也提高了其他推薦產(chǎn)品的服務可用性和高峰吞吐量。

將首頁“猜你喜歡”推薦進行單獨部署,而將push推薦和其他對系統(tǒng)資源要求不高的推薦部署在另一個集群上面;
對于新承接的推薦業(yè)務,新建一套代碼,避免影響首頁推薦這種最高可用性的業(yè)務。
缺點和優(yōu)點:
垂直分割主要的缺點主要有兩個:

增加了維護成本。一方面代碼庫數(shù)量增多提高了開發(fā)工程師的維護成本,另一方面,部署集群的變多會增加運維工程師的工作量;
代碼不共享所導致的重復編碼工作。
解決重復編碼工作問題的一個思路就是為不同的系統(tǒng)提供共享庫(Shared Library),但是這種耦合反過來可能導致部署機器中引入未部署業(yè)務的開銷。所以在共享庫中要減少靜態(tài)代碼的初始化開銷,并將類似緩存初始化等工作交給上層系統(tǒng)??偟膩碚f,通過共享庫的方式引入的開銷可以得到控制。但是對于業(yè)務密集型的系統(tǒng),由于業(yè)務往往是高度定制化的,共用一套代碼庫的好處是開發(fā)工程師可以采用Copy-on-write的模式進行開發(fā),需要修改的時候隨時拷貝并修改。共享庫中應該存放不容易變化的代碼,避免使用者頻繁升級,所以并不適合這種場景。因此,對于業(yè)務密集型的系統(tǒng),分代碼所導致的重復編碼量是需要權(quán)衡的一個因素。

垂直分割是一個非常簡單而又有效的性能優(yōu)化模式,特別適用于系統(tǒng)已經(jīng)出現(xiàn)問題而又需要快速解決的場景。部署層次的分割既安全又有效。需要說明的是部署分割和簡單意義上的加機器不是一回事,在大部分情況下,即使不增加機器,僅通過部署分割,系統(tǒng)整體吞吐量和可用性都有可能提升。所以就短期而言,這幾乎是一個零成本方案。對于代碼層次的分割,開發(fā)工程師需要在業(yè)務承接效率和系統(tǒng)可用性上面做一些折衷考慮。

恒變分離模式(Runtime 3NF Pattern)
原理和動機:
基于性能的設計要求變化的數(shù)據(jù)和不變的數(shù)據(jù)分開,這一點和基于面向?qū)ο蟮脑O計原則相悖。在面向?qū)ο蟮脑O計中,為了便于對一個對象有整體的把握,緊密相關(guān)的數(shù)據(jù)集合往往被組裝進一個類,存儲在一個數(shù)據(jù)庫表,即使有部分數(shù)據(jù)冗余(關(guān)于面向?qū)ο笈c性能沖突的討論網(wǎng)上有很多文章,本文不細講)。很多系統(tǒng)的主要工作是處理變化的數(shù)據(jù),如果變化的數(shù)據(jù)和不變的數(shù)據(jù)被緊密組裝在一起,系統(tǒng)對變化數(shù)據(jù)的操作將引入額外的開銷。而如果易變數(shù)據(jù)占總數(shù)據(jù)比例非常小,這種額外開銷將會通過杠桿效應惡化系統(tǒng)性能。分離易變和恒定不變的數(shù)據(jù)在對象創(chuàng)建、內(nèi)存管理、網(wǎng)絡傳輸?shù)确矫娑加兄谛阅芴岣摺?/p>

恒變分離模式的原理非常類似與數(shù)據(jù)庫設計中的第三范式(3NF):第三范式主要解決的是靜態(tài)存儲中重復存儲的問題,而恒變分離模式解決的是系統(tǒng)動態(tài)運行時候恒定數(shù)據(jù)重復創(chuàng)建、傳輸、存儲和處理的問題。按照3NF,如果一個數(shù)據(jù)表的每一記錄都依賴于一些非主屬性集合,而這些非主屬性集合大量重復出現(xiàn),那么應該考慮對被依賴的非主屬性集合定義一個新的實體(構(gòu)建一個新的數(shù)據(jù)表),原數(shù)據(jù)庫的記錄依賴于新實體的ID。如此一來數(shù)據(jù)庫重復存儲數(shù)據(jù)量將大大降低。類似的,按照恒變分離模式,對于一個實體,如果系統(tǒng)處理的只是這個實體的少量變化屬性,應該將不變的屬性定義為一個新實體(運行時的另一個類,數(shù)據(jù)庫中的另一個表),原來實體通過ID來引用新實體,那么原有實體在運行系統(tǒng)中的數(shù)據(jù)傳輸、創(chuàng)建、網(wǎng)絡開銷都會大大降低。

案例分析:
我們的挑戰(zhàn)是提供一個高性能、高一致性要求的團購服務(DealService)。系統(tǒng)存在一些多次請求杠桿反模式問題,客戶端一次請求會導致幾十次DealService讀取請求,每次獲取上百個團購詳情信息,服務端單機需要支持每秒萬次級別的吞吐量?;谛枨螅到y(tǒng)大體框架設計如下:

每個DealService定期從持久層同步所有發(fā)生變化的deal信息,所有的deal信息保存在內(nèi)存里面。在最初的設計里面,數(shù)據(jù)庫只有一個數(shù)據(jù)表DealModelTable,程序里面也只有一個實體類DealModel。由于銷量、價格、用戶評價等信息的頻發(fā)變化,為了達到高一致性要求,服務系統(tǒng)每分鐘需要從數(shù)據(jù)庫同步幾萬條記錄。隨著美團團購數(shù)量的增多和用戶活躍度的增加,系統(tǒng)出現(xiàn)了三個問題:

團購服務網(wǎng)卡頻繁報警,由于這是高性能低延時服務,又導致了大量的客戶端超時異常;
頻繁的full GC,這是由于每條數(shù)據(jù)庫記錄更新都會導致運行系統(tǒng)里面老的DealModel實體被銷毀,新的DealModels實體被創(chuàng)建;
數(shù)據(jù)庫從庫滯后主庫,使得服務數(shù)據(jù)一致性降低,原因是數(shù)據(jù)庫系統(tǒng)寫數(shù)據(jù)量巨大。
在對系統(tǒng)進行分析之后,我們采用了如下措施,大大降低了網(wǎng)絡傳輸?shù)臄?shù)據(jù)量,緩解了主從數(shù)據(jù)庫同步壓力,使得客戶端的超時異常從高峰時候的9%降低到了小于0.01%(低于萬分之一):

將DealModelTable中的銷量、價格、用戶評價等常變的信息單獨構(gòu)建一張數(shù)據(jù)表VariableDealModel;
同時在代碼中為銷量、價格、用戶評價等常變數(shù)據(jù)創(chuàng)建一個單獨的類VariableDealModel;
DealService對兩張表進行分別同步;
如果DealModelTable的記錄產(chǎn)生了更新,運行系統(tǒng)銷毀老的DealModel實體并創(chuàng)建新的DealModel實體;
如果只是VariableDealModel的記錄產(chǎn)生了更新,只對VariableDealModel的屬性進行更改。
缺點和優(yōu)點:
采用恒變分離模式,主要有三個缺點:

不符合面向?qū)ο蟮脑O計原則。原本概念上統(tǒng)一的實體被切分成多個實體,會給開發(fā)工程師帶來一些理解上的困難,因此增加維護成本。進一步而言,這會增加引入額外Bug的概率(實際上面向?qū)ο笾匀绱耸軞g迎的一個重要原因就是容易理解)。
增加了類不變量(Class invariant)的維護難度。很多情況下,Class invariant是通過語言所提供的封裝(Encapsulation)特性來維護的。當一個類變成多個類,Class invariant可能會被破壞。如果必須維護Class invariant,而這種Class invariant又發(fā)生在不同實體之間,那么往往是把不變的屬性從不變實體移到易變的實體中去。
一張數(shù)據(jù)庫表變成多張,也會增加維護成本。
在如下兩種場景下,恒變分離模式所帶來的好處有限:

易變數(shù)據(jù)導致的操作和傳輸并不頻繁,不是系統(tǒng)主要操作;
易變數(shù)據(jù)占整體數(shù)據(jù)的比例很高,杠桿效應不顯著,通過恒變分離模式不能根本性地解決系統(tǒng)性能問題。
總的來說,恒變分離模式非常容易理解,其應用往往需要滿足兩個條件:易變數(shù)據(jù)占整體數(shù)據(jù)比例很低(比例越低,杠桿效應越大)和易變數(shù)據(jù)所導致的操作又是系統(tǒng)的主要操作。在該場景下,如果系統(tǒng)性能已經(jīng)出現(xiàn)問題,犧牲一些可維護性就顯得物有所值。

大部分系統(tǒng)都是由多種類型的數(shù)據(jù)構(gòu)成,大多數(shù)數(shù)據(jù)類型的都包含易變、少變和不變的屬性。盲目地進行恒變分離會導致系統(tǒng)的復雜度指數(shù)級別的增加,系統(tǒng)變得很難維護,所以系統(tǒng)設計者必須在高性能和高維護性之間找到一個平衡點。作者的建議是:對于復雜的業(yè)務系統(tǒng),盡量按照面向?qū)ο蟮脑瓌t進行設計,只有在性能出現(xiàn)問題的時候才開始考慮恒變分離模式;而對于高性能,業(yè)務簡單的基礎數(shù)據(jù)服務,恒變分離模式應該是設計之初的一個重要原則。

數(shù)據(jù)局部性模式(Locality Pattern)
原理和動機:
數(shù)據(jù)局部性模式是多次請求杠桿反模式的針對性解決方案。在大數(shù)據(jù)和強調(diào)個性化服務的時代,一個服務消費幾十種不同類型數(shù)據(jù)的現(xiàn)象非常常見,同時每一種類型的數(shù)據(jù)服務都有可能需要一個大的集群(多臺機器)提供服務。這就意味著客戶端的一次請求有可能會導致服務端成千上萬次調(diào)用操作,很容易使系統(tǒng)進入多次請求杠桿反模式。在具體開發(fā)過程中,導致數(shù)據(jù)服務數(shù)量暴增的主要原因有兩個:1. 緩存濫用以及缺乏規(guī)劃,2. 數(shù)據(jù)量太大以至于無法在一臺機器上提供全量數(shù)據(jù)服務。數(shù)據(jù)局部性模的核心思想是合理組織數(shù)據(jù)服務,減少服務調(diào)用次數(shù)。具體而言,可以從服務端和客戶端兩個方面進行優(yōu)化。

服務端優(yōu)化方案的手段是對服務進行重新規(guī)劃。對于數(shù)據(jù)量太大以至于無法在一臺機器上存儲全量數(shù)據(jù)的場景,建議采用Bigtable或類似的解決方案提供數(shù)據(jù)服務。典型的Bigtable的實現(xiàn)包括Hbase、Google Cloud Bigtable等。實際上數(shù)據(jù)局部性是Bigtable的一個重要設計原則,其原理是通過Row key和Column key兩個主鍵來對數(shù)據(jù)進行索引,并確保同一個Row key索引的所有數(shù)據(jù)都在一臺服務器上面。通過這種數(shù)據(jù)組織方式,一次網(wǎng)絡請求可以獲取同一個Row key對應的多個Column key索引的數(shù)據(jù)。缺乏規(guī)劃也是造成服務數(shù)量劇增的一個重要原因。很多通過統(tǒng)計和挖掘出來的特征數(shù)據(jù)往往是在漫長的時間里由不同team獨立產(chǎn)生的。而對于每種類型數(shù)據(jù),在其產(chǎn)生之初,由于不確定其實際效果以及生命周期,基于快速接入原則,服務提供者往往會用手頭最容易實施的方案,例如采用Redis Cache(不加選擇地使用緩存會導致緩存濫用)。數(shù)據(jù)服務之間缺乏聯(lián)動以及缺乏標準接入規(guī)劃流程就會導致數(shù)據(jù)服務數(shù)量膨脹。數(shù)據(jù)局部性原則對規(guī)劃的要求,具體而言是指:1. 數(shù)據(jù)由盡可能少的服務器來提供,2. 經(jīng)常被一起使用的數(shù)據(jù)盡可能放在同一臺服務器上。

客戶端優(yōu)化有如下幾個手段:

本地緩存,對于一致性要求不高且緩存命中率較高的數(shù)據(jù)服務,本地緩存可以減少服務端調(diào)用次數(shù);
批處理,對于單機或者由等價的機器集群提供的數(shù)據(jù)服務,盡可能采用批處理方式,將多個請求合成在一個請求中;
客戶端Hash,對于需要通過Hash將請求分配到不同數(shù)據(jù)服務機器的服務,盡量在客戶端進行Hash,對于落入同一等價集群的請求采用批處理方式進行調(diào)用。
案例分析:
我們的挑戰(zhàn)來自于美團的推薦、個性化列表和個性化搜索服務。這些個性化系統(tǒng)需要獲取各種用戶、商家和團購信息。信息類型包括基本屬性和統(tǒng)計屬性。最初,不同屬性數(shù)據(jù)由不同的服務提供,有些是RPC服務,有些是Redis服務,有些是HBase或者數(shù)據(jù)庫,參見下圖:

通常而言,客戶端每個用戶請求都會觸發(fā)多個算法。一方面,每個算法都會召回幾十甚至幾百個團購或者商家ID,團購和商家基礎屬性被均勻地分配到幾十臺Redis里面(如下圖),產(chǎn)生了大量的Redis請求,極端情況下,一次客戶端請求所觸發(fā)的團購基礎數(shù)據(jù)請求就超過了上千次;另一方面,用戶特征屬性信息有十幾種,每種屬性也由單獨的服務提供,服務端網(wǎng)絡調(diào)用次數(shù)暴增。在一段時間里,很多系統(tǒng)都進入了多次請求杠桿反模式,Redis服務器的網(wǎng)卡經(jīng)常被打死,多次進行擴容,提高線程池線程數(shù)量,絲毫沒有改善。

在對系統(tǒng)進行分析之后,按照數(shù)據(jù)局部性模式的原則,我們采用了如下手段,徹底解決了系統(tǒng)多次請求杠桿反模式的問題:

采用大內(nèi)存服務器存儲所有的團購和商家基礎信息,每個算法只要一次網(wǎng)絡請求就可以獲取所有的信息;
服務端采用多線程方式提供服務,避免了Redis單一線程模式下單個請求慢所帶來的連鎖效應;
借鑒類似Bigtable的數(shù)據(jù)組織方式,將用戶的多種特征采用兩個維度(用戶維度和特征類型)進行索引,確保同一用戶的信息只存放在一臺機器上面,減少網(wǎng)絡調(diào)用數(shù)量。
缺點和優(yōu)點:
數(shù)據(jù)局部性模式并不適用于系統(tǒng)初級階段。在初級階段,最小可用原則往往是主要設計原則之一,出于兩方面的考慮:一方面,在初級階段,很難預測所要提供服務的數(shù)據(jù)是否有效而且能夠長期使用,以及未來的調(diào)用量;另一方面,在初級階段,工程師可能無法預測最終的調(diào)用模式,而不同的調(diào)用模式會導致數(shù)據(jù)局部性方案的設計不同。對于已經(jīng)大量使用的數(shù)據(jù)服務,采用數(shù)據(jù)局部性模式進行重構(gòu)必然要改變老的調(diào)用模式,這一方面會引入新的Bug,另一方面也意味著巨大的工作量。需要特別強調(diào)的是,數(shù)據(jù)處于系統(tǒng)的最底層,對于結(jié)構(gòu)復雜而又重要的數(shù)據(jù),重構(gòu)所帶來可靠性、一致性和工作量都是需要權(quán)衡的因素。對于請求量比較小的數(shù)據(jù)服務,即使一次請求會觸發(fā)嚴重的請求杠桿效應,但是如果原始觸發(fā)請求數(shù)量在可預見的時間內(nèi)沒有明顯變多的跡象,進行數(shù)據(jù)服務重構(gòu)可能得不償失。

數(shù)據(jù)局部性模式能夠解決多次請求杠桿反模式所導致的問題,但它并非大數(shù)據(jù)的產(chǎn)物,CPU、編譯器的設計理念里早就融入了該模式,所以很容易被工程師理解。雖然過度設計在系統(tǒng)初級階段是一個要盡量避免的事情,但是理解和掌握數(shù)據(jù)局部性模式對于設計出一個可擴展、可重用的系統(tǒng)有很大幫助。很多成熟的系統(tǒng)因為多次請求杠桿反模式而導致系統(tǒng)頻繁崩潰,理解數(shù)據(jù)局部性模式的原則有助于提高工程師分析解決問題的能力,而在確認了系統(tǒng)存在請求杠桿問題后,數(shù)據(jù)局部性原則是一件非常銳利的武器。

避免蚊子大炮模式(Avoiding Over-generalized Solution Pattern)
原理和動機:
“用大炮打蚊子”本來是大材小用的意思,但是細致想一想,用大炮打蚊子,成功率不高。對于開發(fā)工程師而言,一方面為了快速承接業(yè)務,按照方案復用原則,總是盡可能地利用現(xiàn)有系統(tǒng),這使得系統(tǒng)功能越來越強大;另一方面,提高系統(tǒng)的通用性或可重用性也是工程師們在設計系統(tǒng)的一個重要目標。隨著這兩個過程的相互獨立演化,采用通用方案解決特定問題的現(xiàn)象隨處可見,形象地說,這就像大炮打蚊子。大炮成本很高,蚊子的數(shù)量眾多,最終的結(jié)局往往是蚊子戰(zhàn)勝了大炮。

“避免蚊子大炮模式”是經(jīng)濟原則在運行時系統(tǒng)的運用,它要求采用最節(jié)省資源(CPU、內(nèi)存等)的方法來解決所面臨的問題,資源浪費會帶來未來潛在的風險。工程師接到一個需求的時候,需要思考的不僅僅是如何復用現(xiàn)有的系統(tǒng),減少開發(fā)時間,還需要考慮現(xiàn)有系統(tǒng)為處理每個新需求訪問所需運行時成本,以及新需求的預期訪問量。否則,不加辨別地利用現(xiàn)有系統(tǒng),不僅僅增大了重構(gòu)風險,還有可能交叉影響,對現(xiàn)有系統(tǒng)所支持的服務造成影響。從另外一個角度講,工程師在構(gòu)建一個可重用系統(tǒng)的時候,要明確其所不能解決和不建議解決的問題,而對于不建議解決的問題,在文檔中標明潛在的風險。

案例分析:
我們的挑戰(zhàn)是為移動用戶尋找其所在位置附近的商家信息。美團有非常完善的搜索系統(tǒng),也有資深的搜索工程師,所以一個系統(tǒng)需要查找附近的商家的時候,往往第一方案就是調(diào)用搜索服務。但是在美團,太多的服務有基于LBS的查詢需求,導致搜索請求量直線上升,這本來不屬于搜索的主營業(yè)務,在一段時間里面反倒成了搜索的最多請求來源。而搜索引擎在如何從幾十萬商家里面找最近的幾百商家方面的性能非常差,因此一段時間里,搜索服務頻繁報警。不僅僅搜索服務可用性受到了影響,所有依賴于LBS的服務的可用性都大大降低。

在對系統(tǒng)分析之后,我們認為更適合解決最短直線距離的算法應該是k-d tree,在快速實現(xiàn)了基于k-d tree的LBS Search解決方案之后,我們用4臺服務器輕松解決了30多臺搜索服務器無法解決的問題,平均響應時間從高峰時的100ms降低到300ns,性能取得了幾百倍的提高。

缺點和優(yōu)點:
避免蚊子大炮模式的問題和數(shù)據(jù)局部性模式類似,都與最小可用原則相沖突。在系統(tǒng)設計初級階段,尋求最優(yōu)方案往往意味著過度設計,整個項目在時間和成本變得不可控,而為每個問題去找最優(yōu)秀的解決方案是不現(xiàn)實的奢求。最優(yōu)化原則的要求是全面的,不僅僅要考慮的運行時資源,還需要考慮工程師資源和時間成本等,而這些點往往相互矛盾。在如下情況下,避免蚊子大炮模式所帶來的好處有限:在可預見的未來,某個業(yè)務請求量非常小,這時候花大量精力去找最優(yōu)技術(shù)方案效果不明顯。

在設計階段,避免蚊子大炮模式是一個需要工程師去權(quán)衡的選擇,需要在開發(fā)成本和系統(tǒng)運行成本之間保持一個平衡點。當很多功能融入到一個通用系統(tǒng)里而出現(xiàn)性能問題的時候,要拆分出來每一個功能點所造成的影響也不是件輕易的事情,所以采用分開部署而共用代碼庫的原則可以快速定位問題,然后有針對性地解決“蚊子大炮”問題。總的來說,在設計階段,避免蚊子大炮模式是工程師們進行分析和設計的一個重要準則,工程師可以暫時不解決潛在的問題,但是一定要清楚潛在的危害。構(gòu)建可重用系統(tǒng)或方案,一定要明確其所不能解決和不建議解決的問題,避免過度使用。

實時離線分離模式(Sandbox Pattern)
原理和動機:
本模式的極端要求是:離線服務永遠不要調(diào)用實時服務。該模式比較簡單也容易理解,但是,嚴格地講它不是一種系統(tǒng)設計模式,而是一種管理規(guī)范。離線服務和在線服務從可用性、可靠性、一致性的要求上完全不同。原則上,工程師在編寫離線服務代碼的時候,應該遵循的就是離線服務編程規(guī)范,按照在線服務編程規(guī)范要求,成本就會大大提高,不符合經(jīng)濟原則;從另外一方面講,按照離線服務的需求去寫在線服務代碼,可用性、可靠性、一致性等往往得不到滿足。

具體而言,實時離線分離模式建議如下幾種規(guī)范:

如果離線程序需要訪問在線服務,應該給離線程序單獨部署一套服務;
類似于MapReduce的云端多進程離線程序禁止直接訪問在線服務;
分布式系統(tǒng)永遠不要直接寫傳統(tǒng)的DBMS。
案例分析:
因為違反實時離線分離模式而導致的事故非常常見。有一次,因為一個離線程序頻繁的向Tair集群寫數(shù)據(jù),每一次寫10M數(shù)據(jù),使得整個Tair集群宕機。另一次,因為Storm系統(tǒng)直接寫MySQL數(shù)據(jù)庫導致數(shù)據(jù)庫連接數(shù)耗盡,從而使在線系統(tǒng)無法連接數(shù)據(jù)庫。

缺點和優(yōu)點:
為了實現(xiàn)實時在線分離,可能需要為在線環(huán)境和離線環(huán)境單獨部署,維護多套環(huán)境所帶來運維成本是工程師需要考慮的問題。另一方面,在線環(huán)境的數(shù)據(jù)在離線環(huán)境中可能很難獲取,這也是很多離線系統(tǒng)直接訪問在線系統(tǒng)的原因。但是,遵從實時離線分離模式是一個非常重要的安全管理準則,任何違背這個準則的行為都意味著系統(tǒng)性安全漏洞,都會增大線上故障概率。

降級模式(Degradation Pattern)
原理和動機:
降級模式是系統(tǒng)性能保障的最后一道防線。理論上講,不存在絕對沒有漏洞的系統(tǒng),或者說,最好的安全措施就是為處于崩潰狀態(tài)的系統(tǒng)提供預案。從系統(tǒng)性能優(yōu)化的角度來講,不管系統(tǒng)設計地多么完善,總會有一些意料之外的情況會導致系統(tǒng)性能惡化,最終可能導致崩潰,所以對于要求高可用性的服務,在系統(tǒng)設計之初,就必須做好降級設計。根據(jù)作者的經(jīng)驗,良好的降級方案應該包含如下措施:

在設計階段,確定系統(tǒng)的開始惡化數(shù)值指標(例如:響應時間,內(nèi)存使用量);
當系統(tǒng)開始惡化時,需要第一時間報警;
在收到報警后,或者人工手動控制系統(tǒng)進入降級狀態(tài),或者編寫一個智能程序讓系統(tǒng)自動降級;
區(qū)分系統(tǒng)所依賴服務的必要性,一般分為:必要服務和可選服務。必要服務在降級狀態(tài)下需要提供一個快速返回結(jié)果的權(quán)宜方案(緩存是常見的一種方案),而對于可選服務,在降級時系統(tǒng)果斷不調(diào)用;
在系統(tǒng)遠離惡化情況時,需要人工恢復,或者智能程序自動升級。
典型的降級策略有三種:流量降級、效果降級和功能性降級。流量降級是指當通過主動拒絕處理部分流量的方式讓系統(tǒng)正常服務未降級的流量,這會造成部分用戶服務不可用;效果降級表現(xiàn)為服務質(zhì)量的降級,即在流量高峰時期用相對低質(zhì)量、低延時的服務來替換高質(zhì)量、高延時的服務,保障所有用戶的服務可用性;功能性降級也表現(xiàn)為服務質(zhì)量的降級,指的是通過減少功能的方式來提高用戶的服務可用性。效果降級和功能性降級比較接近,效果降級強調(diào)的是主功能服務質(zhì)量的下降,功能性降級更多強調(diào)的是輔助性功能的缺失。做一個類比如下:計劃將100個工程師從北京送到夏威夷度假,但是預算不夠。采用流量降級策略,只有50工程師做頭等艙去了夏威夷度假,其余工程師繼續(xù)編寫程序(這可不好);效果降級策略下,100個工程師都坐經(jīng)濟艙去夏威夷;采用功能性降級策略,100個工程師都坐頭等艙去夏威夷,但是飛機上不提供食品和飲料。

案例分析:
我們的系統(tǒng)大量使用了智能降級程序。在系統(tǒng)惡化的時候,智能降級程序自動降級部分流量,當系統(tǒng)恢復的時候,智能降級程序自動升級為正常狀態(tài)。在采用智能降級程序之前,因為系統(tǒng)降級問題,整體系統(tǒng)不可用的情況偶爾發(fā)生。采用智能降級程序之后,基本上沒有因為性能問題而導致的系統(tǒng)整體不可用。我們的智能降級程序的主要判定策略是服務響應時間,如果出現(xiàn)大量長時間的響應異?;虺瑫r異常,系統(tǒng)就會走降級流程,如果異常數(shù)量變少,系統(tǒng)就會自動恢復。

缺點和優(yōu)點:
為了使系統(tǒng)具備降級功能,需要撰寫大量的代碼,而降級代碼往往比正常業(yè)務代碼更難寫,更容易出錯,所以并不符合奧卡姆剃刀原則。在確定使用降級模式的前提下,工程師需要權(quán)衡這三種降級策略的利弊。大多數(shù)面向C端的系統(tǒng)傾向于采用效果降級和功能性降級策略,但是有些功能性模塊(比如下單功能)是不能進行效果和功能性降級的,只能采用流量降級策略。對于不能接受降級后果的系統(tǒng),必須要通過其他方式來提高系統(tǒng)的可用性。

總的來說,降級模式是一種設計安全準則,任何高可用性要求的服務,必須要按照降級模式的準則去設計。對于違背這條設計原則的系統(tǒng),或早或晚,系統(tǒng)總會因為某些問題導致崩潰而降低可用性。不過,降級模式并非不需要成本,也不符合最小可用原則,所以對于處于MVP階段的系統(tǒng),或者對于可用性要求不高的系統(tǒng),降級模式并非必須采納的原則。

其他性能優(yōu)化建議:
對于無法采用系統(tǒng)性的模式方式講解的性能優(yōu)化手段,作者也給出一些總結(jié)性的建議:

刪除無用代碼有時候可以解決性能問題,例如:有些代碼已經(jīng)不再被調(diào)用但是可能被初始化,甚至占有大量內(nèi)存;有些代碼雖然在調(diào)用但是對于業(yè)務而言已經(jīng)無用,這種調(diào)用占用CPU資源。
避免跨機房調(diào)用,跨機房調(diào)用經(jīng)常成為系統(tǒng)的性能瓶頸,特別是那些偽batch調(diào)用(在使用者看起來是一次性調(diào)用,但是內(nèi)部實現(xiàn)采用的是順序單個調(diào)用模式)對系統(tǒng)性能影響往往非常巨大
。


總結(jié)
Christopher Alexander曾說過:"Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice" 。 盡管Christopher Alexander指的是建筑模式,軟件設計模式適用,基于同樣的原因,性能優(yōu)化模式也適用。每個性能優(yōu)化模式描述的都是工程師們?nèi)粘9ぷ髦薪?jīng)常出現(xiàn)的問題,一個性能優(yōu)化模式可以解決確定場景下的某一類型的問題。所以要理解一個性能優(yōu)化模式不僅僅要了解性能模式的所能解決的問題以及解決手段,還需要清楚該問題所發(fā)生的場景和需要付出的代價。

最后,本文所描述的性能優(yōu)化模式只是作者的工作經(jīng)驗總結(jié),都是為了解決由以下三種情況所造成的性能問題:1. 日益增長的用戶數(shù)量,2. 日漸復雜的業(yè)務,3. 急劇膨脹的數(shù)據(jù),但是這些遠非該領域里面的所有模式。對于文章中提到的其他性能優(yōu)化建議,以及現(xiàn)在和將來可能碰到的性能問題,作者還會不斷抽象,在未來總結(jié)出更多的模式。性能問題涉及領域非常廣泛,而模式是一個非常好的講解性能問題以及解決方案的方式,作者有理由相信,無論是在作者所從事的工作領域里面還是在其他的領域里面,新的性能優(yōu)化模式會不斷涌現(xiàn)。希望通過本文的講述,對碰到同樣問題的工程師們有所幫助,同時也拋磚引玉,期待出現(xiàn)更多的基于模式方式講解性能優(yōu)化的文章。

標簽:郴州 克拉瑪依 昌都 烏海 上饒 萍鄉(xiāng) 黔南 曲靖

巨人網(wǎng)絡通訊聲明:本文標題《美團點評對于網(wǎng)站性能優(yōu)化的經(jīng)驗總結(jié)》,本文關(guān)鍵詞  美團,點評,對于,網(wǎng)站,性能,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡,涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《美團點評對于網(wǎng)站性能優(yōu)化的經(jīng)驗總結(jié)》相關(guān)的同類信息!
  • 本頁收集關(guān)于美團點評對于網(wǎng)站性能優(yōu)化的經(jīng)驗總結(jié)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    国语对白做受xxxxx在线中国| 九七伦理97伦理| 欧美日韩国产影片| 日韩精品999| 亚洲欧美一区二区三区在线观看| 亚洲国产婷婷香蕉久久久久久| 久久亚洲精品石原莉奈| 色悠悠久久88| 欧美日韩国产精品一卡| 9自拍视频在线观看| 久一区二区三区| 亚洲 小说 欧美 激情 另类| 中文字幕日韩一区二区三区不卡| 国产日韩精品推荐| 亚洲在线精品视频| 69夜色精品国产69乱| 日本精品一区二区三区四区的功能| 国产精品我不卡| 丝袜人妻一区二区三区| 凹凸av导航大全精品| 色综合久久中文综合久久牛| 免费看欧美黑人毛片| 成人短视频在线看| 亚洲五月婷婷| 中文字幕一区二区三区四区| 久久99精品国产麻豆不卡| 暖暖在线中文免费日本| 无码国产精品久久一区免费| 中文在线а天堂av| 欧美性猛交xxxxx少妇| 老司机在线精品视频| 特黄特黄一级片| 99re成人精品视频| 欧美精品二区三区四区免费看视频| 美女又黄又免费| 中国日韩欧美久久久久久久久| 成人免费视频97| 三上悠亚影音先锋| 久久久久久香蕉网| 91嫩草在线播放| 啪啪av大全导航福利综合导航| 日韩三级视频在线播放| 精品视频一区二区三区四区| 日韩成人动漫| 日本va欧美va国产激情| 亚洲精品乱码久久久久久金桔影视| 污污视频网站免费观看| 影音先锋导航| 黄页网站大全一区二区| 欧美影院午夜播放| 欧美日韩综合一区二区三区| 欧美人与禽猛交乱配视频| 日韩av网站在线| 欧美一区二区三区久久综合| 亚洲欧洲日韩综合一区二区| 欧美中文字幕视频| 国产精品美女一区二区三区四区| 激情黄产视频在线免费观看| 久久99国产精品自在自在app| 高h震动喷水双性1v1| 在线观看国产精品入口| jiuse.com91视频| 色婷婷av一区二区三区在线观看| 麻豆福利视频| 91视频免费在线看| 日本免费在线一区| 久久97人妻无码一区二区三区| 免费看成人a| 在线观看亚洲一区| 国产欧美日韩精品一区二区免费| 韩国成人动漫| 中文字幕精品在线| 亚洲国产精品99久久久久久久久| 亚洲免费一在线| 国产视频一二区| 国产精品theporn动漫| 国内精品国产成人国产三级粉色| 精品免费av在线| 精品街拍一区二区| 亚洲第一精品影视| av在线加勒比| baoyu135国产精品免费| 日韩毛片在线免费看| 偷拍视屏一区| 亚洲欧洲第一视频| 日韩免费电影| 蜜桃视频在线观看视频| 国产在线播放精品| 性生交生活影碟片| 国产精品一区二区在线看| 日韩欧美亚洲区| 国产免费一区二区三区视频| 欧美亚洲国产日韩2020| 久久成年人免费电影| 911国产网站尤物在线观看| 男人添女荫道口图片| 日韩国产精品一区二区三区| 欧美—级在线免费片| 天天视频一区二区三区| 亚洲免费av网址| 九九热99视频| 在线观看免费黄色网址| 蜜桃视频在线观看成人| 久久影院视频免费| 37pao成人国产永久免费视频| 自拍日韩亚洲一区在线| 黄色一区二区三区四区| 国产精品嫩草视频| 中文字幕高清在线免费播放| 国产精华一区二区三区| 欧美人妇做爰xxxⅹ性高电影| 亚洲激情不卡| 精品国产aⅴ一区二区三区东京热| 欧美大片在线免费观看| 日本婷婷久久久久久久久一区二区| 天堂在线观看一卡二卡三卡四卡| 精品国产一级毛片| 亚洲日本aⅴ片在线观看香蕉| 高清性色生活片在线观看| 天天影视欧美综合在线观看| 久久久久久福利| 欧美日韩高清一区二区| 欧美破处大片在线视频| 男女h黄动漫啪啪无遮挡软件| 91国产在线免费观看| 亚洲第一福利视频| 性直播体位视频在线观看| 青草伊人久久| 国产精品入口日韩视频大尺度| 熟妇人妻无乱码中文字幕真矢织江| 欧美亚洲国产精品久久| 亚洲欧美日韩不卡一区二区三区| 亚洲精品福利网站| 日本高清成人vr专区| 久久久久久久中文| 日韩大片b站免费观看直播| 三级视频网站在线| 久久久水蜜桃av免费网站| 一级免费在线观看| 国产精品手机视频| 夜夜嗨av一区二区三区| 精品久久久久久久久久久| 天天综合网天天做天天受| 国产一级一级国产| 国产麻豆综合视频在线观看| 视频在线一区二区| 青春草视频在线观看| 成人综合色站| 69夜色精品国产69乱| 筱崎爱全乳无删减在线观看| 国产精品极品尤物在线观看| 国产亚洲精品日韩| 男女啪啪无遮挡| 国产在线麻豆精品观看| 无套内谢丰满少妇中文字幕| 午放福利视频在线播放| 波多野结衣视频在线观看| 亚洲国产精品一区二区www| 丁香花高清视频完整版在线观看| 国产极品jizzhd欧美| 五月天男人天堂| 亚洲宅男网av| 欧美激情视频二区| 黄色成人免费网| 日韩欧美在线视频播放| 在线日韩视频| 欧美人与禽zozzo禽性配| 91麻豆精品国产91久久综合| 漂亮人妻被中出中文字幕| 夜夜操 天天摸| 欧美日韩五月天| 国产精品一区二区6| 久久福利网址导航| 日韩porn| 国产在线观看一区二区| 国产精品久久午夜夜伦鲁鲁| 黄色在线网站噜噜噜| 欧美一区二区三区高清视频| 亚洲视频欧洲视频| 久久久成人网| 红杏一区二区三区| 大陆极品少妇内射aaaaa| 水蜜桃久久夜色精品一区的特点| 精品女人视频| 国产成人黄色av| 免费精品一区二区三区在线观看| 国产午夜一区二区三区| 天天干天天干天天干天天干天天干| 人妻精品无码一区二区三区| 久久国产精品无码网站| 久久精品青草| 日韩激情视频在线| 亚洲一区二区三区四区在线免费观看| 精品国产av 无码一区二区三区| 国产精品一区三区在线观看| 蜜臀av一区二区| 欧美激情一区二区三区四区| 美女大黄三级视频在线观看| 欧美午夜精品一区二区蜜桃| 国产成人麻豆精品午夜在线| 亚洲国产成人综合| 91免费网站视频| 蜜桃视频在线观看www社区| 亚洲网友自拍| 欧美特黄一级| 国产又粗又猛又爽又黄91精品| 欧美日韩国内自拍| 国内精品国产成人国产三级粉色| 国产精品高精视频免费| 中文字幕一区二区三区四区五区人| 亚洲欧美综合国产精品一区| 久操视频免费在线观看| 国产精品国产精品国产专区不卡| 一本久久知道综合久久| 成人黄色大片在线观看| 吞精囗交69激情欧美| 国产二区三区在线| 色综合天天综合网国产成人综合天| 欧美绝品在线观看成人午夜影视| 亚洲欧美激情在线| 国产成人精品免费在线| 私人影视中文字幕| 欧美极品一区二区三区| 免费观看久久久久| 精品成人av| 两个人看的免费完整在线观看| 日韩av一级电影| 99热这里只有精品5| 国产视频精品网| 在线不卡日本v二区707| 国产视频一区在线观看一区免费| 91在线免费观看网站| 亚洲欧美日韩国产成人综合一二三区| 婷婷国产成人久久精品激情| 欧美毛片免费观看| 国产美女永久免费| 欧美色图第二页| 日韩丝袜美女视频| 欧美另类videoxo高潮| 国产日韩欧美在线观看| 国产成人在线中文字幕| 网红女主播少妇精品视频| 日韩成人精品视频在线观看| av资源网在线观看| 日韩精品久久一区| 亚洲国产成人私人影院tom| 17婷婷久久www| 欧美三级电影精品| 国产69精品久久久久9999apgf| 99riav久久精品riav| 欧美中文娱乐网| 3d性欧美动漫精品xxxx软件| 欧洲grand老妇人| 国产一区二区0| 青青草视频在线观看免费| 午夜精品一区二区三区视频| 日韩视频在线观看视频| 天天色天天综合网| 亚州欧美日韩中文视频| 91亚洲国产高清| 91麻豆精品国产| 欧美国产精品一区二区三区| 亚洲伊人春色| chinese少妇国语对白| 欧美激情小视频| 国精产品一区一区三区四川| 欧美日韩国产在线| 欧美香蕉视频| 日本免费观看网站| 91精品一区二区三区久久久久久| 国产亚洲精品一区二区在线观看| 欧美猛烈性xbxbxbxb| 日本亚洲欧美美色| 国产亚洲永久域名| 亚洲精选视频在线| 日韩不卡免费高清视频| 国产999精品久久久久久| 蜜臀av一级做a爰片久久| 欧美热在线视频精品999| 精品人妻互换一区二区三区| 在线亚洲人成| 超碰在线国产97| 成人在线免费播放视频| 在线黄色免费看| 88久久精品| 日韩系列在线| 天天堂资源网在线观看免费视频| 国产xxxxhd| 岳毛多又紧做起爽| 国产精品白嫩美女在线观看| 九九九九热精品免费视频| 国精品无码一区二区三区| 日本在线视频中文有码| 久久久久久久电影| 成人日韩在线观看| 亚洲欧美日韩在线| 91视频最新入口| 国产小视频免费观看| 国产中文字幕二区| 日韩影院精彩在线| 黄片毛片在线看| 日韩午夜激情av| 日韩理论片网站| 香蕉视频在线播放| 免费a漫导航| 国产福利资源一区| 欧美日韩一区二区区| 91黄色在线观看| 日韩欧美国产综合在线| 欧美黑人国产人伦爽爽爽| 国产高清在线观看免费不卡| 男女一区二区三区| 波多野结衣综合网| 无套内谢大学处破女www小说| 日韩欧美手机在线| 人妻va精品va欧美va| 国产在线播精品第三| 午夜影院免费版| 久久亚洲精品中文字幕蜜潮电影| 国产精品豆花视频| 黄页网站在线看| 亚洲天堂男人的天堂| 欧美视频一区二区三区…| 久久伊人精品| 亚洲精品国产熟女久久久| 91精品久久久久久久久青青| 日本一线产区和二线产区| 日本免费中文字幕在线|