如何構建日均千萬PV Web站點 (三) Sharding

        其實國內許多大型網站爲了應對日益複雜的業務場景,經過使用分而治之的手段將整個網站業務分紅不一樣的產品線,好比說國內那些大型購物交易網站它們都將本身的網站首頁、商鋪、訂單、買家、賣家等拆分不一樣的產品線,分歸不一樣的業務團隊負責;數據庫

    集體到技術,也會根據產品線劃分,將一個網站拆分紅許多不一樣的應用,每一個應用用獨立部署維護。應用之間能夠經過一個超連接創建關係(在首頁上的導航連接每一個都指向不一樣的應用地址),也能夠經過消息隊列進行數據分發,固然最多的仍是經過訪問同一個數據庫存儲系統來構成一個關聯的完整系統 此時的架構以下圖所示:服務器

  分佈式服務,隨着業務拆分愈來愈小,存儲系統愈來愈龐大,應用系統的總體複雜度呈指數級增長,部署維護愈來愈困難,因爲全部應用要和全部數據庫系統鏈接,在數萬臺服務器規模的網站中,這些鏈接的數目是服務器規模的平方,致使數據庫鏈接資源不足,拒絕服務。架構

  既然每個應用系統都須要執行許多相同的業務操做,好比用戶管理、商品管理等,那麼能夠將這些共用的業務提取出來,獨立部署。由這些可複用的業務鏈接數據庫,提供共用服務,而應用系統只須要管理用戶界面,經過分佈式服務調用共用業務服務完成具體業務操做分佈式

數據庫如何sharding?模塊化

數據的切分(Sharding)根據其切分規則的類型,能夠分爲兩種切分模式。一種是按照 不一樣的表(或者 Schema)來切分到不一樣的數據庫(主機)之上,這種切能夠稱之爲數據的 垂直(縱向)切分;另一種則是根據表中的數據的邏輯關係,將同一個表中的數據按照某 種條件拆分到多臺數據庫(主機)上面,這種切分稱之爲數據的水平(橫向)切分。 垂直切分的最大特色就是規則簡單,實施也更爲方便,尤爲適合各業務之間的耦合度非 常低,相互影響很小,業務邏輯很是清晰的系統。在這種系統中,能夠很容易作到將不一樣業 務模塊所使用的表分拆到不一樣的數據庫中。根據不一樣的表來進行拆分,對應用程序的影響也 更小,拆分規則也會比較簡單清晰。 水平切分於垂直切分相比,相對來講稍微複雜一些。由於要將同一個表中的不一樣數據拆 分到不一樣的數據庫中,對於應用程序來講,拆分規則自己就較根據表名來拆分更爲複雜, 後期的數據維護也會更爲複雜一些。 當咱們某個(或者某些)表的數據量和訪問量特別的大,經過垂直切分將其放在獨立的 設備上後仍然沒法知足性能要求,這時候咱們就必須將垂直切分和水平切分相結合,先垂直 切分,而後再水平切分,才能解決這種超大型表的性能問題。 下面咱們就針對垂直、水平以及組合切分這三種數據切分方式的架構實現及切分後數據 的整合進行相應的分析。 14.2 數據的垂直切分 咱們先來看一下,數據的垂直切分究竟是如何一個切分法的。數據的垂直切分,也能夠 稱之爲縱向切分。將數據庫想象成爲由不少個一大塊一大塊的「數據塊」(表)組成,咱們 垂直的將這些 「數據塊」切開,而後將他們分散到多臺數據庫主機上面。這樣的切分方法就 是一個垂直(縱向)的數據切分。 一個架構設計較好的應用系統,其整體功能確定是由不少個功能模塊所組成的,而每一 個功能模塊所須要的數據對應到數據庫中就是一個或者多個表。而在架構設計中,各個功能 模塊相互之間的交互點越統一越少,系統的耦合度就越低,系統各個模塊的維護性以及擴展 性也就越好。這樣的系統,實現數據的垂直切分也就越容易。 當咱們的功能模塊越清晰,耦合度越低,數據垂直切分的規則定義也就越容易。徹底可 以根據功能模塊來進行數據的切分,不一樣功能模塊的數據存放於不一樣的數據庫主機中,能夠 很容易就避免掉跨數據庫的 Join 存在,同時系統架構也很是的清晰.性能

固然,很難有系統可以作到全部功能模塊所使用的表徹底獨立,徹底不須要訪問對方的 表或者須要兩個模塊的表進行 Join 操做。這種狀況下,咱們就必須根據實際的應用場景進 行評估權衡。決定是遷就應用程序將須要 Join 的表的相關某快都存放在同一個數據庫中, 仍是讓應用程序作更多的事情,也就是程序徹底經過模塊接口取得不一樣數據庫中的數據, 然 後在程序中完成 Join 操做。 通常來講,若是是一個負載相對不是很大的系統,並且表關聯又很是的頻繁,那可能數 據庫讓步,將幾個相關模塊合併在一塊兒減小應用程序的工做的方案能夠減小較多的工做量, 是一個可行的方案。 固然,經過數據庫的讓步,讓多個模塊集中共用數據源,實際上也是簡介的默許了各模 塊架構耦合度增大的發展,可能會讓之後的架構愈來愈惡化。尤爲是當發展到必定階段以後 , 發現數據庫實在沒法承擔這些表所帶來的壓力,不得不面臨再次切分的時候,所帶來的架構 改形成本可能會遠遠大於最初的時候。 因此,在數據庫進行垂直切分的時候,如何切分,切分到什麼樣的程度,是一個比較考 驗人的難題。只能在實際的應用場景中經過平衡各方面的成本和收益,才能分析出一個真正 適合本身的拆分方案。 好比在本書所使用示例系統的 example 數據庫,咱們簡單的分析一下,而後再設計一 個簡單的切分規則,進行一次垂直垂直拆分。 系統功能能夠基本分爲四個功能模塊:用戶,羣組消息,相冊以及事件,網站

分別對應爲如 下這些表:

1. 用戶模塊表:user,user_profile,user_group,user_photo_album

2. 羣組討論表:groups,group_message,group_message_content,top_message

3. 相冊相關表:photo,photo_album,photo_album_relation,photo_comment

 

4. 事件信息表:event 初略一看,沒有哪個模塊能夠脫離其餘模塊獨立存在,模塊與模塊之間都存在着關係 , 莫非沒法切分? 固然不是,咱們再稍微深刻分析一下,能夠發現,雖然各個模塊所使用的表之間都有關 聯,可是關聯關係還算比較清晰,也比較簡單。 羣組討論模塊和用戶模塊之間主要存在經過用戶或者是羣組關係來進行關聯。通常 關聯的時候都會是經過用戶的 id 或者 nick_name 以及 group 的 id 來進行關 聯,經過模塊之間的接口實現不會帶來太多麻煩; 相冊模塊僅僅與用戶模塊存在經過用戶的關聯。這兩個模塊之間的關聯基本就有通 過用戶 id 關聯的內容,簡單清晰,接口明確; 事件模塊與各個模塊可能都有關聯,可是都只關注其各個模塊中對象的 ID信息 , 一樣能夠作到很容易分拆。 因此,咱們第一步能夠將數據庫按照功能模塊相關的表進行一次垂直拆分,每一個模塊所 涉及的表單獨到一個數據庫中,模塊與模塊之間的表關聯都在應用系統端經過藉口來處理。 以下圖所示:spa

經過這樣的垂直切分以後,以前只能經過一個數據庫來提供的服務,就被分拆成四個數 據庫來提供服務,服務能力天然是增長几倍了。 架構設計

垂直切分的優勢設計

一、數據庫的拆分簡單明瞭,拆分規則明確;

二、應用程序模塊清晰明確,整合容易;

三、數據維護方便易行,容易定位;

垂直切分的缺點

一、部分表關聯沒法在數據庫級別完成,須要在程序中完成;

二、對於訪問極其頻繁且數據量超大的表仍然存在性能平靜,不必定能知足要求;

三、事務處理相對更爲複雜;

四、切分達到必定程度以後,擴展性會遇到限制;

五、過讀切分可能會帶來系統過渡複雜而難以維護。

  針對於垂直切分可能遇到數據切分及事務問題,在數據庫層面實在是很難找到一個較好 的處理方案。實際應用案例中,數據庫的垂直切分大可能是與應用系統的模塊相對應,同一個 模塊的數據源存放於同一個數據庫中,能夠解決模塊內部的數據關聯問題。而模塊與模塊之間,則經過應用程序以服務接口方式來相互提供所須要的數據。雖然這樣作在數據庫的整體 操做次數方面確實會有所增長,可是在系統總體擴展性以及架構模塊化方面,都是有益的。 可能在某些操做的單次響應時間會稍有增長,可是系統的總體性能極可能反而會有必定的提 升。而擴展瓶頸問題,就只能依靠下一節將要介紹的數據水平切分架構來解決了。

   數據的水平切分

   上面一節分析介紹了數據的垂直切分,這一節再分析一下數據的水平切分。數據的垂直 切分基本上能夠簡單的理解爲按照表按照模塊來切分數據,而水平切分就再也不是按照表或者 是功能模塊來切分了。通常來講,簡單的水平切分主要是將某個訪問極其平凡的表再按照某 個字段的某種規則來分散到多個表之中,每一個表中包含一部分數據。 簡單來講,咱們能夠將數據的水平切分理解爲是按照數據行的切分,就是將表中的某些 行切分到一個數據庫,而另外的某些行又切分到其餘的數據庫中。固然,爲了可以比較容易的斷定各行數據被切分到哪一個數據庫中了,切分老是都須要按照某種特定的規則來進行的。 如根據某個數字類型字段基於特定數目取模,某個時間類型字段的範圍,或者是某個字符類 型字段的 hash 值。若是整個系統中大部分核心表均可以經過某個字段來進行關聯,那這個 字段天然是一個進行水平分區的上上之選了,固然,很是特殊沒法使用就只能另選其餘了。 通常來講,像如今互聯網很是火爆的 Web2.0 類型的網站,基本上大部分數據都可以通 過會員用戶信息關聯上,可能不少核心表都很是適合經過會員 ID 來進行數據的水平切分。 而像論壇社區討論系統,就更容易切分了,很是容易按照論壇編號來進行數據的水平切分。 切分以後基本上不會出現各個庫之間的交互。 如咱們的示例系統,全部數據都是和用戶關聯的,那麼咱們就能夠根據用戶來進行水平 拆分,將不一樣用戶的數據切分到不一樣的數據庫中。固然,惟一有點區別的是用戶模塊中的 groups 表和用戶沒有直接關係,因此 groups 不能根據用戶來進行水平拆分。對於這種特 殊狀況下的表,咱們徹底能夠獨立出來,單獨放在一個獨立的數據庫中。其實這個作法能夠 說是利用了前面一節所介紹的 「數據的垂直切分」方法,我將在下一節中更爲詳細的介紹這 種垂直切分與水平切分同時使用的聯合切分方法。 因此,對於咱們的示例數據庫來講,大部分的表均可以根據用戶 ID 來進行水平的切分 。 不一樣用戶相關的數據進行切分以後存放在不一樣的數據庫中。如將全部用戶 ID 經過 2 取模 而後分別存放於兩個不一樣的數據庫中。每一個和用戶 ID 關聯上的表均可以這樣切分。這樣, 基本上每一個用戶相關的數據,都在同一個數據庫中,即便是須要關聯,也能夠很是簡單的關 聯上。 咱們能夠經過下圖來更爲直觀的展現水平切分相關信息:

水平切分的優勢

一、表關聯基本可以在數據庫端所有完成;

二、不會存在某些超大型數據量和高負載的表遇到瓶頸的問題;

三、應用程序端總體架構改動相對較少; 事務處理相對簡單;

四、只要切分規則可以定義好,基本上較難遇到擴展性限制;

水平切分的缺點

一、切分規則相對更爲複雜,很難抽象出一個可以知足整個數據庫的切分規則;

二、後期數據的維護難度有所增長,人爲手工定位數據更困難;

三、應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分形成必定的困難。

    垂直與水平聯合切分的使用

    上面兩節內容中,咱們分別,瞭解了「垂直」和「水平」這兩種切分方式的實現以及切 分以後的架構信息,同時也分析了兩種架構各自的優缺點。可是在實際的應用場景中,除了 那些負載並非太大,業務邏輯也相對較簡單的系統能夠經過上面兩種切分方法之一來解決 擴展性問題以外,恐怕其餘大部分業務邏輯稍微複雜一點,系統負載大一些的系統,都沒法 經過上面任何一種數據的切分方法來實現較好的擴展性,而須要將上述兩種切分方法結合使 用,不一樣的場景使用不一樣的切分方法。 在這一節中,我將結合垂直切分和水平切分各自的優缺點,進一步完善咱們的總體架構 , 讓系統的擴展性進一步提升。 通常來講,咱們數據庫中的全部表很難經過某一個(或少數幾個)字段所有關聯起來, 因此很難簡單的僅僅經過數據的水平切分來解決全部問題。而垂直切分也只能解決部分問 題,對於那些負載很是高的系統,即便僅僅只是單個表都沒法經過單臺數據庫主機來承擔其 負載。咱們必須結合「垂直」和「水平」兩種切分方式同時使用,充分利用二者的優勢,避 開其缺點。 每個應用系統的負載都是一步一步增加上來的,在開始遇到性能瓶頸的時候,大多數 架構師和 DBA 都會選擇先進行數據的垂直拆分,由於這樣的成本最早,最符合這個時期所追 求的最大投入產出比。然而,隨着業務的不斷擴張,系統負載的持續增加,在系統穩定一段 時期以後,通過了垂直拆分以後的數據庫集羣可能又再一次不堪重負,遇到了性能瓶頸。 這時候咱們該如何抉擇?是再次進一步細分模塊呢,仍是尋求其餘的辦法來解決?若是 咱們再一次像最開始那樣繼續細分模塊,進行數據的垂直切分,那咱們可能在不久的未來, 又會遇到如今所面對的一樣的問題。並且隨着模塊的不斷的細化,應用系統的架構也會越來 越複雜,整個系統極可能會出現失控的局面。 這時候咱們就必需要經過數據的水平切分的優點,來解決這裏所遇到的問題。並且, 咱們徹底沒必要要在使用數據水平切分的時候,推倒以前進行數據垂直切分的成果,而是在其基 礎上利用水平切分的優點來避開垂直切分的弊端,解決系統複雜性不斷擴大的問題。而水平 拆分的弊端(規則難以統一)也已經被以前的垂直切分解決掉了,讓水平拆分能夠進行的駕輕就熟。 對於咱們的示例數據庫,假設在最開始,咱們進行了數據的垂直切分,然而隨着業務的 不斷增加,數據庫系統遇到了瓶頸,咱們選擇重構數據庫集羣的架構。如何重構?考慮到之 前已經作好了數據的垂直切分,並且模塊結構清晰明確。而業務增加的勢頭愈來愈猛,即便 如今進一步再次拆分模塊,也堅持不了過久。咱們選擇了在垂直切分的基礎上再進行水平拆分。 在經歷過垂直拆分後的各個數據庫集羣中的每個都只有一個功能模塊,而每一個功能模 塊中的全部表基本上都會與某個字段進行關聯。如用戶模塊所有均可以經過用戶ID進行切分,羣組討論模塊則都經過羣組ID來切分,相冊模塊則根據相冊ID來進切分,最後的事 件通知信息表考慮到數據的時限性(僅僅只會訪問最近某個事件段的信息),則考慮按時間 來切分。 下圖展現了切分後的整個架構:

實際上,在不少大型的應用系統中,垂直切分和水平切這兩種數據的切分方法基本上都 是並存的,並且常常在不斷的交替進行,以不斷的增長系統的擴展能力。咱們在應對不一樣的 應用場景的時候,也須要充分考慮到這兩種切分方法各自的侷限,以及各自的優點,在不一樣的時期(負載壓力)使用不一樣的結合方式。

聯合切分的優勢

一、能夠充分利用垂直切分和水平切分各自的優點而避免各自的缺陷;

二、讓系統擴展性獲得最大化提高;

聯合切分的缺點

一、數據庫系統架構比較複雜,維護難度更大;

二、應用程序架構也相對更復雜。

關於數據庫如何sharding詳情請參考<<MySQL性能調優與架構設計>>

相關文章
相關標籤/搜索