系統架構概念及思想1

  

分佈式系統
 特色:
  1.系統各組件分佈於網絡上多個計算機上
  2.咱們部署的各功能組件彼此之間僅僅經過消息傳遞來通訊,達到協調行動的目的。
  知足這兩點,你的系統就是分佈式系統

分佈式系統存在的意義:
 向上擴展達到瓶頸:
  1.即單機上不管你增長內存,磁盤,CPU個數,其性價比很難再提不上去了。
  2.性能達到臨界點後,性能將不升反降。
  3.單點故障沒法避免,故障後一切擴展都將不可用。

  基於馮諾依曼的計算機架構,對於當前來講已經沒法從單機上獲得更好的總體系統性能。摩爾定律說計算機硬件技術會每18個月更新一次,在當今世界也在改變,硬件的提高會逐漸達到提高瓶頸,而數據則會在18個月後翻一倍,因此咱們已經進入一個大數據的時代。另外,摩爾定義也向咱們說明了一個問題,今天你花多大的價錢買的硬件,在一年半(18個月)後都會落後。

多CPU:
  硬件技術進步,讓單機計算能力出現了太多空閒,所以多線程編程技術就成爲了最佳的提升性價比的方式。
多線程編程模型:
 1. 互不通訊的線程模型: 這些模型的性能是最好的,執行效率也是最高效的,但實用性可能不高。
 2. 基於共享容器協同工做的模型:
   A線程運行過程當中,須要從B線程哪裏獲取一個結果,才能繼續運行,若此時A線程直接去啓動B線程,
  這實際上是至關麻煩的事,若藉助中間容器,這裏指隊列,A線程經過將請求發給隊列,而後,B線程
  從隊列中獲取請求,執行結束後將結果再放回隊列中,A線程從隊列中獲取結果後,就能夠繼續執行了。
  這種就是共享容器模型,它能夠實現讓多個線程並行協同運行。
  爲了使這種共享容器模型在多線程並行時,訪問數據更加安全,它又分爲兩種類型:
  a. 線程安全
    指A線程修改了共享容器中的A數據,而C去訪問A數據或修改A數據也同樣能夠,它們之間都是
   互相獨立,互不干擾的,這種就稱爲線程安全的模型。
  b. 線程不安全
    指A線程修改了共享容器中的A數據,而C線程此時也去修改A數據,就可能致使A數據損壞,這種
   就稱爲線程不安全。 對於線程不安全的類型,一般使用加鎖的機制 或 Copy on Write(COW)
   的方式來保障數據安全,在使用加鎖的機制時,若併發線程數不少時,一般會使用互斥鎖。
   這種方式中線程之間是須要互相通訊的,所以就會形成等待結果的一方將不能繼續運行,因此這其實
   就會下降多線程並行執行的效率了。
 3.經過事件協調的多線程模型
   B的某個執行流程依賴於A完成了某種特定操做以後才能進行。那麼A就須要在某個特定操做完成以後,
  觸發一個事件,這個事件能夠通知給B,因此B拿到這個事件後,就能夠繼續運行了,因此在A觸發這個
  事件以前,B就只能處於等待事件的狀態。

多線程 和 多進程模型的區別:
  線程之間是可共享父進程內部的不少資源,如:父進程打開的文件句柄,內部信號等等。
  進程之間是互相隔離的,它們僅能經過進程間通訊模式進行交互通訊,因此多進程模型比多線程模型,在資源控制方面更爲簡單。

  這些模型的出現,主要是爲了使用多CPU,由於,單個CPU已經不能經過提高頻率來提高其性能,目前芯片廠商都是經過增長CPU的核心數,藉助於多線程編程,來解決單機上面性能的提高問題。但多線程編程又很是複雜,若程序員不能很好的利用多核心來編程,對於多核來講效益是很小的。

網絡I/O:
  1.經過阻塞模型,即一個請求過來,在處理它時,其它請求都被阻塞等待第一個請求處理完才能被接入進來進行處理,因此這種模型目前已不在使用。
  2.多進程模型,即每一個進程響應一個請求;
  3.多線程,多進程,即每一個進程生成多個線程,每一個線程響應一個用戶請求。
  4.多線程,每一個線程直接響應多個請求。
   可是不管是那種方式,每個請求進來都須要有一個對應的套接字。
前端

基於socket實現網絡通訊開發,其實現方式主要有三類:
  BIO: Blocking IO,即阻塞式IO:一個Socket套接字須要一個進程或一個線程來處理,那麼鏈接的創建讀數據寫數據的過程都有可能產生阻塞,這種機制就是每進程 或 每線程響應一個請求的模式。
    缺點:每一個鏈接都要佔用一個套接字. 【注:套接字有兩種:鏈接和監聽套接字】
  NIO: Nonblocking IO,非阻塞I/O,它是基於事件驅動(Linux是epoll實現事件驅動的.)的思想,採用Reactor模式,實現響應。
    優勢: 一個套接字分配個一個線程,而一個線程能夠處理多個套接字相關的工做。
  AIO:異步IO模式,它也是基於事件驅動的思想,但它採用Proactor模式

如何把應用從單機擴展到多機?
輸入、輸出設備如何變化?
控制器如何變化?程序員

實現的模式:
  透明代理: 即用戶訪問時,已經給咱們響應的就是服務器,其實多是如下這些,這種就屬於對用戶透明的.
     並且中間的轉發控制器就成爲網絡的中心。以下:
      LVS的NAT模型,
      Haproxy, Nginx的反向代理
  旁路代理
    LVS的DR模型
  名稱服務模式:
    DNS: 用戶僅第一次訪問時,須要查詢,DNS經過名稱給客戶端反饋不一樣的解析IP,實現調度控制。
  規則服務模式:
    規則服務器:在數據庫服務中,當數據庫很大時,須要分庫,分表時,就須要規則服務器在中間作爲一個嚮導,
        告訴第一次訪問數據的客戶端,你須要的數據是分散在多個主機上,仍是一個節點上。
  Master/Slave機制:
    Master可以處理全部請求,Slave僅作爲運算器分擔部分讀運算任務,Master須要控制給Slave發送數據,
   因此Master也是一種控制器。
算法

運算器的變化:  【暫時理解不深】
存儲器的變化: 【暫時理解不深】

分佈式系統實現的難點:
  1.缺少全局時鐘: 在單機中,CPU的每秒中能產生不少個時鐘頻率,可是其它部件的功能頻率相對與CPU來講是極慢的,爲了達到步調一致,單機內部經過中斷等機制實現協同工做。
  2.面對故障時的獨立性
  3.處理單點故障
  4.事務處理:
    ACID
    2PC(兩段式提交)、BASE、CAP、Paxos(帕克索斯:希臘神話中的天馬)

  大型網站站點的架構演進方式:
    LAMT, LNMT(Tomcat)

  應用從資源佔用的角度分兩類:
    CPU Bound: CPU密集型,ApplicationServer對CPU佔用多。
    IO Bound: IO密集型, 數據庫對IO佔用多。

 網站從最開始一臺主機上運行一個Nginx代理 + Tomcat應用服務器 + MySQL數據庫.數據庫

  

  當網站訪問量增大時,首先出現告警的多是MySQL數據庫,由於磁盤I/O天生是系統的瓶頸,所以數據庫先被分離出來,這樣數據庫壓力就變小了。
  引入MySQL主從面臨的問題:
    1. 數據複製的問題
    2. 應用選擇數據源的問題編程

  

    接着網站訪問量繼續增大,Tomcat這類應用服務器,Nginx代理等都屬於CPU密集型,它們在單機上出現了CPU資源爭用的問題,這僅是小問題,更重要的是應用服務器出現了數據訪問的熱區,基本上會遵循二八定律,這時就必須分離,而且增長應用服務器,你的系統就變成了兩臺應用服務器,這時前端必須有一個反向代理,因此加上MySQL就是四臺主機.但應用服務器分開後,就須要用戶訪問的會話保存問題,有如下三種解決方案:
  Session sticky:會話粘性,存在單點故障,必定其中一臺Server宕機,會話將丟失。
  ip based:
  cookie based:它帶來的額外問題是,帶寬佔用將很是巨大,若一個cookie僅50字節,可是若一天一億個請求,就有一億個50字節,有多大?
  Session replication: 會話複製,不適合大規模使用,由於一方面會消耗Server的內存,另外一方會帶來大量的內網同步Session的流量,影響總體網絡環境。
  Session server:經過Memcached來集中存儲用戶會話,擴展性好,適合大規模擴展。
若考慮到網站在一年內可能出現幾何增加的可能,如:從200併發到過萬的併發,這時使用前兩種會話保存就不合適了,就必須使用第三種方案。後端

  

引入搜索引擎實現全文搜索:
  網站演變到這裏,咱們須要知道問題的核心在哪裏,數據庫中的數據最終是要讓用戶能夠查詢到的,由於 用戶不能在你的網站一個一個網頁去翻,而後去找到本身須要的商品,一般都是經過搜索定位到他們須要的商品,那這時僅靠MySQL很難實現了,由於咱們的電商網站的數據庫是須要支持事務,但MyISAM存儲引擎支持全文索引,但不支持事務,因此它並不是最佳途徑,咱們就須要另拿一臺服務器專門安裝MySQL使用支持全文索引的存儲引擎,將現有MySQL的Slave節點上將數據都讀出來,在它上面作全文索引,而後,前端本身開發的索引引擎,經過搜索全文索引數據庫,來響應用戶的搜索請求,因此Slave讀取Master上數據的及時性就顯得很重要了,由於新上架是商品可否讓用戶看到,取決於搜索庫中有沒有從Slave庫中讀到新商品數據。緩存

  

引入緩存
  當咱們的網站中應用服務器的壓力主要集中在對不少靜態內容的處理上時,那咱們就須要使用動靜分離技術,但比它更使用的此時應該是緩存,在負載均衡器後面第一級,先引入緩存,把不變化的靜態內容直接緩存在應用服務器的前端緩存服務器中,甚至還可使用AJAX技術實現緩存網頁中的一部分數據,另一部分變化的數據,到後端去計算後獲得,好比一個淘寶頁面,第一用戶看商品頁面和第二個用戶看的商品頁面是同樣的,這時就能夠緩存這個頁面,但有可能第二個用戶看時,這個商品已經賣出去了2個,因此僅須要從後端應用服務器上獲取這部分變化的庫存量信息就能夠了,這樣能夠更大程度減小後端的壓力。
  引入緩存要考慮兩個方面的問題:
  1.頁面緩存
    varnish, squid
  2.數據庫緩存
    由於數據庫節點可能也會逐漸增長,而查詢緩存僅在數據庫本地有效,爲了提升命中率,增長數據庫緩存也是必須的。
    對於數據庫緩存,要使用Key-Value類型的存儲,而Memcached是其中最具表明性的。
  若引入Memcached,將會引入新問題:
    a. 須要自行開發程序調用Memcached的API實現存儲。
    b. 須要自行管理其數據有效期。
   注意:
    引入緩存,可能不會只有一臺,或者說會逐漸增長成多臺,這時咱們就能夠稱這種緩存架構爲分佈式緩存,在分佈式緩存中,要提升數據的命中率,就必須使用哈希算法,來提升命中率。安全

    

當網站規模繼續增大時,接下來面臨壓力的必定就是數據庫的寫庫。
對於數據庫寫庫的分擔,只有數據庫拆分這一條路.
  垂直拆分:把數據庫中不一樣的業務的數據拆分到不一樣的數據庫中,它緩解的是讀壓力.
    假如以電商網站來講:將它的用戶表,交易表,商品表分別分到三個庫,但咱們知道,
    咱們到淘寶上買的東西,咱們會去搜索用戶嗎?會搜索其餘人的交易信息嗎?
    不會,甚至也不容許,因此商品表被讀的壓力就會很大,所以它是必定要作主從的,
    其它庫能夠從數據安全性角度來講,也能夠作主從。
    因爲數據庫級別拆分紅多個了,這時咱們訪問數據庫就必需要知道咱們訪問的數據在哪裏
    因此前端應該還要有規則服務器來告知前端應用數據在那臺後端數據庫上。服務器

  

    靜態內容: 如用戶證書,用戶生物信息,交易歷史記錄,商品圖片等
    FTP上傳: 如: 商品圖片,用戶身份證圖片,文檔等

水平拆分:把一個單獨的表中的數據拆分到多個不一樣的數據庫服務器中,它緩解的是寫壓力。
    假如立刻要到剁手節,將產生大量用戶產生交易信息,交易表可能受不了,那怎麼辦?
  這就須要分擔對交易表的寫壓力,對交易表咱們能夠根據用戶年齡來拆分,將年輕羣體
  中消費能力弱的18-20的分到一張表,消費能力較強的21-25分一張表,26-29分一張表,
  等等,來拆分表,可是表拆分完了後,該怎麼去訪問?前端應用怎麼知道我要訪問的數據
  在哪裏存儲?由此規則服務就更加劇要了。cookie

  

  引入NoSQL: 非關係型數據庫
  文檔數據庫
  列式數據庫
  ....

DFS: 非結構化數據
TFS, MogileFS: 適用於海量小文件
HDFS, GFS: 少許大文件

  

CDN的使用:
  越向後,系統的訪問量越大,這時內部整個機房的擴容若在繼續擴大,不在是解決問題最有效的手段,並且主機數量也總有上限,可是前端的壓力已經讓負載和緩存吃不消了,在這時最佳的手段就是引入CDN,目前國內比較知名的CDN廠家有 BAT,藍汛等。 CDN它可以實現讓用戶直接在家門口的緩存服務器上獲取要咱們的網站數據,這樣就有效的分散了到達咱們主站的流量壓力,當用戶訪問咱們網站時,智能DNS一般會,根據用戶所在地區爲用戶解析域名,它會依據緩存服務器距離用戶地理位置最近,或帶寬最大等信息,作智能判斷並返回用戶一個域名,這個域名一般是一個負載均衡器的域名,用戶進行二次解析後,獲得距離本身最近的緩存集羣,該緩存集羣的負載均衡器將用戶請求接入進來,在後端緩存服務器上查詢,若命中,則直接返回數據給用戶,若未命中,則向最近的緩存節點查詢,無數據則由該緩存節點,向咱們網站發起請求,網站響應該請求時,先查詢本地緩存,命中則直接返回,未命中則繼續向下,到應用服務器,由應用服務器處理此請求,並經過查詢數據庫等一系列業務邏輯處理,返回結果給CDN的緩存節點,由該節點再向用戶返回數據。

  

應用拆分:
  根據業務特性拆分
  根據用戶拆分
    如: 用戶註冊應用
      用戶登陸應用
      用戶信息維護應用
  根據對底層應用的調用進行拆分

異步: 解耦
  消息中間件:
    它是協調多個應用之間,經過消息傳遞的方式來實現其功能協調的機制,它的整個工做過程是
   經過異步方式實現的。因此它在分佈式系統中,是消息接收和發送的基礎性軟件。
  它最大的特色就是:異步和解耦。
  MOM:Message-oriented middleware.
  現有的比較知名的消息中間件:
    RabbitMQ, ActiveMQ, ZeroMQ(ZMQ)
  注: 它們僅能工做於它們支持的模型中。
  模塊化:

    

    服務化:

    

     當網站的結構發展到服務化後,每一個層均可能出現大量重複代碼,但這是不可避免的。

 一旦架構進入這樣的級別,不管是垂直仍是水平拆分都會面臨ACID被打破的問題,此時只有兩種選擇,放棄事務 或 引入分佈式事務! 在進行Join查詢時,也將變得異常困難,原來依賴與外鍵實現的約束將無從保證等等問題,都將面臨巨大的挑戰。面對這些挑戰,咱們惟一能作到就是從理論出發,結合實際去構建適合本身實際需求的解決方案。

相關文章
相關標籤/搜索