1. 程式人生 > >資料切分 垂直切分、垂直拆分與水平拆分的優缺點

資料切分 垂直切分、垂直拆分與水平拆分的優缺點

資料切分 垂直切分

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

雖然在雲端計算時代,傳統資料庫存在著先天性的弊端,但是NoSQL資料庫又無法將其替代,NoSQL只能作為傳統資料的補充而不能將其替代,所以規避傳統資料庫的缺點是目前大資料時代必須要解決的問題。如果傳統資料易於擴充套件,可切分,就可以避免單機(單庫)的效能缺陷,但是由於目前開源或者商用的傳統資料庫基本不支援大規模自動擴充套件,所以就需要藉助第三方來做處理,下面就來分析一下如何進行資料切分。

何為資料切分?

簡單來說,就是指通過某種特定的條件,將我們存放在同一個資料庫中的資料分散存放到多個數據庫(主機)上面,以達到分散單臺裝置負載的效果。

資料的切分(Sharding)根據其切分規則的型別,可以分為兩種切分模式。一種是按照不同的表(或者Schema)來切分到不同的資料庫(主機)之上,這種切可以稱之為資料的垂直(縱向)切分;另外一種則是根據表中的資料的邏輯關係,將同一個表中的資料按照某種條件拆分到多臺資料庫(主機)上面,這種切分稱之為資料的水平(橫向)切分。

垂直切分的最大特點就是規則簡單,實施也更為方便,尤其適合各業務之間的耦合度非常低,相互影響很小,業務邏輯非常清晰的系統。在這種系統中,可以很容易做到將不同業務模組所使用的表分拆到不同的資料庫中。根據不同的表來進行拆分,對應用程式的影響也更小,拆分規則也會比較簡單清晰。

水平切分於垂直切分相比,相對來說稍微複雜一些。因為要將同一個表中的不同資料拆分到不同的資料庫中,對於應用程式來說,拆分規則本身就較根據表名來拆分更為複雜,後期的資料維護也會更為複雜一些。

垂直切分

一個數據庫由很多表的構成,每個表對應著不同的業務,垂直切分是指按照業務將表進行分類,分佈到不同的資料庫上面,這樣也就將資料或者說壓力分擔到不同的庫上面,如下圖:

blob.png

系統被切分成了,使用者,訂單交易,支付幾個模組。

一個架構設計較好的應用系統,其總體功能肯定是由很多個功能模組所組成的,而每一個功能模組所需要的資料對應到資料庫中就是一個或者多個表。而在架構設計中,各個功能模組相互之間的互動點越統一越少,系統的耦合度就越低,系統各個模組的維護性以及擴充套件性也就越好。這樣的系統,實現資料的垂直切分也就越容易。

但是往往系統之有些表難以做到完全的獨立,存在這擴庫join的情況,對於這類的表,就需要去做平衡,是資料庫讓步業務,共用一個數據源,還是分成多個庫,業務之間通過介面來做呼叫。在系統初期,資料量比較少,或者資源有限的情況下,會選擇共用資料來源,但是當資料發展到了一定的規模,負載很大的情況,就需要必須去做分割。

一般來講業務存在著複雜join的場景是難以切分的,往往業務獨立的易於切分。如何切分,切分到何種程度是考驗技術架構的一個難題。

下面來分析下垂直切分的優缺點:

優點:

拆分後業務清晰,拆分規則明確。

系統之間整合或擴充套件容易。

資料維護簡單。

缺點:

部分業務表無法join,只能通過介面方式解決,提高了系統複雜度。

受每種業務不同的限制存在單庫效能瓶頸,不易資料擴充套件跟效能提高。

事務處理複雜。

由於垂直切分是按照業務的分類將表分散到不同的庫,所以有些業務表會過於龐大,存在單庫讀寫與儲存瓶頸,所以就需要水平拆分來做解決。

水平切分

相對於垂直拆分,水平拆分不是將表做分類,而是按照某個欄位的某種規則來分散到多個庫之中,每個表中包含一部分資料。簡單來說,我們可以將資料的水平切分理解為是按照資料行的切分,就是將表中的某些行切分到一個數據庫,而另外的某些行又切分到其他的資料庫中,如圖:

blob.png

拆分資料就需要定義分片規則。關係型資料庫是行列的二維模型,拆分的第一原則是找到拆分維度。比如:從會員的角度來分析,商戶訂單交易類系統中查詢會員某天某月某個訂單,那麼就需要按照會員結合日期來拆分,不同的資料按照會員ID做分組,這樣所有的資料查詢join都會在單庫內解決;如果從商戶的角度來講,要查詢某個商家某天所有的訂單數,就需要按照商戶ID做拆分;但是如果系統既想按會員拆分,又想按商家資料,則會有一定的困難。如何找到合適的分片規則需要綜合考慮衡量。

幾種典型的分片規則包括:

按照使用者ID求模,將資料分散到不同的資料庫,具有相同資料使用者的資料都被分散到一個庫中。

按照日期,將不同月甚至日的資料分散到不同的庫中。

按照某個特定的欄位求摸,或者根據特定範圍段分散到不同的庫中。

如圖,切分原則都是根據業務找到適合的切分規則分散到不同的庫,下面用使用者ID求模舉例:

blob.png

既然資料做了拆分有優點也就優缺點。

優點有:

拆分規則抽象好,join操作基本可以資料庫做。

不存在單庫大資料,高併發的效能瓶頸。

應用端改造較少。

提高了系統的穩定性跟負載能力。

缺點有:

拆分規則難以抽象。

分片事務一致性難以解決。

資料多次擴充套件難度跟維護量極大。

跨庫join效能較差。

前面講了垂直切分跟水平切分的不同跟優缺點,會發現每種切分方式都有缺點,但共同的特點缺點有:

引入分散式事務的問題。

跨節點Join的問題。

跨節點合併排序分頁問題。

多資料來源管理問題。

針對資料來源管理,目前主要有兩種思路:

A. 客戶端模式,在每個應用程式模組中配置管理自己需要的一個(或者多個)資料來源,直接訪問各個資料庫,在模組內完成資料的整合;

B. 通過中間代理層來統一管理所有的資料來源,後端資料庫叢集對前端應用程式透明;

可能90%以上的人在面對上面這兩種解決思路的時候都會傾向於選擇第二種,尤其是系統不斷變得龐大複雜的時候。確實,這是一個非常正確的選擇,雖然短期內需要付出的成本可能會相對更大一些,但是對整個系統的擴充套件性來說,是非常有幫助的。

 

由於資料切分後資料Join的難度在此也分享一下資料切分的經驗:

第一原則:能不切分儘量不要切分。

第二原則:如果要切分一定要選擇合適的切分規則,提前規劃好。

第三原則:資料切分儘量通過資料冗餘或表分組(Table Group)來降低跨庫Join的可能。

第四原則:由於資料庫中介軟體對資料Join實現的優劣難以把握,而且實現高效能難度極大,業務讀取儘量少使用多表Join。
-----------------------------------------------------------------------------
資料庫垂直拆分 水平拆分
        當我們使用讀寫分離、快取後,資料庫的壓力還是很大的時候,這就需要使用到資料庫拆分了。
        
        資料庫拆分簡單來說,就是指通過某種特定的條件,按照某個維度,將我們存放在同一個資料庫中的資料分散存放到多個數據庫(主機)上面以達到分散單庫(主機)負載的效果。 
 
        切分模式: 垂直(縱向)拆分、水平拆分。
 
垂直拆分
 
        專庫專用
 
        一個數據庫由很多表的構成,每個表對應著不同的業務,垂直切分是指按照業務將表進行分類,分佈到不同的資料庫上面,這樣也就將資料或者說壓力分擔到不同的庫上面,如下圖:
        
優點:
        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
        MySQL資料庫的演化可以參考:http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=207666963&idx=2&sn=0d0710e071420c6fc6af8d4a3bc3dfe6&scene=1#rd
        http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651959773&idx=1&sn=7e4ad0dcd050f6662dfaf39d9de36f2c&chksm=bd2d04018a5a8d17b92098b4840aac23982e32d179cdd957e4c55011f6a08f6bd31f9ba5cfee&mpshare=1&scene=23&srcid=1220t4ttl8wZaYHlQRzO0xYB#rd【一分鐘掌握資料庫垂直拆分-沈劍】
 
 
垂直拆分
  垂直拆分就是要把表按模組劃分到不同資料庫表中(當然原則還是不破壞第三正規化),這種拆分在大型網站的演變過程中是很常見的。當一個網站還在很小的時候,只有小量的人來開發和維護,各模組和表都在一起,當網站不斷豐富和壯大的時候,也會變成多個子系統來支撐,這時就有按模組和功能把表劃分出來的需求。其實,相對於垂直切分更進一步的是服務化改造,說得簡單就是要把原來強耦合的系統拆分成多個弱耦合的服務,通過服務間的呼叫來滿足業務需求看,因此表拆出來後要通過服務的形式暴露出去,而不是直接呼叫不同模組的表,淘寶在架構不斷演變過程,最重要的一環就是服務化改造,把使用者、交易、店鋪、寶貝這些核心的概念抽取成獨立的服務,也非常有利於進行區域性的優化和治理,保障核心模組的穩定性
  垂直拆分:單表大資料量依然存在效能瓶頸
  水平拆分
  上面談到垂直切分只是把表按模組劃分到不同資料庫,但沒有解決單表大資料量的問題,而水平切分就是要把一個表按照某種規則把資料劃分到不同表或資料庫裡。例如像計費系統,通過按時間來劃分表就比較合適,因為系統都是處理某一時間段的資料。而像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資訊,然後才能進行我們需要的查詢操作。

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

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

 ---------------------------------------------------------------------------------
資料切分可以是物理上的,對資料通過一系列的切分規則將資料分佈到不同的DB伺服器上,通過路由規則路由訪問特定的資料庫,這樣一來每次訪問面對的就不是單臺伺服器了,而是N臺伺服器,這樣就可以降低單臺機器的負載壓力。

資料切分也可以是資料庫內的,對資料通過一系列的切分規則,將資料分佈到一個數據庫的不同表中,比如將article分為article_001,article_002等子表,若干個子表水平拼合有組成了邏輯上一個完整的article表,這樣做的目的其實也是很簡單的。 舉個例子說明,比如article表中現在有5000w條資料,此時我們需要在這個表中增加(insert)一條新的資料,insert完畢後,資料庫會針對這張表重新建立索引,5000w行資料建立索引的系統開銷還是不容忽視的。但是反過來,假如我們將這個表分成100 個table呢,從article_001一直到article_100,5000w行資料平均下來,每個子表裡邊就只有50萬行資料,這時候我們向一張只有50w行資料的table中insert資料後建立索引的時間就會呈數量級的下降,極大了提高了DB的執行時效率,提高了DB的併發量。當然分表的好處還不知這些,還有諸如寫操作的鎖操作等,都會帶來很多顯然的好處。

綜上,分庫降低了單點機器的負載;分表,提高了資料操作的效率,尤其是Write操作的效率。
----------------------------------------------------------------------------------

垂直拆分與水平拆分的優缺點

資料的拆分(Sharding)根據其拆分分規則的型別,可以分為兩種拆分模式。一種是按照不同的表(或者Schema)來切分到不同的資料庫(主機)之上,這種切可以稱之為資料的垂直(縱向)拆分;
另外一種則是根據表中的資料的邏輯關係,將同一個表中的資料按照某種條件拆分到多臺資料庫(主機)上面,這種切分稱之為資料的水平(橫向)拆分。

垂直拆分的優點:
拆分後業務清晰,拆分規則明確
系統之間進行整合或擴充套件很容易
按照成本、應用的等級、應用的型別等將表放到不同的機器上便於管理
方便實現動靜分離,冷熱分離的資料庫表的設計模式
資料維護相對簡單


垂直拆分的缺點:
部分業務表無法Join,只能通過介面方式解決,提高了系統的複雜度
受每種業務的不同限制,存在單庫效能瓶頸,不易進行資料擴充套件和提升效能
事務處理複雜


水平拆分的優點:
單庫單表的資料能保持在一定的量級,有助於效能的提高。
切分的表結構相同,應用層改造較少,只需要增加路由規則即可。
提高了系統的穩定性和負載能力。
水平拆分的缺點:
切分後,資料是分散的,跨庫join操作難和效能差
拆分規則難以抽象
分片事務的一致性難以解決
資料擴容的難度和維護量極大


綜上所述,垂直拆分和水平拆分的共同點為:
存在分散式事務的問題
存在跨節點Join問題
存在跨節點合併排序和分頁問題
存在多資料來源管理的問題
----------------------------------------------------------------------------------
垂直拆分:
       垂直拆分是根據資料庫裡面的資料表的相關性進行拆分,比如:一個數據庫裡面既存在使用者資料,又存在訂單資料,那麼垂直拆分可以把使用者資料放入到使用者庫,把訂單資料放到訂單庫。垂直分表是對資料表進行垂直拆分的一種方式,常見是把一個多欄位的大表按常用欄位和非常用欄位進行拆分,每個表裡面的資料記錄數一般情況下是相同的,只是欄位不一樣,使用主鍵關聯。

比如原始使用者表是:

 

垂直拆分後的表是:



垂直拆分的優點是:

  1. 可以使得資料變小,一個數據塊(block)就能存放更多的資料,在查詢時就會減少I/O次數(每次查詢時讀取的Block就少)

  2. 可以達到最大化利用Cache的目的,具體在垂直拆分的時候可以將不常變的欄位放一起,將經常改變的放一起

  3. 資料維護簡單

 缺點是:

  1. 主鍵出現冗餘,需要管理冗餘例

  2.  會引起表連線JOIN操作(增加CPU開銷)可以通過在業務伺服器上進行join來減少資料庫壓力

  3.  依然存在單表資料量過大的問題(需要水平拆分)

  4. 事務處理複雜

 

水平拆分
概述

水平拆分是通過某種策略將資料分片來儲存,分庫內分表和分庫兩部分,每片資料會分散到不同的MySQL表或庫,達到分散式的效果,能夠支援非常大的資料量。前面的表分割槽本質上也是一種特殊的庫內分表

庫內分表,僅僅是單純的解決了單一表資料過大的問題,由於沒有把表的資料分佈到不同的機器上,因此對於減輕MySQL伺服器的壓力來說,並沒有太大的作用,大家還是競爭同一個物理機上的IO、CPU、網路,這個就要通過分庫來解決

水平拆分表如下:



 

實際情況中往往會是垂直拆分和水平拆分的結合,即將Users_A_M和Users_N_Z再拆成Users和UserExtras,這樣一共四張表

水平拆分的優點是:

不存在單庫大資料和高併發的效能瓶頸
應用端改造較少
提高了系統的穩定性和負載能力
缺點是:

分片事務一致性難以解決
跨節點Join效能差,邏輯複雜
資料多次擴充套件難度跟維護量極大
---------------------