關於大型網站技術演進的思考(二)--存儲的瓶頸(2)

  上篇裏我講到某些網站在高併發下會報出503錯誤,503錯誤的含義是指網站服務端暫時沒法提供服務的含義,503還表達了網站服務端如今有問題可是之後可能會提供正常的服務,對http協議熟悉的人都知道,5開頭的響應碼錶達了服務端出現了問題,在咱們開發測試時候最爲常見的是500錯誤,500表明的含義是服務端程序出現了錯誤致使網站沒法正常提供服務,500一般是服務端異常和錯誤所致,若是生產系統裏發現了500錯誤,那麼只能說明網站存在邏輯性的錯誤,這每每是系統上線前的測試作的不到位所致。回到503錯誤,我上文解釋爲拒絕訪問,其實更加準確的回答應該是服務不可用,那麼爲何我會說503錯誤在高併發的狀況下90%的緣由是數據庫所致呢?上文我作出了詳細的解釋,可是今天我回味了一下,發現那個解釋還不是太突出重點,問題的重點是在高併發的狀況整個網站系統首先暴露出問題的是數據庫,若是咱們把整個網站系統比做一個盛水的木桶,那麼木桶最短的那個板就是數據庫了,通常而言網站的服務應用出問題都會是解決存儲問題以後纔會出現web

       數據庫出現了瓶頸並非程序存在邏輯性錯誤,數據庫瓶頸的表現就是數據庫由於承受了太多的訪問後,數據庫沒法迅速的作出響應,嚴重時候數據庫會拒絕進一步操做死鎖在哪裏不能作出任何反應。數據庫猶如一把巨型的大鎖,不少人爭搶這個鎖時候會致使這個大鎖徹底被鎖死,最終請求的處理就停留在這個大鎖上最終致使網站提示出503錯誤,503錯誤最終會傳遞到全部的客戶端上,最終的現象就是全站不可用了。算法

       上文裏我講到session共享的一個方案是將session數據存儲在外部一個獨立的緩存服務器裏,我開始說用一臺服務器作緩存服務器,後面提到若是以爲一臺服務器作緩存不安全,那麼採用分佈式緩存服務器例如memcached,那麼這裏就有一個問題了,爲了保證web服務的可用性,咱們會把web服務分開部署到不一樣的服務器上,這些服務器都是對等關係,其中一臺服務器不能正常提供服務不會影響到整個網站的穩定性,那麼咱們採起memcached集羣是否是能夠達到一樣的效果了?即緩存服務器集羣中一臺服務器掛掉,不會影響到用戶對網站的使用了?問題的答案是使人失望了,假如咱們使用兩臺服務器作緩存服務器來存儲session信息,那麼若是其中一臺服務器掛掉了,那麼網站將會有一半的用戶將不能正常使用網站,緣由是他們的session信息丟失了,網站沒法正常的跟蹤用戶的會話狀態。我之因此提到這個問題是想告訴你們以memcached爲表明的分佈式緩存和咱們傳統理解的分佈式系統是有區別的,傳統的分佈式系統都會包含一個容災維護系統穩定性的功能,但實際的分佈式技術是多種多樣的,例如memcached的分佈式技術並非爲了解決容災維護系統穩定性的模式設計,換個說法就是memcached集羣的設計是沒有過度考慮冗餘的問題,而只有適當的冗餘才能保證系統的健壯性問題。分佈式技術的實現是千差萬別的,每一個優秀的分佈式系統都有自身獨有的特色。數據庫

       全面的講述memcached技術並不是本文的主題,並且這個主題也不是一兩句話能說清楚的,這裏我簡單的介紹下memcached實現的原理,當網站使用緩存集羣時候,緩存數據是經過必定的算法將緩存數據儘可能均勻分不到不一樣服務器上,若是用戶A的緩存在服務器A上,那麼服務器B上是沒有該用戶的緩存數據,早期的memcache數據分佈式的算法是根據緩存數據的key即鍵值計算出一個hash值,這個hash值再除以緩存服務器的個數,獲得的餘數會對應某一臺服務器,例如1對應服務器A,2對應服務器B,那麼餘數是1的key值緩存就會存儲在服務器A上,這樣的算法會致使某一臺服務器掛掉,那麼網站損失的緩存數據的佔比就會比較高,爲了解決這個問題,memcached引入了一致性hash算法。關於一致性hash網上有不少資料,這裏我就貼出一個連接,本文就不作過多論述了。連接地址以下:緩存

http://blog.csdn.net/kongqz/article/details/6695417安全

      一致性hash能夠服務器宕機時候這臺服務器對整個緩存數據的影響最小。服務器

      上文裏我講到了讀寫分離的設計方案,而讀寫分離方案主要是應用於網站讀寫比例嚴重失衡的網站,而互聯網上絕大部分網站都是讀操做的比例遠遠大於寫操做,這是網站的主流,若是一個網站讀寫比例比較均衡,那麼這個網站通常都是提供專業服務的網站,這種網站對於我的而言是一個提供生活便利的工具,它們和企業軟件相似。大部分關注大型網站架構技術關心的重點應該是那種對於讀寫比例失衡的網站,由於它們作起來更加有挑戰性。session

      將數據庫進行讀寫分離是網站解決存儲瓶頸的第一步,爲何說是第一步呢?由於讀寫分離從業務角度而言它是一種粗粒度的數據拆分,所以它所包含的業務複雜度比較低,容易操做和被掌控,從技術而言,實現手段也相對簡單,所以讀寫分離是一種低成本解決存儲瓶頸的一種手段,這種方案是一種改良方案而不是革命性的的方案,不論是從難度,仍是影響範圍或者是經濟成本角度考慮都是很容易讓相關方接受的。架構

      那麼咱們僅僅將數據庫作讀寫分離爲什麼能產生好的效率了?回答這個問題咱們首先要了解下硬盤的機制,硬盤的物理機制就有一個大圓盤飛速旋轉,而後有個磁頭不斷掃描這個大圓盤,這樣的物理機制就會致使硬盤數據的順序操做比隨機操做效率更高,這點對於硬盤的讀和寫還算公平,可是寫操做在高併發狀況下會有點複雜,寫操做有個特性就是咱們要保證寫操做的準確性,可是高併發下可能會出現多個用戶同時修改某一條數據,爲了保證數據能被準確的修改,那麼咱們一般要把並行的操做轉變爲串行操做,這個時候就會出現一個鎖機制,鎖機制的實現是很複雜的,它會消耗不少系統性能,若是寫操做摻雜了讀操做狀況就更復雜,效率會更加低效,相對於寫操做讀操做就單純多了,若是咱們的數據只有讀操做,那麼讀的性能也就是硬盤順序讀能力和隨機讀能力的體現,即便摻雜了併發也不會對其有很大的影響,所以若是把讀操做和寫操做分離,效率天然會獲得很大提高。併發

      既然讀寫分離能夠提高存儲系統的效率,那麼爲何咱們又要引入緩存系統和搜索技術了?緩存將數據存在內存中,內存效率是硬盤的幾萬倍,這樣的好處不言而喻,而選擇搜索技術的背後的原理就不一樣了,數據庫存儲的數據稱之爲結構化數據,結構化數據的限制不少,當結構化數據遇到了變幻無窮的隨機訪問時候,其效率會變得異常低效,可是若是一個網站不能提供靈活、高效的隨機訪問能力,那麼這個網站就會變得單板沒有活力,例如咱們在淘寶裏查找咱們想要的商品,可是時常咱們並不清楚本身到底想買啥,若是是在實體店裏店員會引導咱們的消費,可是網站又如何引導咱們的消費,那麼咱們必需要賦予網站經過人們簡單意向隨機找到各類不一樣的商品,這個對於數據庫就是一個like操做的,可是數據裏數據量達到了必定規模之後like的低效是沒法讓人忍受的,這時候搜索技術在隨機訪問的能力正好能夠彌補數據庫這塊的不足。分佈式

     業務再接着的增加下去,數據量也會隨之愈來愈大了,這樣發展下去總有一天主庫也會產生瓶頸了,那麼接下來咱們又該如何解決主庫的瓶頸了?方法很簡單就是咱們要拆分主庫的數據了,那麼我該以什麼維度拆分數據了?一個數據庫裏有不少張表,不一樣的表都針對不一樣的業務,網站的不一樣業務所帶來的數據量也不是不一樣的,這個時候系統的短板就是那些數據量最大的表,因此咱們要把那些會讓數據庫產生瓶頸的表拆出來,例如電商系統裏商品表和交易表每每數據量很是大,那麼咱們能夠把這兩種表創建在單獨的兩個數據庫裏,這樣就拆分了數據庫的壓力,這種作法叫作數據垂直拆分,不過垂直拆分會給原有的數據庫查詢,特別是有事務的相關操做產生影響,這些問題咱們必需要進行改造,關於這個問題,我將在下篇裏進行討論。

     當咱們的系統作完了讀寫分離,數據垂直拆分後,咱們的網站還在迅猛發展,最終必定又會達到新的數據庫瓶頸,固然這些瓶頸首先仍是出如今那些數據量大的表裏,這些表數據的處理已經超出了單臺服務器的能力,這個時候咱們就得對這個單庫單表的數據進行更進一步的拆分,也就是將一張表分佈到兩臺不一樣的數據庫裏,這個作法就是叫作數據的水平拆分了

     Ok,今天內容就講到這裏了,有這兩篇文章咱們能夠理出一個解決大型網站數據瓶頸的一個脈絡了,具體以下:

     單庫數據庫-->數據庫讀寫分離-->緩存技術-->搜索技術-->數據的垂直拆分-->數據的水平拆分

     以上的每一個技術細節在具體實現中可能存在很大的不一樣,可是問題的原因大體是一致的,咱們理清這個脈絡就是想告訴你們咱們若是碰到這樣的問題應該按何種思路進行思考和設計解決方案,好了,今天就寫到這裏了,晚安。

相關文章
相關標籤/搜索