分庫分表概念
按字面解釋,分庫是把本來存儲於一個庫的數據分塊存儲到多個庫上,分表是把本來存儲於一個表的數據分塊存儲到多個表上。
合理的分庫能夠下降單臺服務器的負載壓力,合理的分表能夠提高數據操做的效率。java
分庫分表實施時能夠分爲:垂直切分和水平切分。
垂直切分
垂直切分是將表按照功能模塊、關係密切程度劃分出來,部署到不一樣的庫上,也就是分庫。依據原則:將業務緊密,表間關聯密切的表劃分在一塊兒。
例如,咱們會創建定義數據庫workDB、商品數據庫payDB、用戶數據庫userDB、日誌數據庫logDB等,分別用於存儲項目數據定義表、商品定義表、用戶數據表、日誌數據表等。mysql
水平切分
水平切分是將表的數據按某種特定規範進行散列劃分,而後存儲到多個結構相同的表上。要實現水平切分,表中必須有冗餘字段做爲切分依據和標誌字段。
例如,咱們的userDB中的用戶數據表中,每個表的數據量都很大,就能夠把userDB切分爲結構相同的多個userDB:part0DB、part1DB等,
再將userDB上的用戶數據表userTable,切分爲不少userTable:userTable0、userTable1等,而後將這些表按照必定的規則存儲到多個userDB上。sql
數據切分原則
實施數據庫分庫分表不只僅是一個技術方案,它須要開發人員充分了解系統業務邏輯和數據庫schema,既要考慮業務邏輯的維護成本和可擴展性,同時也要兼顧數據庫的性能及瓶頸。
若是數據庫是由於表太多而形成海量數據,而且項目的各項業務邏輯劃分清晰、低耦合,那麼規則簡單明瞭、容易實施的垂直切分必是首選。
若是數據庫中的表並很少,但單表的數據量很大、或數據熱度很高,這種狀況之下就應該選擇水平切分。
在現實項目中,每每是這兩種狀況兼而有之,這就須要作出權衡,甚至既須要垂直切分,又須要水平切分。
一般先對數據庫進行垂直切分,而後,再針對一部分表,一般是用戶數據表,進行水平切分。
分庫分表也不是萬能方案,與單庫相比會帶來以下問題:數據庫
分佈式事務問題。若是用數據庫自身分佈式事務管理,會付出高昂的性能代價;用程序邏輯控制,會形成開發上額外負擔及風險。
跨庫跨表的join問題。程序沒法join位於不一樣分庫的表,也沒法join分表粒度不一樣的表,結果本來一次查詢可以完成的業務,可能須要屢次查詢才能完成。
額外的數據管理負擔和數據運算壓力。
通常來講分庫分表能夠在如下層面進行實現:編程
實現層面
產品與框架
數據訪問層(DAO層) 項目組自行實現
DAO與JDBC間的Spring數據訪問封裝層 CobarClient
JDBC驅動層 dbShards shardingjdbc(噹噹開源)
ORM框架層 Guzz 、HibernateShards
應用服務器與數據庫間的代理層 Routing4DB、TDDL、MysqlProxy、Amoeba服務器
DAO層實現
優點:
DAO層能夠直接得到數據庫表以及參數信息,無需SQL解析和路由規則匹配才能定位分區分片。
不受ORM框架制約,易於根據系統特色進行靈活的定製。
性能上沒有額外的解析匹配,表現通常會比較好一些。
劣勢:
有必定技術門檻,須要自行實現分庫分表相關功能和特性。
因爲缺乏框架支持,代碼工做量會額外增長許多。
難以造成通用框架,每每只能在特定系統裏工做。固然,在DAO層一樣能夠經過XML配置或是註解將分片邏輯抽離到「外部」,造成配置邏輯的可複用。mybatis
總結:通常小型項目纔會採用這種技術選型,中大型項目會帶來巨大的維護成本和風險。架構
Spring數據訪問封裝層實現
優點:
能夠對上層代碼透明。經過Spring的各類template來管理資源的建立與釋放以及與事務的同步,能夠達到和JDBC驅動層實現基本一致的效果,但實現就容易多了。
不受ORM框架制約。oracle
劣勢:
須要依賴Spring。嚴格上說,目前Spring大行其道的今天,這不是一個問題,幾乎沒有哪一個java平臺上構建的應用不使用Spring。
表明產品:阿里集團研究院開源的CobarClient。
CobarClient簡介:
它是阿里巴巴研發的關係型數據的分佈式處理系統,該產品成功替代了原先基於Oracle的數據存儲方案,目前已經接管了3000+個MySQL數據庫的schema,
平均天天處理近50億次的SQL執行請求,優異的數據庫性能和可靠的穩定性是它的突出優勢,可是它存在以下限制:
只支持Mysql數據庫,能夠認爲是CobarClient就是一種Mysql的大型集羣方案。
有限度支持SQL語句,例如:不支持跨庫狀況下的join、分頁、排序、子查詢操做;分庫狀況下,insert語句必須包含拆分字段列名等。
有限度支持JDBC,例如:不支持useServerPrepStmts=true參數設置;BLOB, BINARY, VARBINARY字段不能使用setBlob()或setBinaryStream()方法設置參數等。app
ORM框架層實現
優點:
能夠和ORM無縫集合,減小開發工做量。
劣勢:
受ORM框架制約。若是ORM框架發生變更,就會帶來很大的維護成本。例如:hibernate下有hibernateShards的分庫分表方案,
而mybatis由於插件機制控制不到多數據源的鏈接層面尚未成熟的分庫分表框架。
O-RMapping的支持有限,不少場合仍是須要手動編寫SQL。
表明產品:開源軟件Guzz、hibernate的擴展產品hibernateShards。
Guzz簡介:
Guzz是一種用來進行快速開發和高性能網站設計的框架,用於替代或者補充hibernate或mybatis的持久化實現,並提供更多的大型系統架構設計支持。
支持像hibernate同樣的對象持久,映射和方便的增刪改查
支持像ibatis同樣,讓dba參與sql設計的複雜數據庫操做和優化
支持大量的數據庫和主從分離
支持數據表在多組機器中水平分佈(Shard)
它自己是以網站開發爲主要目的,所以分庫分表並不是核心,仍是有很多侷限:
須要手動編寫分片路由規則的java類,不能徹底依靠配置完成。
有限度支持SQL語句,例如:不支持分庫分表狀況下的join、Union等操做。
hibernateShards簡介:
多數據庫水平分區解決方案,Hibernate的一個擴展,用於處理多數據庫水平分區架構。由google工程師在2007年捐獻給Hibernate社區
JDBC API層實現
JDBC驅動層是不少人都會想到的一個實現分庫分表的絕佳場所,若是能作到此點,那麼分庫分表方案對於整個應用程序來講就是徹底透明的。
可是涉及各類平臺的數據庫,這種方案的技術門檻和工做量顯然不是通常團隊能作得來的,所以基本上沒有團隊會在這一層面上實現分庫分表,甚至也沒有此類的開源產品。
筆者知道的只有一款商業產品dbShards採用的是這一方案。能夠採用噹噹開源的shardingjdbc產品。
代理實現
優點:
對應用程序徹底透明,通用性好。這種方案在應用服務器與數據庫之間加入一個代理,應用程序向數據發出的數據請求會先經過代理,
代理會根據配置的路由規則,對SQL進行解析後路由到目標分片。業務層徹底不知道這些操做,所以這也成了不少中間件產品的選擇方案。
可靠性高,不依賴任何框架。
劣勢:
性能不是最優的。由於增長了代理,增長了額外的消息通信,對於實時性很高的業務系統,須要慎重考慮。
表明產品:TDDL、MysqlProxy、Amoeba
TDDL簡介:
淘寶根據本身的業務特色開發了TDDL框架,主要解決了分庫分表對應用的透明化以及異構數據庫之間的數據複製,它是一個基於集中式配置的jdbc數據源實現,
具備主備,讀寫分離,動態數據庫配置等功能。可是它存在以下限制:
支持mysql和oracle數據庫,支持的數據庫種類比較少。
只開源動態數據源,分表分庫部分還未開源。TDDL必需要依賴diamond配置中心(diamond是淘寶內部使用的一個管理持久配置的系統,
目前淘寶內部絕大多數系統的配置,由diamond來進行統一管理,同時diamond也已開源)。
TDDL複雜度相對較高,當前公佈的文檔較少。
MysqlProxy簡介:
它是Mysql的官方代理工具,處於客戶端和MySQL服務端之間的中間層程序,它能夠監測、分析或改變它們的通訊。它使用靈活,沒有限制,
常見的用途包括:負載平衡,故障、查詢分析,查詢過濾和修改等等,它的侷限很明顯:
只支持Mysql數據庫,並非一種通用技術解決方案。
使用lua腳本,能夠實現複雜的鏈接控制和過濾。這一點技術團隊必須考慮額外的學習成本。
Amoeba簡介:
Amoeba是一個以MySQL爲底層數據存儲,並對應用提供MySQL協議接口的proxy。它集中地響應應用的請求,依據用戶事先設置的規則,
將SQL請求發送到特定的數據庫上執行。基於此能夠實現負載均衡、讀寫分離、高可用性等需求。它使用很是簡單,不使用任何編程語言,只須要經過xml進行配置。
它的侷限以下:只支持Mysql數據庫,並非一種通用技術解決方案。
還不支持事務。
只支持主從模式,還不支持分庫分表。
還有一個很重要的就是Mycat,功能強大,能夠參考。
開源選擇的兩個形式:jdbc層:shardingjdbc。
不作任何修改,直接遷移的mycat