數據庫垂直拆分 水平拆分


        當我們使用讀寫分離、緩存后,數據庫的壓力還是很大的時候,這就需要使用到數據庫拆分了。
        
        數據庫拆分簡單來說,就是指通過某種特定的條件,按照某個維度,將我們存放在同一個數據庫中的數據分散存放到多個數據庫(主機)上面以達到分散單庫(主機)負載的效果。 
 
        切分模式: 垂直(縱向)拆分、水平拆分。
 
垂直拆分
 
        專庫專用
 
        一個數據庫由很多表的構成,每個表對應着不同的業務,垂直切分是指 按照業務將表進行分類,分布到不同的數據庫上面,這樣也就將數據或者說壓力分擔到不同的庫上面,如下圖:
        
優點:
        1. 拆分后業務清晰,拆分規則明確。
        2. 系統之間整合或擴展容易。
        3. 數據維護簡單。
 
缺點:
        1. 部分業務表無法join,只能通過接口方式解決,提高了系統復雜度。
        2. 受每種業務不同的限制存在單庫性能瓶頸,不易數據擴展跟性能提高。
        3. 事務處理復雜。
 
水平拆分
 
        垂直拆分后遇到單機瓶頸,可以使用水平拆分。相對於垂直拆分的區別是:垂直拆分是把不同的表拆到不同的數據庫中,而水平拆分是把同一個表拆到不同的數據庫中。
 
         相對於垂直拆分,水平拆分不是將表的數據做分類,而是按照某個字段的某種規則來分散到多個庫之中,每個表中包含一部分數據。簡單來說,我們可以將數據的水平切分理解為是按照數據行的切分,就是將表中 的某些行切分到一個數據庫,而另外的某些行又切分到其他的數據庫中,主要有分表,分庫兩種模式,如圖:
                 
 
        
優點:
        1. 不存在單庫大數據,高並發的性能瓶頸。
        2. 對應用透明,應用端改造較少。     
        3. 按照合理拆分規則拆分,join操作基本避免跨庫。
        4. 提高了系統的穩定性跟負載能力。
 
缺點:
        1.  拆分規則難以抽象。
        2. 分片 事務一致性難以解決。
        3. 數據多次擴展難度跟維護量極大。
        4. 跨庫join性能較差。
 
拆分的處理難點
 
兩張方式共同缺點
 
        1. 引入分布式事務的問題。
        2. 跨節點Join 的問題。
        3. 跨節點合並排序分頁問題。
 
針對數據源管理,目前主要有兩種思路:
 
        A. 客戶端模式,在每個應用程序模塊中配置管理自己需要的一個(或者多個)數據源,直接訪問各個 數據庫,在模塊內完成數據的整合。 
        優點:相對簡單,無性能損耗。   
        缺點:不夠通用,數據庫連接的處理復雜,對業務不夠透明,處理復雜。
 
       B. 通過 中間代理層來統一管理所有的數據源,后端數據庫集群對前端應用程序透明;   
        優點:通用,對應用透明,改造少。   
        缺點:實現難度大,有二次轉發性能損失。
 
拆分原則
    
        1. 盡量不拆分,架構是進化而來,不是一蹴而就。(SOA)
        2. 最大可能的找到最合適的切分維度。
        3. 由於數據庫中間件對數據Join 實現的優劣難以把握,而且實現高性能難度極大,業務讀取  盡量少使用多表Join -盡量通過數據冗余,分組避免數據垮庫多表join。
        4. 盡量避免分布式事務。
        5. 單表拆分到數據1000萬以內。
 
切分方案
    
        范圍、枚舉、時間、取模、哈希、指定等
 
案例分析
 
場景一
建立一個歷史his系統,將公司的一些歷史個人游戲數據保存到這個his系統中,主要是寫入,還有部分查詢,讀寫比約為1:4;由於是所有數據的歷史存取,所以並發要求比較高; 
 
分析:
歷史數據
寫多都少
越近日期查詢越頻繁?
什么業務數據?用戶游戲數據
有沒有大規模分析查詢?
數據量多大?
保留多久?
機器資源有多少?
 
方案1:按照日期每月一個分片
帶來的問題:1.數據熱點問題(壓力不均勻)
 
方案2:按照用戶取模,  --by Jerome 就這個比較合適了
帶來的問題:后續擴容困難
 
方案3:按用戶ID范圍分片(1-1000萬=分片1,xxx)
帶來的問題:用戶活躍度無法掌握,可能存在熱點問題
 
場景二
建立一個商城訂單系統,保存用戶訂單信息。
 
分析:
電商系統
一號店或京東類?淘寶或天貓?
實時性要求高
存在瞬時壓力
基本不存在大規模分析
數據規模?
機器資源有多少?
維度?商品?用戶?商戶?
 
方案1:按照用戶取模,
帶來的問題:后續擴容困難
 
方案2:按用戶ID范圍分片(1-1000萬=分片1,xxx)
帶來的問題:用戶活躍度無法掌握,可能存在熱點問題
 
方案3:按省份地區或者商戶取模
數據分配不一定均勻
 
場景3
上海公積金,養老金,社保系統
 
分析:
社保系統
實時性要求不高
不存在瞬時壓力
大規模分析?
數據規模大
數據重要不可丟失
偏於查詢?
 
方案1:按照用戶取模,
帶來的問題:后續擴容困難
 
方案2:按用戶ID范圍分片(1-1000萬=分片1,xxx)
帶來的問題:用戶活躍度無法掌握,可能存在熱點問題
 
方案3:按省份區縣地區枚舉
數據分配不一定均勻
 
 
 
        數據庫問題解決后,應用面對的新挑戰就是拆分應用等
 

參考
        Mycat在線視頻培訓【鏈接: http://pan.baidu.com/s/1nuR26rZ 密碼:1gr9 (2015)】
         大型網站系統與Java中間件實踐.pdf
 
 
垂直拆分
  垂直拆分就是要把表按模塊划分到不同 數據庫表中(當然原則還是不破壞第三范式),這種拆分在大型網站的演變過程中是很常見的。當一個網站還在很小的時候,只有小量的人來開發和維護,各模塊和表都在一起,當網站不斷豐富和壯大的時候,也會變成多個子系統來支撐,這時就有按模塊和功能把表划分出來的需求。其實,相對於垂直切分更進一步的是服務化改造,說得簡單就是要把原來強耦合的系統拆分成多個弱耦合的服務,通過服務間的調用來滿足業務需求看,因此表拆出來后要通過服務的形式暴露出去,而不是直接調用不同模塊的表,淘寶在架構不斷演變過程,最重要的一環就是服務化改造,把用戶、交易、店鋪、寶貝這些核心的概念抽取成獨立的服務,也非常有利於進行局部的優化和治理,保障核心模塊的穩定性
  垂直拆分:單表大數據量依然存在性能瓶頸
   水平拆分
  上面談到垂直切分只是把表按模塊划分到不同數據庫,但沒有解決單表大數據量的問題,而水平切分就是要把一個表按照某種規則把數據划分到不同表或數據庫里。例如像計費系統,通過按時間來划分表就比較合適,因為系統都是處理某一時間段的數據。而像SaaS應用,通過按用戶維度來划分數據比較合適,因為用戶與用戶之間的隔離的,一般不存在處理多個用戶數據的情況,簡單的按user_id范圍來水平切分
  通俗理解:水平拆分行,行數據拆分到不同表中, 垂直拆分列,表數據拆分到不同表中
   垂直與水平聯合切分
  由上面可知垂直切分能更清晰化模塊划分,區分治理,水平切分能解決大數據量性能瓶頸問題,因此常常就會把兩者結合使用,這在大型網站里是種常見的策略
  案例:
  以mysql為例,簡單購物系統暫設涉及如下表:
  1.產品表(數據量10w,穩定)
  2.訂單表(數據量200w,且有增長趨勢)
  3.用戶表 (數據量100w,且有增長趨勢)
  以mysql為例講述下水平拆分和垂直拆分,mysql能容忍的數量級在百萬靜態數據可以到千萬
   垂直拆分:
  解決問題:
  表與表之間的io競爭
  不解決問題:
  單表中數據量增長出現的壓力
  方案:
  把產品表和用戶表放到一個 server
  訂單表單獨放到一個server上
   水平拆分:
  解決問題:
  單表中數據量增長出現的壓力
  不解決問題:
  表與表之間的io爭奪
  方案:
  用戶表通過性別拆分為男用戶表和女用戶表
  訂單表通過已完成和完成中拆分為已完成訂單和未完成訂單
  產品表 未完成訂單放一個server上
  已完成訂單表盒男用戶表放一個server上
  女用戶表放一個server上(女的愛購物)
 
 
 
 

《大型網站系統與Java中間件實踐》本書圍繞大型網站和支撐大型網站架構的 Java 中間件的實踐展開介紹。從分布式系統的知識切入,讓讀者對分布式系統有基本的了解;然后介紹大型網站隨着數據量、訪問量增長而發生的架構變遷;接着講述構建 Java 中間件的相關知識;之后的幾章都是根據筆者的經驗來介紹支撐大型網站架構的 Java 中間件系統的設計和實踐。本節為大家介紹專庫專用,數據垂直拆分。

AD:
51CTO 網+ 第十二期沙龍:大話數據之美_如何用數據驅動用戶體驗

2.2.7 讀寫分離后,數據庫又遇到瓶頸

通過讀寫分離以及在某些場景用分布式存儲系統替換關系型數據庫的方式,能夠降低主庫的壓力,解決數據存儲方面的問題。不過隨着業務的發展,我們的主庫也會遇到瓶頸。我們的網站演進到現在,交易、商品、用戶的數據還都在一個數據庫中。盡管采取了增加緩存、讀寫分離的方式,這個數據庫的壓力還是在繼續增加,因此我們需要去解決這個問題,我們有數據垂直拆分和水平拆分兩種選擇。

2.2.7.1 專庫專用,數據垂直拆分

垂直拆分的意思是把數據庫中不同的業務數據拆分到不同的數據庫中。結合現在的例子,就是把交易、商品、用戶的數據分開,如圖2-20 所示。

 

 

這樣的變化給我們帶來的影響是什么呢?應用需要配置多個數據源,這就增加了所需的配置,不過帶來的是每個數據庫連接池的隔離。不同業務的數據從原來的一個數據庫中拆分到了多個數據庫中,那么就需要考慮如何處理原來單機中跨業務的事務。一種辦法是使用分布式事務,其性能要明顯低於之前的單機事務;而另一種辦法就是去掉事務或者不去追求強事務支持,則原來在單庫中可以使用的表關聯的查詢也就需要改變實現了。

對數據進行垂直拆分之后,解決了把所有業務數據放在一個數據庫中的壓力問題。並且也可以根據不同業務的特點進行更多優化。

 

2.2.7.2 垂直拆分后的單機遇到瓶頸,數據水平拆分

與數據垂直拆分對應的還有數據水平拆分。數據水平拆分就是把同一個表的數據拆到兩個數據庫中。產生數據水平拆分的原因是某個業務的數據表的數據量或者更新量達到了單個數據庫的瓶頸,這時就可以把這個表拆到兩個或者多個數據庫中。數據水平拆分與讀寫分離的區別是,讀寫分離解決的是讀壓力大的問題,對於數據量大或者更新量的情況並不起作用。數據水平拆分與數據垂直拆分的區別是,垂直拆分是把不同的表拆到不同的數據庫中,而水平拆分是把同一個表拆到不同的數據庫中。例如,經過垂直拆分后,用戶表與交易表、商品表不在一個數據庫中了,如果數據量或者更新量太大,我們可以進一步把用戶表拆分到兩個數據庫中,它們擁有結構一模一樣的用戶表,而且每個庫中的用戶表都只涵蓋了一部分的用戶,兩個數據庫的用戶合在一起就相當於沒有拆分之前的用戶表。我們先來簡單看一下引入數據水平拆分后的結構,如圖2-21 所示。

我們來分析一下水平拆分后給業務應用帶來的影響。

首先,訪問用戶信息的應用系統需要解決SQL 路由的問題,因為現在用戶信息分在了兩個數據庫中,需要在進行數據庫操作時了解需要操作的數據在哪里。

此外,主鍵的處理也會變得不同。原來依賴單個數據庫的一些機制需要變化,例如原來使用Oracle 的Sequence 或者MySQL 表上的自增字段的,現在不能簡單地繼續使用了。並且在不同的數據庫中也不能直接使用一些數據庫的限制來保證主鍵不重復了。

 

 

最后,由於同一個業務的數據被拆分到了不同的數據庫中,因此一些查詢需要從兩個數據庫中取數據,如果數據量太大而需要分頁,就會比較難處理了。

不過,一旦我們能夠完成數據的水平拆分,我們將能夠很好地應對數據量及寫入量增長的情況。具體如何完成數據水平拆分,在后面分布式數據訪問層的章節中我們將進行更加詳細的介紹。

 

2.2.8 數據庫問題解決后,應用面對的新挑戰

2.2.8.1 拆分應用

前面所講的讀寫分離、分布式存儲、數據垂直拆分和數據水平拆分都是在解決數據方面的問題。下面我們來看看應用方面的變化。

之前解決了應用服務器從單機到多機的擴展,應用就可以在一定范圍內水平擴展了。隨着業務的發展,應用的功能會越來越多,應用也會越來越大。我們需要考慮如何不讓應用持續變大,這就需要把應用拆開,從一個應用變為兩個甚至多個應用。我們來看兩種方式。

第一種方式,根據業務的特性把應用拆開。在我們的例子中,主要的業務功能分為三大部分:交易、商品和用戶。我們可以把原來的一個應用拆成分別以交易和商品為主的兩個應用,對於交易和商品都會有涉及用戶的地方,我們讓這兩個系統自己完成涉及用戶的工作,而類似用戶注冊、登錄等基礎的用戶工作,可以暫時交給兩系統之一來完成(注意,我們在這里主要是通過例子說明拆分的做法),如圖2-22 所示,這樣的拆分可以使大的應用變小。

 

 

我們還可以按照用戶注冊、用戶登錄、用戶信息維護等再拆分,使之變成三個系統。不過,這樣拆分后在不同系統中會有一些相似的代碼,例如用戶相關的代碼。如何能夠保證這部分代碼的一致以及如何對其復用是需要解決的問題。此外,按這樣的方式拆分出來的新系統之間一般沒有直接的相互調用。而且,新拆出來的應用可能會連接同樣的數據庫。

來看一個具體的例子,如圖2-23 所示。

我們根據業務的不同功能拆分了幾個業務應用,而且這些業務應用之間不存在直接的調用,它們都依賴底層的數據庫、緩存、文件系統、搜索等。這樣的應用拆分確實能夠解決當下的一些問題,不過也有一些缺點。  

 

 

2.2.8.2 走服務化的路

我們再來看一下服務化的做法。圖2-24 是一個示意圖。從中可以看到我們把應用分為了三層,處於最上端的是Web 系統,用於完成不同的業務功能;處於中間的是一些服務中心,不同的服務中心提供不同的業務服務;處於下層的則是業務的數據庫。當然,我們在這個圖中省去了緩存等基礎的系統,因此可以說是服務化系統結構的一個簡圖。

 

 

圖2-24 與之前的圖相比有幾個很重要的變化。首先,業務功能之間的訪問不僅是單機內部的方法調用了,還引入了遠程的服務調用。其次,共享的代碼不再是散落在不同的應用中了,這些實現被放在了各個服務中心。第三,數據庫的連接也發生了一些變化,我們把與數據庫的交互工作放到了服務中心,讓前端的Web 應用更加注重與瀏覽器交互的工作,而不必過多關注業務邏輯的事情。連接數據庫的任務交給相應的業務服務中心了,這樣可以降低數據庫的連接數。而服務中心不僅把一些可以共用的之前散落在各個業務的代碼集中了起來,並且能夠使這些代碼得到更好的維護。第四,通過服務化,無論是前端Web 應用還是服務中心,都可以是由固定小團隊來維護的系統,這樣能夠更好地保持穩定性,並能更好地控制系統本身的發展,況且穩定的服務中心日常發布的次數也遠小於前端Web 應用,因此這個方式也減小了不穩定的風險。

要做到服務化還需要一些基礎組件的支撐,在后面服務框架的章節我們會具體介紹。

 

 

通過某種特定的條件,將存放在同一個數據庫中的數據分散存放到多個數據庫上,實現分布存儲,通過路由規則路由訪問特定的數據庫,這樣一來每次訪問面對的就不是單台服務器了,而是N台服務器,這樣就可以降低單台機器的負載壓力。提示:sqlserver 2005版本之后,可以友好的支持“表分區”。

  垂直(縱向)拆分:是指按功能模塊拆分,比如分為訂單庫、商品庫、用戶庫...這種方式多個數據庫之間的表結構不同。

  水平(橫向)拆分:將同一個表的數據進行分塊保存到不同的數據庫中,這些數據庫中的表結構完全相同。

SQL Server:數據庫/數據表 拆分
▲(縱向拆分)

SQL Server:數據庫/數據表 拆分
▲(橫向拆分)

  1,實現原理:使用垂直拆分,主要要看應用類型是否合適這種拆分方式,如系統可以分為,訂單系統,商品管理系統,用戶管理系統業務系統比較明的,垂直拆分能很好的起到分散數據庫壓力的作用。業務模塊不明晰,耦合(表關聯)度比較高的系統不適合使用這種拆分方式。但是垂直拆分方式並不能徹底解決所有壓力問題,例如 有一個5000w的訂單表,操作起來訂單庫的壓力仍然很大,如我們需要在這個表中增加(insert)一條新的數據,insert完畢后,數據庫會針對這張表重新建立索引,5000w行數據建立索引的系統開銷還是不容忽視的,反過來,假如我們將這個表分成100個table呢,從table_001一直到table_100,5000w行數據平均下來,每個子表里邊就只有50萬行數據,這時候我們向一張只有50w行數據的table中insert數據后建立索引的時間就會呈數量級的下降,極大了提高了DB的運行時效率,提高了DB的並發量,這種拆分就是橫向拆分

  2,實現方法:垂直拆分,拆分方式實現起來比較簡單,根據表名訪問不同的數據庫就可以了。橫向拆分的規則很多,這里總結前人的幾點,

  (1)順序拆分:如可以按訂單的日前按年份才分,2003年的放在db1中,2004年的db2,以此類推。當然也可以按主鍵標准拆分。

  優點:可部分遷移

  缺點:數據分布不均,可能2003年的訂單有100W,2008年的有500W。

  (2)hash取模分: 對user_id進行hash(或者如果user_id是數值型的話直接使用user_id的值也可),然后用一個特定的數字,比如應用中需要將一個數據庫切分成4個數據庫的話,我們就用4這個數字對user_id的hash值進行取模運算,也就是user_id%4,這樣的話每次運算就有四種可能:結果為1的時候對應DB1;結果為2的時候對應DB2;結果為3的時候對應DB3;結果為0的時候對應DB4,這樣一來就非常均勻的將數據分配到4個DB中。

  優點:數據分布均勻

  缺點:數據遷移的時候麻煩;不能按照機器性能分攤數據 。

  (3)在認證庫中保存數據庫配置

  就是建立一個DB,這個DB單獨保存user_id到DB的映射關系,每次訪問數據庫的時候都要先查詢一次這個數據庫,以得到具體的DB信息,然后才能進行我們需要的查詢操作。

  優點:靈活性強,一對一關系

  缺點:每次查詢之前都要多一次查詢,會造成一定的性能損失。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM