
一個剛上線的IT系統,往往負載壓力不大,所以不會存在什么性能問題,這時,人們大多只關心系統的功能性和用戶體驗,但是,隨著時間推移,用戶量和資料量都比剛上線的時候要多很多,高并發和大資料場景下,系統遇到性能瓶頸,持續不能改善最終導致系統崩潰,這對于做C端的開發人員應該更加深有體會,
系統經常回應慢,甚至宕機,這對用戶造成很差的用戶體驗,更有嚴重的,會導致大批用戶流失、業務停擺等,造成不可挽回的損失,因此,持續運營的系統,是非常有必要進行性能優化的作業,對于性能優化,已經有很多可行且成熟的技術方案,下面就聊聊,旨在大概了解,不展開詳說,
性能監控
具體問題具體分析,解決性能問題總得要知道系統哪里遇到性能瓶頸,往大的來說,性能問題無非就是服務器的CPU、記憶體、資料庫、IO、網路等出了問題,往小的來說,就是程式的某個方法或者某條SQL陳述句執行比較慢,系統的技術堆疊不一樣,可用的性能監控工具也不一樣,例如Linux系統就有top、sar、nmon等命令列工具可以監控服務器的CPU和記憶體的使用情況,JDK也提供了不少命令列工具,例如jstat、jmap、jhat、jstack等可以監控JVM(Java虛擬機)的記憶體情況,JDK可視化分析工具Visual VM,甚至可以進行方法級的程式運行性能分析,找到被呼叫最多、運行時間最長的方法,SQL Server可以用SQL Server Profiler進行慢查詢陳述句分析,而MySQL就用mysqldumpslow,
除了使用監控工具進行性能監控,我們還可以通過在程式代碼上加上一些日志,記錄一些代碼段的運行時間,從而判斷出性能瓶頸的位置,
負載均衡
高并發場景下,比較典型的有電商的秒殺活動,同一時刻內,巨量的HTTP包要發送給服務器端處理,由于服務器資源有限,其同時處理請求的能力自然也有限,當高并發出現時,服務器的處理和回應速度會大幅降低,
為了應對這種場景,可以把用戶請求分發到多臺應用服務器上,利用更多的服務器資源分擔高并發下的負載壓力,這就是負載均衡,

當然,實際的網路結構肯定比上圖的要復雜的多,負載均衡一般分三種,分別是應用層負載均衡、 IP 層負載均衡(網路層負載均衡)、鏈路層負載均衡,應用層負載均衡通常用在規模比較小的集群上,而對于大規模的應用服務器集群,則使用IP層負載均衡或者鏈路層負載均衡,目前大型互聯網應用大多使用鏈路層負載均衡,
分布式快取
快取目的就是減少應用程式請求資料庫,從而降低資料庫的壓力,快取一般存盤那些很少變化而又經常會訪問到的資料,例如每個系統的基礎資料,而分布式快取是應用于分布式架構的,就是單獨的快取服務器,多個應用服務器都可以訪問快取服務器里的資料,分布式快取可以分為CDN、反向代理、分布式物件快取,
CDN
CDN(Content Delivery Network),內容分發網路,本質就是在網路運營商的機房里部署快取服務器,這樣,用戶就可以從離自己近的機房獲取到資料,從而提高了回應速度,因為距離用戶非常近,又被稱作網路連接的第一跳,CDN一般快取的是靜態資源,如圖片,檔案,CSS,JS腳本,靜態網頁等,這些檔案訪問頻率很高,將其快取在CDN可極大改善網頁的打開速度,

反向代理
我們有時候需要通過代理上網,這個代理是代理我們的客戶端上網設備(例如,瀏覽器),反向代理則是代理服務器,所有的網路請求都需要通過反向代理才能到達應用程式服務器,如果在反向代理服務器加一個快取,將資料回傳給用戶,而不是通過應用服務器,這就是反向代理快取,反向代理一般也是快取靜態資源,反向代理服務器同時也具有保護應用服務器安全的作用,來自互聯網的訪問請求必須經過代理服務器,相當于在應用服務器前面建立了一個屏障,

分布式物件快取
CDN 和反向代理快取對應用程式服務器是透明的,通常被當做系統前端的一部分,而應用程式服務器如果要使用快取,就需要分布式物件快取,分布式物件快取,比較熟悉的就是Redis、Memcached,這些中間件提供給應用程式SDK,應用程式通過SDK的API操作快取,

使用快取架構可以快速回應用戶請求,但是快取只能改善系統的讀操作性能,對于寫操作,快取是無能為力的,我們不能把用戶提交的資料直接寫入快取中,因為快取通常被認為是一種不可靠的存盤,
訊息佇列
訊息佇列就是將用戶請求進行異步處理,通俗來說,就是多個用戶的請求排著隊一個個處理,這樣,有效防止了高并發給服務器帶來的壓力,

訊息佇列更多的是用于優化對資料庫的寫入操作,訊息佇列寫資料庫的時候,可以根據資料庫的負載能力控制寫入的速度,高并發的時候降低寫入速度,甚至停止寫入,等到用戶請求低谷的時候,又放開寫入速度的限制,這種方式叫做“削峰填谷”,它可以使系統運行在一個性能最優的負載壓力范圍內,
資料庫優化
前面說的快取其實就是把資料存到記憶體,但是,記憶體的資源畢竟非常有限,不可能把所有資料都存到快取,因此,該連接資料庫還是得連接資料庫,資料庫畢竟是屬于硬碟的東西,它的處理速度肯定沒有記憶體快,同時又對并發壓力比較敏感,大量操作請求同時提交到資料庫,可能會導致資料庫負載壓力太大而崩潰,
優化資料庫一般有三種手段,分別是SQL優化、分庫分表、讀寫分離,
SQL優化
SQL優化最常見的就是慢查詢陳述句優化,查詢優化有一些技巧,例如避免使用select * 、union all關鍵字代替union關鍵字、小表驅動大表、值只有數字的欄位要設為數字型型別、where陳述句欄位加索引、where陳述句的索引欄位不要用函式等等等,
加索引是比較常見的優化方法,但有時候加了索引也慢,這有可能是索引失效了,可以利用資料庫自帶的工具查看執行計劃,看是否索引失效,
分庫分表
分庫分表的主要目的就是為了解決由于資料量過大而導致資料庫性能降低的問題,將原來獨立的資料庫拆分為若干資料庫,將資料大表拆分成若干資料表,使得單一資料庫、單一資料表的資料量變小,從而達到提升資料庫性能的目的,分庫分表又分為垂直分庫、水平分庫、垂直分表、水平分表,值得一提的是,分庫會帶來分布式事務的問題,
-
垂直分庫,就是把原來單庫的表分到多個資料庫,一般會按業務拆分,每個大的業務對應一個資料庫,不同的資料庫可以部署到不同的服務器,這樣,某個業務模塊的資料庫性能問題就不會直接影響到其他業務模塊,例如電商系統的用戶模塊和訂單模塊可以拆分為用戶庫、訂單庫兩個資料庫,垂直分庫的目的是方便按業務分級管理、維護、監控和擴展等,
-
水平分庫,就是把原來單表的行資料分到多個資料庫,這些資料庫的表資料結構是一樣的,例如,把商品id為單數的商品資料分到資料庫A,把商品id為偶數的商品資料分到資料庫B,水平分庫的好處是解決了單庫大資料造成的性能問題,
-
垂直分表,就是把原來單表的欄位分到多個表,例如,原來商品表有id、商品名稱、單價、描述等欄位,經過垂直分表后,分成了兩個表,id、商品名稱、單價欄位分到商品表A,id、描述欄位分到商品表B,需要垂直分表的原因一般是原表中有大欄位(例如商品表的“描述”欄位就是大欄位,里面可以包含很多字符),大欄位IO效率低,需要把大欄位單獨分到一個表中,這樣頁面的商品串列因為不需要顯示“描述”欄位而得到優化,
-
水平分表,就是把原來單表的行資料分到多個表,這些表資料結構是一樣的,例如,把商品id為單數的商品資料分到商品表A,把商品id為偶數的商品資料分到商品表B,水平分表的好處是解決了單表大資料造成的性能問題,
讀寫分離
資料庫讀寫分離就是做資料庫集群,一般是一主多從,一個主庫(master)負責寫入資料,多個從庫(slave)負責讀取資料,當然也有多master的方案,

大多數互聯網業務,往往讀多寫少,這時候,資料庫的讀操作會首先成為資料庫的性能瓶頸,這時,如果我們希望能夠線性的提升資料庫的讀性能,消除讀寫鎖沖突從而提升資料庫的寫性能,那么就可以使用讀寫分離架構,
代碼優化
有些性能問題是可以通過修改代碼解決的,例如,避免回圈次數過多、避免在回圈內讀寫資料庫、避免在回圈內呼叫API、匯出的資料量做限制、盡量批量操作資料庫、同步操作換異步操作、使用快取、采用定時任務等等等,
JVM調優
如果是Java程式,可以考慮JVM配置優化,一般可以通過jstat、jmap、jhat、jstack等命令監控到JVM記憶體的使用情況以及GC的情況,如果發現GC過于頻繁(特別是Full GC),就可以通過修改JVM引數,加大JVM堆記憶體,或者修改堆記憶體磁區比例,達到優化的效果,當然,其他編程語言應該也有類似的優化辦法,
服務降級
服務降級就好比大環境不好,錢不好賺,需要把燒錢和不賺錢的業務裁掉,留下核心業務過冬,當系統負載過高或者出現故障時,需要啟動限流,寫入限制,甚至將一些非核心業務(負載過高)或者故障業務進行移除,以此釋放服務器資源以保證核心業務的正常運行,
硬體擴容或升級
有條件(不缺錢)的情況,是可以考慮買買買的(簡單粗暴),記憶體擴容、硬碟空間擴容、加服務器、上固態硬碟等等等,
結語
IT系統性能優化是個大課題,是一個龐大的知識體系,包含但不限于上面提到的知識點,如果要展開詳說,估計要講到天荒地老,有興趣的,可以一個個的去深入研究,
本文來自博客園,作者:Yi00,轉載請注明原文鏈接:https://www.cnblogs.com/ayic/p/16536268.html
聊聊技術,聊聊人生,歡迎關注我的公眾號!^_^
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/514300.html
標籤:其他
上一篇:系統安全及應用
下一篇:筆記本外接顯卡方案
