1 何謂數據切分數據庫
不管數據的 Sharding 仍是數據的切分,其實質都是同樣的。簡單來講,就是指經過某種特定的條件,將存放在同一個數據庫中的數據分散存放到多個數據庫(主機)上面,以達到分散單臺設備負載的效果。數據的切分同時還能夠提升系統的整體可用性,由於單臺設備 Crash 以後,只有整體數據的某部分不可用,而不是全部的數據。架構
數據的切分(Sharding)根據其切分規則的類型,能夠分爲兩種切分模式。一種是按照不一樣的表(或者 Schema)來切分到不一樣的數據庫(主機)之上,這種切分能夠稱之爲數據的垂直(縱向)切分;另一種則是根據表中數據的邏輯關係,將同一個表中的數據按照某種條件拆分到多臺數據庫(主機)上,這種切分稱之爲數據的水平(橫向)切分。ide
垂直切分的最大特色就是規則簡單,實施也更爲方便,尤爲適合各業務之間的耦合度很是低、相互影響很小、業務邏輯很是清晰的系統。在這種系統中,能夠很容易作到將不一樣業務模塊所使用的表分拆到不一樣的數據庫中。根據不一樣的表來進行拆分,對應用程序的影響也更小,拆分規則也會比較簡單清晰。模塊化
水平切分與垂直切分相比,稍微複雜一些。由於要將同一個表中的不一樣數據拆分到不一樣的數據庫中,對於應用程序來講,拆分規則自己就較根據表名來拆分更爲複雜,後期的數據維護也會更復雜。post
當某個(或者某些)表的數據量和訪問量特別大,經過垂直切分將其放在獨立的設備上後仍然沒法知足性能要求時,就必須將垂直切分和水平切分相結合,先垂直切分,而後再水平切分,這樣才能解決這種超大型表的性能問題。性能
下面就針對垂直、水平及組合切分這三種數據切分方式的架構實現及切分後數據的整合進行相應的分析。網站
2 數據的垂直切分spa
咱們先來看一下,數據的垂直切分究竟是如何切分的。數據的垂直切分,也能夠稱爲縱向切分。將數據庫想象成由不少個一大塊一大塊的"數據塊"(表)組成,垂直地將這些"數據塊"切開,而後把它們分散到多臺數據庫主機上面。這樣的切分方法就是垂直(縱向)的數據切分。架構設計
一個架構設計較好的應用系統,其整體功能確定是由不少個功能模塊所組成的,而每個功能模塊所須要的數據對應到數據庫中就是一個或多個表。而在架構設計中,各個功能模塊相互之間的交互點越統1、越少,系統的耦合度就越低,系統各個模塊的維護性及擴展性也就越好。這樣的系統,實現數據的垂直切分也就越容易。設計
功能模塊越清晰,耦合度越低,數據垂直切分的規則定義也就越容易。徹底能夠根據功能模塊來進行數據的切分,不一樣功能模塊的數據存放於不一樣的數據庫主機中,能夠很容易就避免跨數據庫的 Join 存在,同時系統架構也很是清晰。
固然,很難有系統可以作到全部功能模塊使用的表徹底獨立,根本不需要訪問對方的表,或者需要將兩個模塊的表進行 Join 操做。這種狀況下,就必須根據實際的應用場景進行評估權衡。決定是遷就應用程序將須要 Join 的表的相關模塊都存放在同一個數據庫中,仍是讓應用程序作更多的事情--徹底經過模塊接口取得不一樣數據庫中的數據,而後在程序中完成 Join 操做。
通常來講,若是是一個負載相對不大,並且表關聯又很是頻繁的系統,那可能數據庫讓步,將幾個相關模塊合併在一塊兒,減小應用程序工做的方案能夠減小較多的工做量,是一個可行的方案。
固然,經過數據庫的讓步,讓多個模塊集中共用數據源,實際上也是間接默許了各模塊架構耦合度增大的發展,可能會惡化之後的架構。尤爲是當發展到必定階段,發現數據庫實在沒法承擔這些表所帶來的壓力,不得不面臨再次切分時,所帶來的架構改形成本可能遠遠大於最初就使用切分的架構設計。
因此,在數據庫進行垂直切分的時候,如何切分、切分到什麼樣的程度,是一個比較考驗人的難題。這隻能在實際的應用場景中經過平衡各方面的成本和收益,才能分析出一個真正適合本身的拆分方案。
好比在本書所使用的示例系統的 example 數據庫中,咱們簡單分析一下,而後設計一個簡單的切分規則,進行一次垂直拆分。
系統功能基本能夠分爲4個功能模塊:用戶、羣組消息、相冊以及事件,分別對應爲以下這些表:
(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信息,一樣比較容易分拆。
因此,第一步能夠將數據庫按照功能模塊相關的表進行一次垂直拆分,每一個模塊所涉及的表單獨分到一個數據庫中,模塊與模塊之間的表關聯在應用系統端都經過接口來處理。如數據垂直切分示意圖(圖14-1)所示:
(點擊查看大圖)圖14-1 垂直切分示意 |
經過這樣的垂直切分以後,以前只能經過一個數據庫來提供的服務,就被分拆成4個數據庫來提供服務,服務能力天然是增長几倍了。
垂直切分的優勢:
數據庫的拆分簡單明瞭,拆分規則明確;
應用程序模塊清晰明確,整合容易;
數據維護方便易行,容易定位。
垂直切分的缺點:
部分表關聯沒法在數據庫級別完成,要在程序中完成;
對於訪問極其頻繁且數據量超大的表仍然存在性能瓶頸,不必定能知足要求;
事務處理相對複雜;
切分達到必定程度以後,擴展性會受到限制;
過分切分可能會帶來系統過於複雜而難以維護。
針對於垂直切分可能遇到數據切分及事務問題,在數據庫層面實在是很難找到一個較好的處理方案。實際應用案例中,數據庫的垂直切分大可能是與應用系統的模塊相對應的,同一個模塊的數據源存放於同一個數據庫中,能夠解決模塊內部的數據關聯問題。而模塊與模塊之間,則經過應用程序以服務接口的方式來相互提供所須要的數據。雖然這樣作在數據庫的整體操做次數方面確實會有所增長,可是在系統總體擴展性及架構模塊化方面,都是有益的。可能某些操做的單次響應的時間會稍有增長,可是系統的總體性能極可能反而會有必定的提高。而擴展瓶頸問題,就只能依靠下一節將要介紹的數據水平切分架構來解決了。
3 數據的水平切分
數據的垂直切分基本上能夠簡單地理解爲按照表或模塊來切分數據,而水平切分則不一樣。通常來講,簡單的水平切分主要是將某個訪問極其平凡的表再按照某個字段的某種規則分散到多個表中,每一個表包含一部分數據。
簡單來講,能夠將數據的水平切分理解爲按照數據行的切分,就是將表中的某些行切分到一個數據庫,而另外的某些行又切分到其餘的數據庫中。固然,爲了可以比較容易地斷定各行數據被切分到哪一個數據庫中了,切分老是需要按照某種特定的規則來進行的:如根據某個數字類型字段基於特定數目取模,某個時間類型字段的範圍,或者某個字符類型字段的 hash 值。若是整個系統中大部分核心表均可以經過某個字段來進行關聯,那這個字段天然是一個進行水平分區的上上之選了,固然,很是特殊沒法使用的狀況除外。
通常來講,像如今很是火爆的 Web 2.0 類型網站,基本上大部分數據都可以經過會員用戶信息關聯上,可能不少核心表都很是適合經過會員 ID 來進行數據的水平切分。而像論壇社區討論系統,就更容易切分了,能夠按照論壇編號來進行水平切分。切分以後基本上不會出現各個庫之間的交互。
若是示例系統的全部數據都是和用戶關聯的,那麼就能夠根據用戶來進行水平拆分,將不一樣用戶的數據切分到不一樣的數據庫中。固然,惟一區別是用戶模塊中的 groups 表和用戶沒有直接關係,因此 groups 不能根據用戶來進行水平拆分。對於這種特殊狀況下的表,徹底能夠獨立出來,放在一個獨立的數據庫中。其實這個作法能夠說是利用了前面一節所介紹的"數據的垂直切分"方法,將在下一節中更爲詳細地介紹這種垂直切分與水平切分同時使用的聯合切分方法。
因此,對於示例數據庫來講,大部分的表均可以根據用戶 ID 來進行水平切分。不一樣用戶相關的數據進行切分以後存放在不一樣的數據庫中。如將全部用戶 ID 經過被2 取模而後分別存放於兩個不一樣的數據庫中。每一個和用戶 ID 關聯上的表均可以這樣切分。這樣,基本上每一個用戶相關的數據,都在同一個數據庫中,即便需要關聯,也很是容易實現。
能夠經過水平切分示意圖(圖14-2)更爲直觀地展現水平切分相關信息:
(點擊查看大圖)圖14-2 |
水平切分的優勢:
表關聯基本可以在數據庫端所有完成;
不會存在某些超大型數據量和高負載的表遇到瓶頸的問題;
應用程序端總體架構改動相對較少;
事務處理相對簡單;
只要切分規則可以定義好,基本上較難遇到擴展性限制。
水平切分的缺點:
切分規則相對複雜,很難抽象出一個可以知足整個數據庫的切分規則;
後期數據的維護難度有所增長,人爲手工定位數據更困難;
應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分形成必定的困難。