可伸縮架構簡短系列

採起什麼辦法可讓一個Web服務可大規模可擴展?相信你會對這個問題感興趣。前端

克隆

一般來講,公共服務器上的一個可伸縮的web服務老是隱藏在一個Load Balancer(負載均衡器)以後。這個負載均衡器會將負載(來自用戶的請求)均勻的分配到一組服務器或者服務器集羣。那意味着什麼?舉個例子:某個用戶訪問你的服務,他第一次的請求可能會由第二臺服務器提供,第二次請求由第9臺服務器提供,第3次請求又再次由第二臺服務器提供。git

對於該用戶而言,他每次獲得的結果應該是同樣的,不依賴服務究竟是哪臺服務器提供的。這個正是可伸縮性的第一個黃金法則:每一個服務器都包含徹底相同的代碼庫,不在本地磁盤或內存存儲任何與用戶相關的數據,如session或用戶信息。Session須要集中存儲,使得每一臺服務器均可以訪問到它。它能夠是一個外部數據庫或外部持久緩存,好比Redis。相比外部數據庫,在持久化的緩存中存放session將會有更好的性能。這裏提到的「外部」指的是數據存儲不放置在這些應用服務器上,而是在接近您的應用程序服務器的數據中心。github

可是這要怎麼部署呢?你如何肯定當應用代碼發生了改變可以發送到全部的服務器而沒有一臺服務器依舊使用以前的代碼?幸運的是,這個棘手的問題已經被一個很好的工具capistrano解決了,你須要稍微學習瞭解下。web

在解決了session和多臺服務器上新版本的同步更新問題以後,你須要作的就是克隆你的機器鏡像了,而後將你最新的代碼部署上去。能夠參考Amazon提供的AMI服務(Amazon Machine Image)redis

如今你的服務器能夠水平擴展,而且處理成千上萬的併發請求了。數據庫

數據庫

可是你發現應用程序變得愈來愈來最終崩潰。問題的緣由:是MySql,不是嗎?
如今不是增長更多的機器能夠解決的問題了,你有兩種辦法:apache

  • 1,堅持使用MySql,而且讓它運行良好。作主從複製(從服務器負責讀取,主服務器負責寫入),而且升級主服務器,不斷加入更多的內存。隨着不斷優化,你會使用數據庫分片、反規模化、SQL調優等經常使用手段。這時,對於數據庫的任何一個操做成本都會變得至關昂貴。
  • 2,切換到一個更加容易擴展的NoSQL數據庫,好比 MongoDB或CouchDB,鏈接查詢如今須要在應用代碼層裏去進行了。

如今,你的數據庫有了一個可擴展的解決方案了,你不再用擔憂存儲TB級的數據,世界看起來那麼的美好。api

緩存

當大量的數據請求發往到數據庫,你發現又變慢了,解決辦法是增長緩存。
這裏說的緩存指的是內存緩存,好比常見的內存數據庫Memcached或者Redis ,千萬不要使用文件緩存,它會讓你服務器的克隆和自動伸縮很痛苦。緩存

可是回到內存緩存,緩存是一個簡單的鍵值存儲而且應該介於應用程序和數據存儲。任什麼時候候當你的應用程序須要去讀取數據時,它首先應該嘗試從緩存裏面獲取數據,只有沒法從緩存中讀取數據時,纔會嘗試從數據庫中讀到。爲何要這麼作呢?由於緩存快如閃電,它將數據集存放在內存中,而且能夠快速的被處理。舉個例子:Redis沒秒鐘能夠處理成千上萬的讀操做。服務器

訪問流程:第一次訪問綠色,第二次和以後的藍色:

有兩種緩存數據的模式,一種是老的方式,一種是新的方式:

  • 1,緩存數據庫查詢,這個仍然是最廣泛的緩存方式,當你作一次查詢時,將數據集進行緩存,經過哈希後查詢串做爲鍵。下一次查詢時,檢查緩存中是否有結果。這種方式存在一些問題,最主要的問題就是過時。當數據表中的一塊數據發生變化時,你須要刪除全部包含這個數據塊的查詢串的緩存。
  • 2,緩存對象,我強烈推薦使用這種方式,這也是我常用的。

一些適合緩存的對象:

  • 用戶Session(永遠不存放在數據庫中)
  • 徹底呈現的博客文章
  • 活動流
  • 用戶<- -> 朋友 之類的關係

異步

請想象一下,你想在你最喜歡的麪包店買麪包,因此你走進麪包店,向一個店員詢問購買麪包,可是麪包都賣光了。你被告知2個小時以後你訂的麪包能夠好,這個很惱人,不是嗎?
爲了不這種「請等片刻」的場景,須要採起異步。好比何時有面包了,店員會將麪包派送給你的家裏。一般來講,有兩種異步的範例:

  • 1,讓咱們回到普通的買麪包的場景,第一種異步處理流程是:「晚上把麪包都烹製好,次日早上賣」,這個對於顧客來講不須要等待。對於一個web應用程序,這意味着提早作耗時的工做,這樣就能夠在短期處理完工做。一般這種模式用來將動態的內容轉換爲靜態內容。好比提早渲染好CMS裏面的一些網頁,而且本地存儲這些HTML文件。採用定時任務,多是經過腳本叫作每小時的計劃。這種對通用數據預先計算能夠極大的提高網站和web app的可伸縮性和性能。能夠經過腳本將這些預先渲染好的HTML頁面發佈至CDN。你的網站將能作到響應超快而且每小時能夠處理成千上萬的遊客!
  • 2,回到麪包店,有的時候顧客可能會有一些特殊的需求,否則在麪包上加上「生日快樂」等裝飾。麪包店並不能提早知道這種顧客類型的需求,因此當顧客來到店裏後,必須立刻開啓一個任務而且告訴他:」你明天再來吧!「 對於web而言,這意味着異步任務。這裏有一個典型的工做流:一個用戶來到你的網站,開始一項計算密集型任務,這個任務須要花費幾分鐘來完成,因此網站前端會往任務隊列裏面發送一個任務,而且告訴用戶你的任務已經在處理中了,你能夠繼續瀏覽網頁了。一個任務隊列會不斷的被處理任務的workers 檢查處理。若是有一個新任務,work會處理這個任務,過了幾分鐘以後會發送一個處理完畢的消息信號。前端會不斷的檢查(好比輪詢)這個任務是否已經處理完,一旦處理完則通知用戶。若是你想更深刻了解,推薦你去看看RabbmitMQ),Rabbit MQ是一個實現了異步消息隊列的優秀中間件。你也可使用ActiveMQ或者一個簡單的Redis list,異步消息隊列看起來很複雜,可是它值得你花時間去學習和實現。

若是你作一些耗時的操做,試着採用異步。

相關文章
相關標籤/搜索