我我的有收藏感興趣的技術連接的習慣,最近太忙,沒太多時間看收藏的技術貼,可貴今天有空,看了篇美團技術團隊的關於性能優化的內容,html
感受不錯,將其中的一些觀點和方法作了總結概括,其中還摻雜一些我的的思考,寫下這篇博客,以備往後查閱。。。java
原文連接:性能優化模式數據庫
一、性能優化的三個方面編程
一、下降響應時間設計模式
二、提升系統吞吐量緩存
三、提升服務的可用性安全
三者的關係:在某些場景下互相矛盾,不可兼得性能優化
2、性能優化面臨的挑戰restful
一、日益增加的用戶數量網絡
二、愈來愈複雜的業務
三、急劇膨脹的數據
3、性能優化的目標
在保持和下降系統99%RT的前提下,不斷提升系統吞吐量,提升流量高峯時期的服務可用性。
4、本文涉及的幾種原則
一、最小可用原則
也稱爲快速接入原則,有兩個關注點:
①、快速接入,快速完成;
②、實現核心功能可用;
目標:經過下降開發測試周期,增長試錯機會,快速接入而實現風險可控;
注意:這並不意味着成本的下降,而須要爲重構作好準備;
相關閱讀:在產品設計上有一個名詞叫作MVP,即最小可行性產品,這一觀點在《人人都是產品經理1.0記念版》一書中有相關章節描述。
二、經濟原則
軟件項目生命週期包括:預研、設計、開發、測試、運行、維護等階段。
上面提到的最小可用原則主要運用在預研階段,而經濟原則既能夠用在整個軟件生命週期裏,或只關注某一個或者幾個階段;
例如:運行時經濟原則須要考慮的系統成本包括單次請求的CPU、內存、網絡、磁盤消耗等;
設計階段的經濟原則要求避免過分設計;開發階段的經濟原則可能關注代碼複用,工程師資源複用等。
三、代碼複用原則
該原則分兩個層次:
①、使用已有的解決方案或調用已存在的共享庫(Shared Library),也稱爲方案複用;
②、直接在現有的代碼庫中開發,也稱之爲共用代碼庫;
方案複用原則出發點就是最大限度地利用手頭已有的解決方案,即便這個方案並很差;方案的形式能夠是共享庫,也能夠是已存在的服務。
優勢:提升生產效率;
相似:方案複用相似於微服務架構(Microservice Architecture),restful風格,設計出可重用性的組件或服務,經過分層組織各層組件來實現良好的架構。
共用代碼庫原則要求代碼庫中的全部功能編譯時可見,新功能代碼能夠無邊界的調用老代碼;另外,原代碼庫已存在的各類運行、編譯、測試、配置環境可複用。
優勢:
①、充分利用代碼庫中已有的基礎設施,快速接入新業務;
②、直接調用原代碼中的基礎功能,避免網絡或進程間調用開銷,性能更佳;
相似:共用代碼庫和總體架構(Monolithic Architecture)很接近,它但願儘量在一套代碼庫中開發,經過直接調用代碼中的基礎功能實現性能優化和快速迭代。
四、奧卡姆剃刀原則
通常狀況下,系統的代碼量會隨着功能的增長而變多,健壯性有時候也須要經過編寫異常處理代碼來實現,異常考慮越全面,異常處理的代碼量就越大。
隨着代碼量的增大,引入BUG的機率也越大,系統也就越不健壯。從另外一個方面來講,異常流程處理代碼也要考慮健壯性的問題,這就造成了無限循環。
奧卡姆剃刀原則要求:
①、一個功能模塊如非必要,就不要;
②、一段代碼如非必寫,則不寫;
區別:最小可用原則主要運用於產品MVP階段,奧卡姆剃刀原則主要指系統設計和代碼編寫兩個方面,這是徹底不一樣的兩個概念;
MVP包含系統設計和代碼編寫,但同時,系統設計和代碼編寫也能夠發生在成熟系統的迭代階段。
五、性能惡化模式
性能優化的目標之一就是避免系統進入性能惡化模式;
不一樣性能優化模式多是避免同一種性能惡化模式;
同一種性能優化模式可能在不一樣階段避免不一樣的性能惡化模式;
常見的性能惡化模式
1、長請求擁塞惡化模式
介紹:單次請求時延變長致使系統性能惡化甚至崩潰的模式;
典型場景:複雜的業務場景依賴於多個服務,其中某個服務的響應時間變長,隨之系統總體響應時間變長,進而出現CPU、內存、Swap報警;
具體表現:被依賴服務可用性下降、大量RT變長致使線程堆積、內存使用增長,頻繁GC,RT時間變得更長,最終致使服務完全崩潰;
表現方式:
線程數變多致使縣城之間CPU資源競爭,反過來進一步延長了單次請求時間;
線程數增多及線程中緩存變大,內存消耗加重,java語言的服務會頻繁的full GC(垃圾回收),致使單次請求時間變得更長;
內存使用變多,使操做系統內存不足,必須使用Swap(內存)交換,可能致使服務崩潰;
惡化流程圖以下:
2、反覆緩存惡化模式
介紹:爲下降響應時間,加緩存是種頗有效的方式,緩存數據越多,命中率越高,ART就越快;
典型場景:流量高峯衝擊時,系統內存使用增多,出發了JVM進行full GC,進而致使大量緩存被釋放,而大量請求又使得緩存被迅速填滿,
反覆緩存致使頻繁的full GC,頻繁的full GC每每致使系統性能急劇惡化;
緣由:反覆緩存所致使性能惡化的緣由是無節制的使用緩存;
指導原則:全局考慮,精細規劃,確保系統徹底緩存狀況下系統仍然不會頻繁full GC,嚴格控制緩存大小,甚至廢除緩存;
解決措施:線性的增長機器和提升機器的內存大小,能夠顯著減小系統崩潰的機率;
惡化流程圖以下:
3、屢次請求槓桿惡化模式
介紹:客戶端一次點擊每每會出發屢次服務端請求,每一個服務端請求觸發更多底層服務請求,請求層級越多,槓桿效應越大;
典型場景:屢次請求槓桿模式下運行的分佈式系統,深層次的服務需處理大量請求,容易成爲系統瓶頸;
另外大量請求會給網絡帶來巨大壓力,可能會成爲系統完全崩潰的導火索;
表現方式:性能惡化和流量之間每每遵循指數曲線關係,且線性增長機器解決不了可用性問題;
惡化流程圖以下:
6、性能優化模式
1、水平分割模式
動機:典型的服務端流程包含四個環節:接受請求、獲取數據、處理數據、返回結果,大部分耗時長的服務發生在中間兩個環節。
若是服務處理請求採用的是串行調用,那麼其累加效應會極大延長單次請求RT,這就增長了系統進入長請求擁塞惡化模式的機率,進一步的下降系統性能。
若是能對不一樣的業務請求並行處理,請求總耗時就會大大下降。以下圖所示:
Client須要對三個服務進行調用,若是採用順序調用模式,系統的響應時間爲18ms,而採用並行調用只須要7ms。
關於client和service之間的鏈接機制,具體可參考我以前的博客:http鏈接管理
水平分割模式原理:
將整個請求流程切分爲必須相互依賴的多個Stage,每一個Stage包含相互獨立的多種業務處理。切分以後,水平分割模式串行處理多個Stage,可是在Stage內部並行處理。
一次請求總耗時等於各個Stage耗時總和,每一個Stage所耗時間等於該Stage內部最長的業務處理時間。
優化關鍵點:減小Stage數量和下降每一個Stage耗時。
優勢:
①、下降系統的平均響應時間和TP95響應時間,以及流量高峯時系統崩潰的機率。須要明白的一點:有時候,即便少許的並行化也能夠顯著提升總體性能。
②、代碼重構比較複雜,可是水平切割模式很是容易理解,只要熟悉系統的業務,識別出能夠並行處理的流程,就可以進行水平切割;
③、對於新系統而言,若是存在可預見的性能問題,把水平分割模式做爲一個重要的設計理念將會大大地提升系統的可用性、下降系統的重構風險;
④、有效、容易識別和理解;
二、垂直分割模式
動機:不一樣業務功能並存於同一個運行系統裏面意味着資源共享,同時也意味着資源使用衝突。
不一樣業務功能,不管其調用量多小,都有一些內存開銷。對於存在大量緩存的業務功能,數量的增長會極大地提升內存消耗,從而增大系統進入反覆緩存反模式的機率。
思路:將系統按照不一樣的業務功能進行分割,主要有兩種分割模式:部署垂直分割和代碼垂直分割。
部署垂直分割:按照可用性要求將系統進行等價分類,不一樣可用性業務部署在不一樣機器上,高可用業務單獨部署;
代碼垂直分割:讓不一樣業務系統不共享代碼,完全解決系統資源使用衝突問題。
缺點:
①、增長了維護成本。一方面代碼庫數量增多提升了開發工程師的維護成本,另外一方面,部署集羣的變多會增長運維工程師的工做量;
②、代碼不共享所致使的重複編碼工做。
優勢:
①、簡單有效,特別適用於系統已經出現問題而又須要快速解決的場景;
②、部署層次的分割既安全又有效(大部分狀況下,即便不增長機器,僅經過部署分割,系統總體吞吐量和可用性都有可能提高);
注意點:對於代碼層次的分割,開發工程師須要在業務承接效率和系統可用性上面作一些折衷考慮。
三、恆變分離模式
原理:基於性能的設計要求變化的數據和不變的數據分開,而在面向對象設計中,爲了便於對一個對象有總體的把握,
緊密相關的數據集合每每被組裝進一個類,存儲在一個數據庫表,即便有部分數據冗餘。
不少系統的主要工做是處理變化的數據,若是變化的數據和不變的數據被緊密組裝在一塊兒,系統對變化數據的操做將引入額外的開銷。
而若是易變數據佔總數據比例很是小,這種額外開銷將會經過槓桿效應惡化系統性能。
分離易變和恆定不變的數據在對象建立、內存管理、網絡傳輸等方面都有助於性能提升。
缺點:
①、不符合面向對象的設計原則;
②、增長了類不變量的維護難度;
③、一張數據庫表變成多張,增長維護成本。
恆變分離模式須要知足兩個條件:
①、易變數據佔總體數據比例很低(比例越低,槓桿效應越大);
②、易變數據所致使的操做又是系統的主要操做;
分離原則:
對於複雜的業務系統,儘可能按照面向對象的原則進行設計,只有在性能出現問題的時候纔開始考慮恆變分離模式;
而對於高性能,業務簡單的基礎數據服務,恆變分離模式應該是設計之初的一個重要原則。
四、數據局部性模式
動機:數據局部性模式是屢次請求槓桿反模式的針對性解決方案。
典型場景:大數據和強調個性化服務的時代,一個服務消費幾十種不一樣類型數據的現象很是常見,同時每種類型數據服務均可能須要一個大的集羣提供服務。
這就意味着客戶端的一次請求有可能會致使服務端成千上萬次調用操做,很容易使系統進入屢次請求槓桿反模式。
數據服務數量暴增的緣由:
①、緩存濫用以及缺少規劃,
②、數據量太大以致於沒法在一臺機器上提供全量數據服務,數據局部性模的核心思想是合理組織數據服務,減小服務調用次數。
優化方案:
①、對服務進行從新規劃;
②、對客戶端進行優化,包括:
本地緩存,對於一致性要求不高且緩存命中率較高的數據服務,本地緩存能夠減小服務端調用次數;
批處理,對於單機或者由等價的機器集羣提供的數據服務,儘量採用批處理方式,將多個請求合成在一個請求中;
客戶端Hash,對須要經過Hash將請求分配到不一樣數據服務機器的服務,儘可能在客戶端Hash,對於落入同一等價集羣的請求採用批處理方式進行調用。
五、實時離線分離模式
該模式的極端要求:離線服務永遠不要調用實時服務,嚴格地講它不是一種系統設計模式,而是一種管理規範。
離線服務和在線服務從可用性、可靠性、一致性的要求上徹底不一樣。
原則上,應該遵循的就是離線服務編程規範,按照在線服務編程規範要求,成本就會大大提升,不符合經濟原則;
從另一方面講,按照離線服務的需求去寫在線服務代碼,可用性、可靠性、一致性等每每得不到知足。
具體而言,實時離線分離模式建議以下幾種規範:
若是離線程序須要訪問在線服務,應該給離線程序單獨部署一套服務;
相似於MapReduce的雲端多進程離線程序禁止直接訪問在線服務;
分佈式系統永遠不要直接寫傳統的DBMS。
優缺點:
須要爲在線環境和離線環境單獨部署,維護多套環境所帶來運維成本;
在線環境的數據在離線環境中可能很難獲取;;
BUT:聽從實時離線分離模式是一個很是重要的安全管理準則,任何違背這個準則的行爲都意味着系統性安全漏洞,都會增大線上故障機率。
六、降級模式
降級模式是系統性能保障的最後一道防線。理論上講,不存在絕對沒有漏洞的系統,或者說,最好的安全措施就是爲處於崩潰狀態的系統提供預案。
從系統性能優化的角度來說,無論系統設計地多麼完善,總會有一些意料以外的狀況會致使系統性能惡化,最終可能致使崩潰。
對於要求高可用性的服務,在系統設計之初,就必須作好降級設計。
良好的降級方案應該包含以下措施:
①、在設計階段,肯定系統的開始惡化數值指標(例如:響應時間,內存使用量);
②、當系統開始惡化時,須要第一時間報警;
③、在收到報警後,或者人工手動控制系統進入降級狀態,或者編寫一個智能程序讓系統自動降級;
典型的降級策略有三種:流量降級、效果降級和功能性降級。
流量降級是指當經過主動拒絕處理部分流量的方式讓系統正常服務未降級的流量,這會形成部分用戶服務不可用;
效果降級表現爲服務質量的降級,即在流量高峯時期用相對低質量、低延時的服務來替換高質量、高延時的服務,保障全部用戶的服務可用性;
功能性降級也表現爲服務質量的降級,指經過減小功能的方式來提升用戶的服務可用性。
區別:效果降級強調的是主功能服務質量的降低,功能性降級更多強調的是輔助性功能的缺失。
優缺點:
在肯定使用降級模式的前提下,工程師須要權衡這三種降級策略的利弊;
對於不能接受降級後果的系統,必需要經過其餘方式來提升系統的可用性;
總結:降級模式是一種設計安全準則,任何高可用性要求的服務,必需要按照降級模式的準則去設計。
對於處於MVP階段的系統,或者對於可用性要求不高的系統,降級模式並不是必須採納的原則。