架構的本質
一個軟件系統隨着功能愈來愈多,調用量急劇增加,整個系統逐漸碎片化,愈來愈無序,最
終沒法維護和擴展,因此係統在一段時間的野蠻生長後,也須要及時干預,避免愈來愈無序。
架構的本質就是對系統進行有序化重構,使系統不斷進化
那架構是如何實現無序到有序的呢? 基本的手段就是分和合,先把系統打散,而後從新組合。
分的過程是把系統拆分爲各個子系統 / 模塊 / 組件,拆的時候,首先要解決每一個組件的定
位問題,而後才能劃分彼此的邊界,實現合理的拆分。合就是根據最終要求,把各個分離的
組件有機整合在一塊兒,相對來講,第一步的拆分更難。
拆分的結果使開發人員可以作到業務聚焦、技能聚焦,實現開發敏捷,合的結果是系統變得
柔性,能夠因需而變,實現業務敏捷
架構的分類
架構通常可分業務架構、應用架構、技術架構
1. 業務架構從概念層面幫助開發人員更好的理解系統,好比業務流程、業務模塊、輸入輸出、
業務域
2. 應用架構從邏輯層面幫助開發落地系統,如數據交互關係、應用形式、交互方式,是的整
個系統邏輯上更容易理解,步入你們熟知的 SOA 就屬於應用架構的範疇
3. 技術架構主要解決技術平臺選型、如操做系統、中間件、設備、多機房、水平擴展、高可
用等問題
須要注意的是,系統或者架構首先都是爲人服務的,系統的有序度高,用用邏輯合理,業務
概念清晰是第一位。如今你們討論更多的是技術架構,如高併發設計,分佈式事務處理等,
只是由於這個不須要業務上下文背景,比較好相互溝通。具體架構設計時,首先要關注業務
架構和應用架構,這個架構新手要特別注意。也是面試時候的痛點!
大型網站的架構演進
ps : 如下內容部分圖片參考自《大型網站系統與 Java 中間件實戰.pdf》
從一個電商網站開始
爲了更好的理解,咱們用電商網站來舉例,
做爲一個交易類型的網站,必定會具有
用戶(用戶註冊、用戶管理)、商品(商品展現、商品管理)、交易(下單、支付)這些功能假如咱們只須要支持這幾個基本功能,那麼咱們最開始的架構應該多是這樣的
這個地方要注意的是,各個功能
模塊之間是經過 JVM 內部的方
法調用來進行交互的,而應用和
數據庫之間是經過 JDBC 進行訪
問。
單機負載告警,數據庫與應用分離
隨着網站的開放,訪問量不斷增大,那麼這個時候服務器的負載勢必會持續升高,必需要才
需一些辦法來應付。這裏先不考慮更換機器和各類軟件層面的優化,先從架構的結構上來作
一些調整。咱們能夠把數據庫與應用從一臺機器分到兩臺機器
變化:
網站從一臺變成了 2 臺,這個變化對咱們
來講影響很是小。單機的狀況下,咱們應
用採用 JDBC 的方式來和數據庫進行連
接,如今數據庫與應用分開了,咱們只需
要在配置文件中把數據庫的地址從本機
改爲數據庫服務器的 ip 地址就行。
對於開發、測試、部署都沒有影響
調整之後咱們可以緩解當前的系統壓力,
不過隨着時間的退役,訪問量繼續增大的
話,咱們的系統仍是須要作改造爲何這麼分呢?從計算機自己的角度來考慮的話,一個請求的訪問處處理最終到返回,性
能瓶頸只會是:CPU、文件 IO、網絡 IO、內存、等因素。而一臺計算機中這些緯度是有性
能瓶頸的,若是某個資源消耗過多,一般會形成系統的響應速度較慢,因此增長一臺機器,
使得數據庫的 IO 和 CPU 資源獨佔一臺機器從而增長性能。
這個地方插入一點題外話,就是簡單說一下各個資源的消耗緣由。
CPU/IO/內存:
1. 主要是上下文的切換,由於每一個 CPU 核心在同一時刻只能執行一個線程,而 CPU 的調
度有幾種方式,好比搶佔式和輪詢等,以搶佔式爲例,每一個線程會分配必定的執行時間,
當達到執行時間、線程中有 IO 阻塞或者有高優先級的線程要執行時。CPU 會切換執行其
他線程。而在切換的過程當中,須要存儲當前線程的執行狀態並恢復要執行的線程狀態,這
個過程就是上下文切換。好比 IO、鎖等待等場景下也會觸發上下文切換,當上下文切換
過多時會形成內核佔用比較多的 CPU。
2. 文件 IO,好比頻繁的日誌寫入,磁盤自己的處理速度較慢、都會形成 IO 性能問題
3. 網絡 IO,帶寬不夠
4. 內存,包括內存溢出、內存泄漏、內存不足
實際上無論是應用層的調優也好,仍是硬件的升級也好。其實無非就是這幾個因素的調整。
應用服務器複雜告警,如何讓應用服務器走向集羣
假如說這個時候應用服務器的壓力變大了,根據對應用的檢測結果,能夠針對性的對性能壓
力大的地方進行優化。咱們這裏考慮經過水平擴容來進行優化,把單機變爲集羣
應用服務器從一臺變爲兩臺,這兩個應用服
務器之間沒有直接的交互,他們都依賴數據
庫對外提供服務,那麼這個時候會拋出兩個
問題:
1. 最終用戶對應兩個應用服務器訪問的選
擇
對於這個問題,能夠採用 DNS 解決,也能夠
經過負載均衡設備來解決
2. session 的問題?
水平和垂直擴容
對於大型的分佈式架構而言,咱們一直在追求一種簡單、優雅的方式來應對訪問量和數據量
的增加。而這種方式一般指的是不須要改動軟件程序,僅僅經過硬件升級或者增長機器就可
以解決。而這種就是分佈式架構下的伸縮設計。
伸縮分爲垂直伸縮和水平伸縮兩種
垂直伸縮:
表示經過升級或者增長單臺機器的硬件來支撐訪問量以及數據量增加的方式,垂
直伸縮的好處在於技術難度比較低,運營和改動成本也相對較低。可是缺點是機器性能是
有
瓶頸的,同時升級高性能的小型機或者大型機,成本是很是大的。這也是阿里去 IOE 的一個
緣由之一
增長 CPU 核心數:增長 CPU 後系統的服務能力可以獲得大的增加,好比響應速度、同時可以處理的線程數。可是引入 CPU 後也會帶來一些顯著的問題
1. 鎖競爭加重;多個線程同時運行訪問某個共享數據,那麼就涉及到鎖競爭,鎖競爭激烈時會致使不少線程都在等待鎖,因此即時增長 CPU 也沒法讓線程獲得更快的處理。固然這裏是有調優手段的,能夠經過調優手段來下降鎖競爭
2. 支撐併發請求的線程數是固定的,那麼即時增長 CPU,系統的服務能力也不會獲得提高
3. 對於單線程任務,多核心 CPU 是沒有太大的做用的
增長內存:增長內存能夠直接提成系統的響應速度,固然,也有可能達不到效果
,就是若是JVM 堆內存是固定的。
水平伸縮:
經過增長機器來支撐訪問量及數據量增加的方式,成爲水平伸縮,水平伸縮理論
上來講沒有瓶頸,可是缺點是技術要求比較高,同時給運維帶來了更大的挑戰
垂直伸縮和水平伸縮都有各自的有點,咱們在實際使用過程當中都會對二者作結合,一方面要
考慮硬件升級的成本,一方面要考慮軟件改造的成本。
引入負載均衡設備
服務路由,基於負載均衡設備來實現引入負載均衡器之後,會帶來 session 相
關的問題
負載均衡算法
輪詢(Round Robin)法
將請求按順序輪流分配到後臺服務器上,均衡的對待每一臺服務器,而不關心服務器實際的
鏈接數和當前的系統負載
缺點:當集羣中服務器硬件配置不一樣、性能差異大時,沒法區別對待
隨機法
經過系統隨機函數,根據後臺服務器列表的大小值來隨機選取其中一臺進行訪問。隨着調用
量的增大,其實際效果愈來愈接近於平均分配流量到後臺的每一臺服務器,也就是輪詢法的
效果
優勢:簡單使用,不須要額外的配置和算法。
缺點:隨機數的特色是在數據量大到必定量時才能保證均衡,因此若是請求量有限的話,可
能會達不到均衡負載的要求。
源地址哈希法
根據服務消費者請求客戶端的 IP 地址,經過哈希函數計算獲得一個哈希值,將這個哈希值和
服務器列表的大小進行取模運算,獲得的結果即是要訪問的服務器地址的序號。採用源地址
哈希法進行負載均衡,相同的 IP 客戶端,若是服務器列表不變,將映射到同一個後臺服務器
進行訪問。
加權輪詢(Weight Round Robin)法
不一樣的後臺服務器可能機器的配置和當前系統的負載並不相同,所以它們的抗壓能力也不一
樣。跟配置高、負載低的機器分配更高的權重,使其能處理更多的請求,而配置低、負載高
的機器,則給其分配較低的權重,下降其系統負載,加權輪詢很好的處理了這一問題,並將
請求按照順序且根據權重分配給後端
最小鏈接數法
前面幾種方式都是經過對請求次數的合理分配最大可能提升服務器的利用率,可是實際上,
請求次數的均衡並不能表明負載的均衡。因此,引入了最小鏈接數法。它正是根據後端服務
器當前的鏈接狀況,動態的選取其中當前積壓鏈接數最少的一臺服務器來處理當前請求,盡
可能的提升後臺服務器利用率,將負載合理的分流到每一臺服務器。
session 問題
咱們打開一個網頁,基本上須要瀏覽器和 web 服務器進行屢次交互,咱們都知道 Http 協議
自己是無狀態的,這也是 http 協議設計的初衷,客戶端只須要簡單的向服務器請求下載某些
文件,不管是客戶端仍是服務器都不必記錄彼此過去的行爲,每一次請求之間是獨立的,
比如一個顧客和一個自動售貨機之間的關係同樣.
而實際上,咱們不少的場景都須要帶有狀態的特性,所以聰明的咱們引入了 session+cookie
機制來記住每次請求的會話。
在會話開始時,給當前會話分配一個惟一的會話標識(sessionid),而後經過 cookie 把這個
標識告訴瀏覽器,之後在每次請求的時候,瀏覽器都會帶上這個會話標識來告訴 web 服務器
請求屬於哪一個會話。在 web 服務器上,各個會話有獨立的存儲,保存不一樣會話的信息。
若是遇到禁用 cookie 的狀況,通常的作法就是把這個會話標識放到 URL 的參數中。
而咱們應用服務器從一臺變成兩臺後,就會遇到 session 問題
分佈式環境下的 session 共享
Session 共享在當前這個互聯網背景下,已經不是一個新鮮的話題了,並且如何解決 session共享其實也有不少很是成熟的方案。
服務器實現的 session 複製或 session 共享,這類型的共享 session 是和服務器緊密相關的。
咱們在 Web 服務器之間增長了會話數據的同步,經過同步就保證了不一樣 Web 服務器之間
Session 數據的一致。通常應用容器都支持 Session Replication 方式
存在問題:
1. 同步 Session 數據形成了網絡帶寬的開銷。只要 Session 數據有變化,就須要將數據同步
到全部其餘機器上,機器越多,同步帶來的網絡帶寬開銷就越大。
2. 每臺 Web 服務器都要保存全部 Session 數據,若是整個集羣的 Session 數據不少(不少
人同時訪問網站)的話,每臺機器用於保存 Session 數據的內容佔用會很嚴重。
這個方案是靠應用容器來完成 Session 的複製從而解決 Session 的問題的,應用自己並不關
心這個事情。這個方案不適合集羣機器數多的場景。
利用成熟的技術作 session 複製,好比 12306 使用的 gemfire,好比常見的內存數據庫如 Redis,
Session 數據不保存到本機並且存放到一個集中存儲的地方,修改 Session 也是發生在集中
存儲的地方。Web 服務器使用 Session 從集中存儲的地方讀取。這樣保證了不一樣 Web 服務
器讀取到的 Session 數據都是同樣的。存儲 Session 的具體方式能夠是數據庫
存在問題:
1. 讀寫 Session 數據引入了網絡操做,這相對於本機的數據讀取來講,問題就在於存在時延
和不穩定性,不過咱們的通信基本都是發生在內網,問題不大。
2. 若是集中存儲 Session 的機器或者集羣有問題,就會影響到咱們的應用。相對於 Session Replication,當 Web 服務器數量比較大、Session 數比較多的時候,這個集
中存儲方案的優點是很是明顯的。
將 session 維護在客戶端
很容易想到就是利用 cookie,可是客戶端存在風險,數據不安全,並且能夠存放的數據量比
較小,因此將 session 維護在客戶端還要對 session 中的信息加密。
咱們的 Session 數據放到 Cookie 中,而後在 Web 服務器上從 Cookie 中生成對應的 Session
數據。這就比如咱們每次都把本身的碗筷帶在身上,這樣去那家飯店就能夠隨意選擇了。相
對前面的集中存儲方案,不會依賴外部的存儲系統,也就不存在從外部系統獲取、寫入 Session
數據的網絡時延、不穩定性了。
存在問題:
安全性。Session 數據原本都是服務端數據,而這個方案是讓這些服務端數據到了外部網絡及
客戶端,所以存在安全性上的問題。咱們能夠對寫入的 Cookie 的 Session 數據作加密,不過
對於安全來講,物理上不能接觸纔是安全的。
數據庫壓力變大,讀寫分離吧
隨着業務的繼續增加,數據量和訪問量持續增長。對於大型網站來講,有很多業務是讀多寫
少,這個狀況也會直接反饋到數據庫上。那麼對於這種狀況來講,咱們能夠考慮採用讀寫分
離的方式來優化數據庫的壓力這個結構的變化會帶來兩個問題
1. 數據如何同步
咱們但願經過讀庫來分擔主庫上讀的壓力,那麼首先
須要解決的是怎麼複製到讀庫的問題。數據庫系統一
般都提供了數據複製的功能,咱們能夠直接使用數據
庫系統自身的機制。不一樣的數據庫系統有不一樣的支持,
好比 Mysql 支持 Master+slave 的結構提供數據複製機
制
2. 應用對數據源如何路由
對於應用來講,增長一個讀庫對結構變化產生了必定
的影響,也就是咱們的應用須要根據不一樣的狀況來選
擇不一樣的數據庫源
搜索引擎實際上是一個讀庫
搜索引擎其實能夠理解成一個讀庫,咱們的商品存儲在數據庫中,而網站須要提供用戶實時
檢索的功能,尤爲是在商品搜索這塊。對於這樣的讀請求,若是所有走讀庫,其實性能也會
存在一個瓶頸。而使用搜索引擎,不只僅能大大提升檢索速度。還能減輕讀數據庫的壓力,
而搜索引擎最重要的工做,就是須要根據被搜索的數據來構建索引,而隨着被搜索的數據的
變化,索引也須要相應變化。
搜索集羣的使用方式和讀庫的使用方式是同樣的,只
是構建索引的過程基本都是須要咱們本身來實現。可
以從兩個緯度對搜索引擎構建索引的方式進行規劃,
一個是按照全量/增量劃分。一種是按照實時/非實時
劃分。
全量方式用於第一次創建索引,多是新建,也可能
是重建。而增量的方式是在全量的基礎上持續更新索
引。
實時和非實時提如今索引更新的時間上,實時是最好
的,非實時主要考慮到對數據源頭的保護
總的來講,搜索引擎技術解決了站內搜索時某些場景
下的讀的問題,提供了更好的查詢效率。
加速數據讀取的利器-緩存及分佈式存儲
在大型網站中,基本上就是在解決存儲和計算的問題,因此存儲是一個很重要的支撐系統。
網站建設初期咱們都是從關係型數據庫開始的,並且不少時候爲了方便,咱們會把一些業務
邏輯放在數據庫裏面去作,好比觸發器、存儲過程。雖然在前期可以很方便的解決問題,但
是在將來的發展過程當中會帶來不少的麻煩,好比數據量大了之後,要作分庫分表操做等. 同
時,業務發展到必定的體量之後,對存儲的需求不能徹底經過關係型數據庫來知足
分佈式文件系統
對一些圖片、大文本,使用數據庫就不合適了,因此咱們會採用分佈式文件系統來實現文件
存儲,分佈式文件系統有不少產品、好比淘寶的 TFS、google 的 GFS。還有開源的 HDFS
NoSQL
NoSQL 咱們能夠理解成 Not Only SQL、或者是 No SQL。 兩種意思都是爲了表達在大型網
站中,關係型數據庫能夠解決大部分問題,可是對於不一樣內容的特徵、訪問特徵、事務特徵
等對存儲的要求是不同的。NoSQL 是定位因而文件系統和 SQL 關係型數據庫之間的範疇。
數據緩存
大型網站內部都會用到一些數據緩存,主要用於分擔數據庫的讀的壓力,緩存系統通常是用
來保存和查詢鍵值對的。應用系統中通常會把熱點數據放入到緩存,而緩存的填充也應該是
由應用系統完成。若是數據不存在,則從數據庫獨處數據後放入緩存。隨着時間的推移,當
緩存容量不夠須要清除數據時,最近不被訪問的數據就會被清理掉。還有一種方式就是在數
據庫的數據發生變化後,主動把數據放入到緩存系統中,這樣的好處是數據變化時可以及時
更新緩存的數據,不會形成讀取失效。
頁面緩存
除了數據緩存外,咱們還能夠對頁面作緩存,數據緩存能夠加速應用在響應請求時的數據讀
取數度,可是最終展現給用戶的仍是頁面,有些動態產生的頁面或者訪問量特別高的頁面,
咱們會對頁面或者內容作一些緩存。
彌補關係型數據庫的不足,引入分佈式存儲
咱們應用最多的主要仍是關係型數據庫,可是在有些場景中,關係型數據庫不是很合適。所
以咱們會引入分佈式存儲系統,好比 redis、mongoDB、cassandra、HBase 等。
根據不一樣的場景和數據結構類型,選擇合適的分佈式存儲系統能夠極大提升性能。分佈式系
統經過集羣提供一個高容量、高併發訪問、數據冗餘融債的支持。
讀寫分離後,數據庫又遇到瓶頸
經過讀寫分離以及在某些場景用分佈式存儲系統替換關係型數據庫的方式,可以下降主庫的
壓力,解決數據存儲方面的問題,不過隨着業務的發展,咱們的主庫也會遇到瓶頸。推演到
如今,咱們的網站各個模塊:交易、商品、用戶數據都仍是存儲在一個數據庫。儘管增長了
緩存、讀寫分離的方式,可是數據庫的壓力仍然在持續增長,所以咱們能夠對數據垂直拆分
和水平拆分來解決數據庫壓力問題
專庫專用,數據垂直拆分
垂直拆分的意思是把數據庫中不一樣的業務數據拆分到不一樣的數據庫中,那麼根據咱們推演的例子,
把用戶、交易、商品的數據分開不一樣業務的數據從原來的一個數
據庫拆分到了多個數據庫中,那麼
就須要考慮到如何處理原來單機
跨業務的事務
1. 使用分佈式事務解決
2. 去掉事務或者不追求強事務的
支持
對數據進行垂直拆分後,解決了把
全部業務數據放在一個數據庫中
的壓力問題,而且也能夠根據不一樣
業務的特色進行更多的優化
垂直拆分後,遇到瓶頸,數據水平拆分
與垂直拆分對應的還有數據水平拆分,數據水平拆分就是把同一個表的數據拆分到兩個數據
庫中,產生數據水平拆分的緣由是某個業務的數據表的數據量或者更新量達到了單個數據庫
的瓶頸,這個時候就能夠把表拆到兩個或者多個數據庫中。
數據水平拆分與讀寫分離的區別是,讀寫分離解決的是讀壓力大的問題,對於數據量大或者
更新量大的狀況並不起做用。
數據水平拆分與數據垂直拆分的區別是,垂直拆分是把不一樣的表拆分到不一樣的數據庫,而水
平拆分是把同一個表拆分到不一樣的數據庫中。
咱們能夠進一步把用戶表拆分到兩個數據庫中,它們擁有結構如出一轍的用戶表,並且每一個
庫中的用戶表都只涵蓋了一部分的用戶,兩個數據庫的用戶和在一塊兒就至關於沒有拆分以前
的用戶表。
水平拆分帶來的影響
1. sql 路由問題,須要根據一個條件來決定當前請求發到那個數據庫中
2. 主鍵的處理,不能採用自增 id,須要全局 id
3. 因爲同一個業務的數據被拆分到不一樣的數據庫,所以涉及到一些查詢須要跨兩個數據庫獲
取,若是數據量太大而且須要分頁,就比較難處理了
數據庫問題解決後,應用面對的挑戰
前面講的讀寫分離、分佈式存儲、數據垂直拆分和水平拆分都是解決數據方面的問題,接
來咱們要看看應用方面的變化
隨着業務的發展,應用的功能會愈來愈多,應用也會愈來愈大,咱們須要思考如何不讓應用
持續變大,這就須要把應用拆開,從一個應用變爲兩個甚至是多個。
第一種方式
根據業務的特性把應用拆分,在咱們的例子中,主要業務功能分三個部分、用戶、商品、交
易。咱們能夠把原來的一個應用拆成分別以交易和商品爲主的兩個應用,對於交易和商品都
會有設計使用用戶的地方,咱們讓這兩個系統本身完成涉及用戶的工做,而相似用戶註冊、
登陸等基礎的用戶工做,能夠暫時交給兩個系統之一來完成。
咱們還能夠按照用戶註冊、用戶登陸、用戶信息維護等再拆分,變成三個系統,不過這樣拆分後在
不一樣系統中會有一些類似的代碼,好比用戶相關的代碼,如何可以保障這部分代碼的一致以及如何
對其餘模塊提供複用也是須要解決的問題。並且,這樣拆分出來的新系統之間沒有直接的相互調用
服務化的道路
咱們在來看一下服務化的作法,咱們把應用分爲三層,處於最上端的是 web 系統,用於完成不一樣
的業務功能,處於中間的是一些服務中心,不一樣的服務中心提供不一樣的業務服務;處於最下層的則
是業務的數據庫。
與以前相比有幾個重要的變化,首先業務功能之間的訪問不只僅是單機內部的方法調用,還引入了
遠程的服務調用。其次,共享代碼再也不是散落在不一樣的應用中,這些實現被放在各個服務中心。最
後,數據庫的鏈接也發生了一些變化,咱們把數據庫的交互工做放到了服務中心,讓前端的 web 應
用更加註重與瀏覽器的交互工做,而沒必要過多關注業務邏輯的事情。連接數據庫的任務交給響應的
業務服務中心了,這樣能夠下降數據庫的鏈接數。
而服務中心不只把一些能夠共用的代碼集中管理,並且還使得這些代碼變得更好維護。
服務化的方式會帶來不少好處,首先,從結構上來看,系統架構更加清晰了,比本來的架構
更加立體。從穩定性上來看,一些散落在多個應用系統中的代碼變成了服務而且由專門的團隊進行統一維護,一方面能夠提升代碼的質量,另外一方面因爲基礎核心模塊相對穩定。修改
和發佈的頻次相對於業務系統來講會少不少,這也會提升整個架構的穩定性。最後,更加底
層的資源由服務層統一管理,結構更加清晰,對於團隊開發效率來講有比較大的提升
服務化的方式,對於研發也會有很大的影響,之前的開發模式是幾個大團隊負責幾個大應用,
隨着服務化的落地,咱們的應用數量會飛速增加,系統內部的依賴關係也會變的錯綜複雜,
同時團隊也進行了拆分,每一個小團隊專一於某個具體的服務或者應用上,迭代效率也會更高
什麼是分佈式架構
分佈式架構的定義
不少同窗沒法理解分佈式系統,簡單來講,分佈式系統是指位於網絡計算機上的組件僅經過
傳遞消息來通訊和協調目標系統。這裏面有兩個重要因素
1. 組件是分佈在網絡計算機上
2. 組件之間僅僅經過消息傳遞來通訊並協調行動
分佈式系統其實也能夠認爲是一種去中心化的實現思路,對於用戶來講是無感知的
分佈式架構的意義
從單機單用戶到單機多用戶,再到如今的網絡時代,應用系統發生了不少的變化,爲何要
用分佈式系統呢?
1. 升級單機處理處理你能力的性價比愈來愈低
2. 單機處理能力存在瓶頸
3. 對於穩定性和可用性的要求
咱們知道,單臺機器的處理能力能力包括 CPU、內存、磁盤和網絡。
你們聽過摩爾定律吧, 當價格不變時,每隔 18 個月,集成電路上課容納的晶體管數量會增
加一倍,性能也會增長一倍。意味着隨着時間的退役,單位成本的支出所能購買的計算能力
在提高,可是咱們要求處理器的性能越高,所須要付出的成本也就越高。因此經過不斷提高
單臺機器的性能鎖帶來的產值是不划算的,同時,處理器自己也存在性能瓶頸。
還有一個很重要的因素,穩定性和可用性方面,在單機環境中是提供不了的。因此勢必須要
分佈式系統來解決