效能是乙個多方面綜合的結果,遵循短板理論。系統中任何乙個部分成為效能瓶頸,都會影響整個系統的效能表現
對於web應用,首先第一步是響應http請求,即使後端的效能再好,如果在這裡出現瓶頸,整個系統的效能也會很差,類似於乙個很大的水瓶,但是入水口很小。在這個環節,可以通過dns分流,負載均衡等方式改善。另外,現在高效能的http伺服器(nginx、node.js等)本身,由於採用了事件通知等設計方式,單個執行緒可以響應多個http請求,減少了執行緒建立和切換的開銷(cpu與記憶體),也可以顯著提公升響應http請求的效能
接受請求之後,則進入系統後端進行業務邏輯處理,在這裡也會產生效能瓶頸。通過集群的方式,可以有效改善。因為單台伺服器的硬體總是有限的,受限於cpu和記憶體,單台機器能夠處理的負載終究是有限的,這時可以採用集群方案,將請求分攤到不同的伺服器上處理。這對應用的實現本身是有要求的,基本上要求應用是「無狀態」的。比如如果應用的業務邏輯依賴session,那麼集群就無法簡單地實現,還需要加入session同步的策略等。另外應用本身的**也會有影響,比如在關鍵路徑上使用了synchronized,那麼就只能序列處理,對效能肯定有影響
集群不等於分布式。當應用的規模大到一定程度,簡單的集群也無法支撐,這時候往往還需要考慮分布式,對系統進行拆分,充分利用硬體的效能,達到最大的擴充套件性。此外,即使不考慮效能,將系統拆分,實現「服務化」,對於功能的擴充套件也是很有幫助的。比如說,只有單個系統時,使用者管理可以和業務系統放在一起;但是當應用規模不斷增大,有100個系統,那麼把使用者管理拆分出來,就可以在100個系統中實現這部分功能的共享
最後到了持久層,這裡往往會涉及到大量的io讀寫,這是最容易產生效能瓶頸的地方。傳統的rdbms本質上是乙個單機系統,並且需要遵循acid的約束。所以傳統的關聯式資料庫的擴充套件性是很差的。比如說,我們用到了資料庫集群,這可以解決服務可用性的問題(主備倒換),容災的問題(資料冗餘),對效能也有一定的幫助(同時響應更多的資料庫連線請求)。但是僅僅這樣還不夠,因為前面說過rdbms本質上是單機系統,即使用了集群亦然。什麼意思呢?集群僅僅解決了多連線併發的問題,但是資料庫本身插入、查詢,涉及到大量的io,就已經成為了瓶頸,尤其在資料量很大的情況就更加明顯。所以僅僅是集群還不夠,這時候就需要分表(水平拆分),這對系統的**就有要求,什麼樣的資料,要到哪個表裡查詢,都需要遵循一定的規則。有乙個辦法是,將資料庫路由的功能放在jdbc之下,資料庫之上,這樣應用就只需要連線到這個資料庫路由層,不用關心表的實際位置。隨著資料庫複雜度的上公升,本來很好用的orm,也就越來越捉襟見肘了
資料規模越來越大,遇到即使拆表也無法解決問題的時候,就需要考慮rdbms之外的方案。比如鍵值資料庫(redis、tair)、文件資料庫(mongodb)等nosql技術,甚至還有檔案系統(gfs、tfs),當然快取也是很常見的重要方案
總的來說,效能是乙個很大的話題。為了實現高效能,系統的架構是隨著業務的發展,逐步演化的,從一開始就設計乙個大規模的架構,絕非明智之舉。「先實現功能,再按需優化」,才是比較好的策略。在這個過程中,既需要前瞻的眼光,也需要推倒重來的勇氣
如同dota的路人和cw是2個不同的遊戲一樣;同樣的應用,在小規模場景,和大規模場景(高併發、海量資料)下,也是完全不同的兩回事,為了實現同樣的功能,架構和實現上可能是千差萬別的
關於綜合查詢的效能優化問題的解決乙個思路
在專案中,總是會有什麼什麼列表查詢,然後還要求根據型別分類查詢,有時候發現不同型別關聯的表不相同,想要獲得的東西也不相同,之前我查詢方法總是採用union 將幾個相關表連線起來,這樣造成的問題是,壓力全部在資料庫上,後來根據領導的建議,我將相同的基表先查出來,然後,採用for迴圈將不同關聯的表按條件...
乙個指標綜合應用的示例
寫乙個函式,從傳入的num個字串中找出最長的乙個字串,並通過形參指標max傳回該字串的位址 注意用 作為結束輸入的標誌 如下 include using namespace std include cstring 形參是陣列指標 陣列指標a表示指向乙個每行有10個元素的陣列的首位址 和輸入字串的數目...
判斷乙個資料序列是否是BST後序遍歷的結果
基本知識 1 bst 二叉排序樹,即父節點大於左子節點,小於等於右子節點 2 後序遍歷 先遍歷左子樹,再遍歷右子樹,最後遍歷根節點 基本思想 後續遍歷得到的陣列的最後乙個元素為根節點,前一部分為左子樹,後一部分為右子樹 前一部分中的元素都小於root 根 後一部分中的元素都大於root 根 所以可以...