mysql分布式存儲方案
① Mysql Mycat 分布式架構
參考: https://www.jianshu.com/p/5e0062f6cf62
圖中是兩組分片,紅色我們稱為shard1,藍色我們稱為shard2
51 52是伺服器
兩個3307互為主從(雙主),3309是本地3307的從庫
說明:沒有明確說明是只在某一個節點上做的,就是兩個節點都做
兩台虛擬機 db01 db02
每台創建四個mysql實例:3307 3308 3309 3310
mysql軟體我們之前已完成二進制安裝,直接初始化即可
我們server-id規劃為:db01上是7/8/9/10,db02上是17/18/19/20
"箭頭指向誰是主庫"
10.0.0.51:3307 <-----> 10.0.0.52:3307
10.0.0.51:3309 ------> 10.0.0.51:3307
10.0.0.52:3309 ------> 10.0.0.52:3307
兩個分片,每個分片四個mysql節點
shard1:
Master:10.0.0.51:3307
slave1:10.0.0.51:3309
Standby Master:10.0.0.52:3307
slave2:10.0.0.52:3309
shard2:
Master:10.0.0.52:3308
slave1:10.0.0.52:3310
Standby Master:10.0.0.51:3308
slave2:10.0.0.51:3310
shard1
10.0.0.51:3307 <-----> 10.0.0.52:3307
db02
db01
db02
10.0.0.51:3309 ------> 10.0.0.51:3307
db01
10.0.0.52:3309 ------> 10.0.0.52:3307
db02
shard2
10.0.0.52:3308 <-----> 10.0.0.51:3308
db01
db02
db01
10.0.0.52:3310 -----> 10.0.0.52:3308
db02
10.0.0.51:3310 -----> 10.0.0.51:3308
db01
這個復制用戶在誰上建都行
註:如果中間出現錯誤,在每個節點進行執行以下命令
常見方案:
360 Atlas-Sharding 360
Alibaba cobar 阿里
Mycat 開源
TDDL 淘寶
Heisenberg 網路
Oceanus 58同城
Vitess 谷歌
OneProxy
DRDS 阿里雲
我們裝的是openjdk,不是官方的那個
Mycat-server-xxxxx.linux.tar.gz
http://dl.mycat.io/
配置環境變數
我們mycat的命令也是在bin目錄下
啟動
8066就是對外提供服務的埠,9066是管理埠
連接mycat:
默認123456
db01:
我們一般先把原schema.xml備份,然後自己新寫一個:
xml和html看起來差不多,xml是從下往上調用的
前三行我們不用看,直接從第四行schema開始看起:
定義了schema,然後以/schema結尾
為什麼要用邏輯庫?
業務透明化
此配置文件就是實現讀寫分離的配置
重啟mycat
讀寫分離測試
總結:
以上案例實現了1主1從的讀寫分離功能,寫操作落到主庫,讀操作落到從庫.如果主庫宕機,從庫不能在繼續提供服務了。
我們推薦這種架構
一寫三讀,
不設置雙寫的原因是:性能沒提升多少,反而引起主鍵沖突的情況
配置文件:
之後重啟:mycat restart
真正的 writehost:負責寫操作的writehost
standby writeHost :和readhost一樣,只提供讀服務
我們此處寫了兩個writehost,默認使用第一個
當寫節點宕機後,後面跟的readhost也不提供服務,這時候standby的writehost就提供寫服務,
後面跟的readhost提供讀服務
測試:
讀寫分離測試
對db01 3307節點進行關閉和啟動,測試讀寫操作
結果應為另一台(52)的3307(17)是寫,3309(19)是讀
一旦7號節點恢復,此時因為7落後了,寫節點仍是17
balance屬性
負載均衡類型,目前的取值有3種:
writeType屬性
負載均衡類型,目前的取值有2種:
switchType屬性
-1 表示不自動切換
1 默認值,自動切換
2 基於MySQL主從同步的狀態決定是否切換 ,心跳語句為 show slave status
datahost其他配置
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
maxCon="1000":最大的並發連接數
minCon="10" :mycat在啟動之後,會在後端節點上自動開啟的連接線程,長連接,好處是連接速度快,弊端是占內存
tempReadHostAvailable="1"
這個一主一從時(1個writehost,1個readhost時),可以開啟這個參數,如果2個writehost,2個readhost時
<heartbeat>select user()</heartbeat> 監測心跳
其他參數sqlMaxLimit自動分頁,必須在啟用分表的情況下才生效
創建測試庫和表:
我們重啟mycat後連接到8066
發現跟一個庫一樣,實際上已經分到不同的物理硬體上了
分片:對一個"bigtable",比如說t3表
熱點數據表 核心表
(1)行數非常多,800w下坡
(2)訪問非常頻繁
分片的目的:
(1)將大數據量進行分布存儲
(2)提供均衡的訪問路由
分片策略:
范圍 range 800w 1-400w 400w01-800w 不適用於業務訪問不均勻的情況
取模 mod (取余數) 和節點的數量進行取模
枚舉 按枚舉的種類分,如移動項目按省份分
哈希 hash
時間 流水
優化關聯查詢(否則join的表在不同分片上,效率會比單庫還要低)
全局表
ER分片
案例:移動統一:先拆出邊緣業務,再按地域分片,但對應用來說是統一的
vim rule.xml
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>rang-long</algorithm>
</rule>
<function name="rang-long"
class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
</function>
===================================
vim autopartition-long.txt
0-10=0
11-20=1
創建測試表:
mysql -S /data/3307/mysql.sock -e "use taobao;create table t3 (id int not null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t3 (id int not null primary key auto_increment,name varchar(20) not null);"
測試:
重啟mycat
mycat restart
mysql -uroot -p123456 -h 127.0.0.1 -P 8066
insert into t3(id,name) values(1,'a');
insert into t3(id,name) values(2,'b');
insert into t3(id,name) values(3,'c');
insert into t3(id,name) values(4,'d');
insert into t3(id,name) values(11,'aa');
insert into t3(id,name) values(12,'bb');
insert into t3(id,name) values(13,'cc');
insert into t3(id,name) values(14,'dd');
取余分片方式:分片鍵(一個列)與節點數量進行取余,得到余數,將數據寫入對應節點
vim schema.xml
<table name="t4" dataNode="sh1,sh2" rule="mod-long" />
vim rule.xml
<property name="count">2</property>
准備測試環境
創建測試表:
mysql -S /data/3307/mysql.sock -e "use taobao;create table t4 (id int not null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t4 (id int not null primary key auto_increment,name varchar(20) not null);"
重啟mycat
mycat restart
測試:
mysql -uroot -p123456 -h10.0.0.52 -P8066
use TESTDB
insert into t4(id,name) values(1,'a');
insert into t4(id,name) values(2,'b');
insert into t4(id,name) values(3,'c');
insert into t4(id,name) values(4,'d');
分別登錄後端節點查詢數據
mysql -S /data/3307/mysql.sock
use taobao
select * from t4;
mysql -S /data/3308/mysql.sock
use taobao
select * from t4;
t5 表
id name telnum
1 bj 1212
2 sh 22222
3 bj 3333
4 sh 44444
5 bj 5555
sharding-by-intfile
vim schema.xml
<table name="t5" dataNode="sh1,sh2" rule="sharding-by-intfile" />
vim rule.xml
<tableRule name="sharding-by-intfile">
<rule> <columns>name</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
<property name="type">1</property>
<property name="defaultNode">0</property>
</function>
partition-hash-int.txt 配置:
bj=0
sh=1
DEFAULT_NODE=1
columns 標識將要分片的表欄位,algorithm 分片函數, 其中分片函數配置中,mapFile標識配置文件名稱
准備測試環境
mysql -S /data/3307/mysql.sock -e "use taobao;create table t5 (id int not null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t5 (id int not null primary key auto_increment,name varchar(20) not null);"
重啟mycat
mycat restart
mysql -uroot -p123456 -h10.0.0.51 -P8066
use TESTDB
insert into t5(id,name) values(1,'bj');
insert into t5(id,name) values(2,'sh');
insert into t5(id,name) values(3,'bj');
insert into t5(id,name) values(4,'sh');
insert into t5(id,name) values(5,'tj');
a b c d
join
t
select t1.name ,t.x from t1
join t
select t2.name ,t.x from t2
join t
select t3.name ,t.x from t3
join t
使用場景:
如果你的業務中有些數據類似於數據字典,比如配置文件的配置,
常用業務的配置或者數據量不大很少變動的表,這些表往往不是特別大,
而且大部分的業務場景都會用到,那麼這種表適合於Mycat全局表,無須對數據進行切分,
要在所有的分片上保存一份數據即可,Mycat 在Join操作中,業務表與全局表進行Join聚合會優先選擇相同分片內的全局表join,
避免跨庫Join,在進行數據插入操作時,mycat將把數據分發到全局表對應的所有分片執行,在進行數據讀取時候將會隨機獲取一個節點讀取數據。
vim schema.xml
<table name="t_area" primaryKey="id" type="global" dataNode="sh1,sh2" />
後端數據准備
mysql -S /data/3307/mysql.sock
use taobao
create table t_area (id int not null primary key auto_increment,name varchar(20) not null);
mysql -S /data/3308/mysql.sock
use taobao
create table t_area (id int not null primary key auto_increment,name varchar(20) not null);
重啟mycat
mycat restart
測試:
mysql -uroot -p123456 -h10.0.0.52 -P8066
use TESTDB
insert into t_area(id,name) values(1,'a');
insert into t_area(id,name) values(2,'b');
insert into t_area(id,name) values(3,'c');
insert into t_area(id,name) values(4,'d');
A
join
B
為了防止跨分片join,可以使用E-R模式
A join B
on a.xx=b.yy
join C
on A.id=C.id
<table name="A" dataNode="sh1,sh2" rule="mod-long">
<childTable name="B" joinKey="yy" parentKey="xx" />
</table>
當前做分布式的廠商有幾家,我知道比較出名的有「華為雲分布式資料庫DDM」和「阿里雲分布式資料庫」,感興趣可以自行搜素了解下。
分布式資料庫的幾點概念可以了解一下。
數據分庫:
以表為單位,把原有資料庫切分成多個資料庫。切分後不同的表存儲在不同的資料庫上。
以表中的數據行記錄為單位,把原有邏輯資料庫切分成多個物理資料庫分片,表數據記錄分布存儲在各個分片上。
路由分發:
在分布式資料庫中,路由的作用即將SQL語句進行解析,並轉發到正確的分片上,保證SQL執行後得到正確的結果,並且節約QPS資源。
讀寫分離:
資料庫中對計算和緩存資源消耗較多的往往是密集或復雜的SQL查詢。當系統資源被查詢語句消耗,反過來會影響數據寫入操作,進而導致資料庫整體性能下降,響應緩慢。因此,當資料庫CPU和內存資源佔用居高不下,且讀寫比例較高時,可以為資料庫添加只讀資料庫。
③ Mysql資料庫3種存儲引擎有什麼區別
MySQL常見的三種存儲引擎為InnoDB、MyISAM和MEMORY。其區別體現在事務安全、存儲限制、空間使用、內存使用、插入數據的速度和對外鍵的支持。具體如下:
1、事務安全:
InnoDB支持事務安全,MyISAM和MEMORY兩個不支持。
2、存儲限制:
InnoDB有64TB的存儲限制,MyISAM和MEMORY要是具體情況而定。
3、空間使用:
InnoDB對空間使用程度較高,MyISAM和MEMORY對空間使用程度較低。
4、內存使用:
InnoDB和MEMORY對內存使用程度較高,MyISAM對內存使用程度較低。
5、插入數據的速度:
InnoDB插入數據的速度較低,MyISAM和MEMORY插入數據的速度較高。
6、對外鍵的支持:
InnoDB對外鍵支持情況較好,MyISAM和MEMORY兩個不支持外鍵。
三種引擎特點如下:
1、InnoDB存儲引擎
InnoDB是事務型資料庫的首選引擎,支持事務安全表(ACID),其它存儲引擎都是非事務安全表,支持行鎖定和外鍵,MySQL5.5以後默認使用InnoDB存儲引擎。
InnoDB特點: 支持事務處理,支持外鍵,支持崩潰修復能力和並發控制。如果需要對事務的完整性要求比較高(比如銀行),要求實現並發控制(比如售票),那選擇InnoDB有很大的優勢。
如果需要頻繁的更新、刪除操作的資料庫,也可以選擇InnoDB,因為支持事務的提交(commit)和回滾(rollback)。
2、MyISAM存儲引擎
MyISAM基於ISAM存儲引擎,並對其進行擴展。它是在Web、數據倉儲和其他應用環境下最常使用的存儲引擎之一。MyISAM擁有較高的插入、查詢速度,但不支持事務,不支持外鍵。
MyISAM特點: 插入數據快,空間和內存使用比較低。如果表主要是用於插入新記錄和讀出記錄,那麼選擇MyISAM能實現處理高效率。如果應用的完整性、並發性要求比較低,也可以使用
3、MEMORY存儲引擎
MEMORY存儲引擎將表中的數據存儲到內存中,為查詢和引用其他表數據提供快速訪問。
MEMORY特點: 所有的數據都在內存中,數據的處理速度快,但是安全性不高。如果需要很快的讀寫速度,對數據的安全性要求較低,可以選擇MEMOEY。
它對表的大小有要求,不能建立太大的表。所以,這類資料庫只使用在相對較小的資料庫表。
(3)mysql分布式存儲方案擴展閱讀:
mysql其餘不太常見的存儲引擎如下:
1、BDB: 源自Berkeley DB,事務型資料庫的另一種選擇,支持COMMIT和ROLLBACK等其他事務特性
2、Merge :將一定數量的MyISAM表聯合而成一個整體,在超大規模數據存儲時很有用
3、Archive :非常適合存儲大量的獨立的,作為歷史記錄的數據。因為它們不經常被讀取。Archive擁有高效的插入速度,但其對查詢的支持相對較差
4、Federated: 將不同的Mysql伺服器聯合起來,邏輯上組成一個完整的資料庫。非常適合分布式應用
5、Cluster/NDB :高冗餘的存儲引擎,用多台數據機器聯合提供服務以提高整體性能和安全性。適合數據量大,安全和性能要求高的應用
6、CSV: 邏輯上由逗號分割數據的存儲引擎。它會在資料庫子目錄里為每個數據表創建一個.CSV文件。這是一種普通文本文件,每個數據行佔用一個文本行。CSV存儲引擎不支持索引。
7、BlackHole :黑洞引擎,寫入的任何數據都會消失,一般用於記錄binlog做復制的中繼
④ 一個資料庫有兩張表,同步兩張表的數據
如果是同一個mysql服務端的兩個資料庫同步可考慮下觸發器,如果是不同埠的兩個mysql服務端跟在兩台伺服器同步配置上沒有區別。
資料庫最好不要做主從,不然性能會降低很多的。
可以採取其他的方法撒,比如分布式存儲。可以考慮下memcachedb,實現持久存儲。
表結構一致的話,可以考慮映射表去實現來的(shell腳本定時同步,觸發器),不過shell腳本會將環境搞的復雜一點,維護也會相對麻煩.
映射表具體實現(在要同步的資料庫下創建相同的表結構):
CREATE TABLE table_name
(
column_name column_type ....
....
key ....
)
ENGINE=MYISAM DEFAULT CHARSET=utf8
CONNECTION="mysql://user:pwd@ip_address/db_name/table_name";
⑤ 單機MySQL資料庫怎麼做成分布式資料庫集群
"可以採用開源的MyCat解決方案,優點是免費,缺點是出現問題可能要自己解決或者去社區尋找解決方案;
也可以採用北京萬里開源軟體有限公司的集群解決方案,後端使用開源的MySQL存儲數據,優點是有任何問題他們都可以幫忙解決,而且不用擔心系統後續的擴展、集群高可用等情況,他們的工程師還開發過MySQL核心代碼,找他們可以睡個安穩覺,缺點是不免費,他們還有自己的國產資料庫GreatDB,100%兼容MySQL。
對於初創企業,可以考慮選擇免費的開源解決方案,畢竟遇到的問題可能有限,如果要想長期穩定發展,還是選擇萬里開源這樣的公司比較靠譜一些。"
⑥ 一個大型、穩健、成熟的分布式系統的背後,往往會涉及眾多的支撐系統基礎設施
樹苗中2包是需要混合浸泡嗎?一個大型、穩健、成熟的分布式系統的背後,往往會涉及眾多的支撐系統,我們將這些支撐系統稱為分布式系統的基礎設施。除了前面所介紹的分布式協作及配置管理系統ZooKeeper,我們進行系統架構設計所依賴的基礎設施,還包括分布式緩存系統、持久化存儲、分布式消息系統、搜索引擎,以及CDN系統、負載均衡系統、運維自動化系統等,還有後面章節所要介紹的實時計算系統、離線計算系統、分布式文件系統、日誌收集系統、監控系統、數據倉庫等。
分布式緩存主要用於在高並發環境下,減輕資料庫的壓力,提高系統的響應速度和並發吞吐。當大量的讀、寫請求湧向資料庫時,磁碟的處理速度與內存顯然不在一個量級,因此,在資料庫之前加一層緩存,能夠顯著提高系統的響應速度,並降低資料庫的壓力。作為傳統的關系型資料庫,MySQL提供完整的ACID操作,支持豐富的數據類型、強大的關聯查詢、where語句等,能夠非常客易地建立查詢索引,執行復雜的內連接、外連接、求和、排序、分組等操作,並且支持存儲過程、函數等功能,產品成熟度高,功能強大。但是,對於需要應對高並發訪問並且存儲海量數據的場景來說,出於對性能的考慮,不得不放棄很多傳統關系型資料庫原本強大的功能,犧牲了系統的易用性,並且使得系統的設計和管理變得更為復雜。這也使得在過去幾年中,流行著另一種新的存儲解決方案——NoSQL,它與傳統的關系型資料庫最大的差別在於,它不使用SQL作為查詢語言來查找數據,而採用key-value形式進行查找,提供了更高的查詢效率及吞吐,並且能夠更加方便地進行擴展,存儲海量數據,在數千個節點上進行分區,自動進行數據的復制和備份。在分布式系統中,消息作為應用間通信的一種方式,得到了十分廣泛的應用。消息可以被保存在隊列中,直到被接收者取出,由於消息發送者不需要同步等待消息接收者的響應,消息的非同步接收降低了系統集成的耦合度,提升了分布式系統協作的效率,使得系統能夠更快地響應用戶,提供更高的吞吐。
當系統處於峰值壓力時,分布式消息隊列還能夠作為緩沖,削峰填谷,緩解集群的壓力,避免整個系統被壓垮。垂直化的搜索引擎在分布式系統中是一個非常重要的角色,它既能夠滿足用戶對於全文檢索、模糊匹配的需求,解決資料庫like查詢效率低下的問題,又能夠解決分布式環境下,由於採用分庫分表,或者使用NoSQL資料庫,導致無法進行多表關聯或者進行復雜查詢的問題。
⑦ 分布式緩存是什麼
分布式緩存主要用於在高並發環境下,減輕資料庫的壓力,提高系統的響應速度和並發吞吐。當大量的讀、寫請求湧向資料庫時,磁碟的處理速度與內存顯然不在一個量級,因此,在資料庫之前加一層緩存,能夠顯著提高系統的響應速度,並降低資料庫的壓力。作為傳統的關系型資料庫,MySQL提供完整的ACID操作,支持豐富的數據類型、強大的關聯查詢、where語句等,能夠非常客易地建立查詢索引,執行復雜的內連接、外連接、求和、排序、分組等操作,並且支持存儲過程、函數等功能,產品成熟度高,功能強大。但是,對於需要應對高並發訪問並且存儲海量數據的場景來說,出於對性能的考慮,不得不放棄很多傳統關系型資料庫原本強大的功能,犧牲了系統的易用性,並且使得系統的設計和管理變得更為復雜。這也使得在過去幾年中,流行著另一種新的存儲解決方案——NoSQL,它與傳統的關系型資料庫最大的差別在於,它不使用SQL作為查詢語言來查找數據,而採用key-value形式進行查找,提供了更高的查詢效率及吞吐,並且能夠更加方便地進行擴展,存儲海量數據,在數千個節點上進行分區,自動進行數據的復制和備份。在分布式系統中,消息作為應用間通信的一種方式,得到了十分廣泛的應用。消息可以被保存在隊列中,直到被接收者取出,由於消息發送者不需要同步等待消息接收者的響應,消息的非同步接收降低了系統集成的耦合度,提升了分布式系統協作的效率,使得系統能夠更快地響應用戶,提供更高的吞吐。
當系統處於峰值壓力時,分布式消息隊列還能夠作為緩沖,削峰填谷,緩解集群的壓力,避免整個系統被壓垮。垂直化的搜索引擎在分布式系統中是一個非常重要的角色,它既能夠滿足用戶對於全文檢索、模糊匹配的需求,解決資料庫like查詢效率低下的問題,又能夠解決分布式環境下,由於採用分庫分表,或者使用NoSQL資料庫,導致無法進行多表關聯或者進行復雜查詢的問題。
⑧ MySQL的sharding的程序是不是要自己開發的
不一定需要自己開發。Shard層可以位於:
1、DAO層:一般需要自行開發,可以靈活定製
2、ORM層:比如guzz、Hibernate Shard
3、JDBC API層:比較難,有一個商業產品dbShards
4、應用伺服器與資料庫之間通過代理實現:MySQL Proxy、amoeba.....
一 背景
當資料庫中的數據量越來越大時,不論是讀還是寫,壓力都會變得越來越大。採用MySQL
Replication多master多slave方案,在上層做負載均衡,雖然能夠一定程度上緩解壓力。但是當一張表中的數據變得非常龐大時,壓力還是
非常大的。試想,如果一張表中的數據量達到了千萬甚至上億級別的時候,不管是建索引,優化緩存等,都會面臨巨大的性能壓力。
二 定義
數據sharding,也稱作數據切分,或分區。是指通過某種條件,把同一個資料庫中的數據分散到多個資料庫或多台機器上,以減小單台機器壓力。
三 分類
數據分區根據切分規則,可以分為兩類:
1、垂直切分
數據的垂直切分,也可以稱之為縱向切分。將資料庫想像成為由很多個一大塊一大塊的「數據塊」(表)組成,我們垂直的將這些「數據塊」切開,然後將他們分散
到多台資料庫主機上面。這樣的切分方法就是一個垂直(縱向)的數據切分。以表為單位,把不同的表分散到不同的資料庫或主機上。規則簡單,實施方便,適合業
務之間耦合度低的系統。
Sharding詳解" title="MySQL Sharding詳解" height="373" width="553">
垂直切分的優點
(1)資料庫的拆分簡單明了,拆分規則明確;
(2)應用程序模塊清晰明確,整合容易;
(3)數據維護方便易行,容易定位;
垂直切分的缺點
(1)部分表關聯無法在資料庫級別完成,需要在程序中完成;
(2)對於訪問極其頻繁且數據量超大的表仍然存在性能平靜,不一定能滿足要求;
(3)事務處理相對更為復雜;
(4) 切分達到一定程度之後,擴展性會遇到限制;
(5)過讀切分可能會帶來系統過渡復雜而難以維護。
2、水平切分
一般來說,簡單的水平切分主要是將某個訪問極其平凡的表再按照某個欄位的某種規則來分散到多個表之中,每個表中包含一部分數據。以行為單位,將同一個表中的數據按照某種條件拆分到不同的資料庫或主機上。相對復雜,適合單表巨大的系統。
Sharding詳解" title="MySQL Sharding詳解" height="372" width="553">
水平切分的優點
(1)表關聯基本能夠在資料庫端全部完成;
(2)不會存在某些超大型數據量和高負載的表遇到瓶頸的問題;
(3)應用程序端整體架構改動相對較少;
(4)事務處理相對簡單;
(5)只要切分規則能夠定義好,基本上較難遇到擴展性限制;
水平切分的缺點
(1)切分規則相對更為復雜,很難抽象出一個能夠滿足整個資料庫的切分規則;
(2)後期數據的維護難度有所增加,人為手工定位數據更困難;
(3)應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分造成一定的困難。
3、聯合切分
實際的應用場景中,除了那些負載並不是太大,業務邏輯也相對較簡單的系統可以通過上面兩種切分方法之一來解決擴展性問題之外,恐怕其他大部分業務邏輯稍微
復雜一點,系統負載大一些的系統,都無法通過上面任何一種數據的切分方法來實現較好的擴展性,而需要將上述兩種切分方法結合使用,不同的場景使用不同的切
分方法。
Sharding詳解" title="MySQL Sharding詳解" height="480" width="342">
聯合切分的優點
(1)可以充分利用垂直切分和水平切分各自的優勢而避免各自的缺陷;
(2)讓系統擴展性得到最大化提升;
聯合切分的缺點
(1)資料庫系統架構比較復雜,維護難度更大;
(2)應用程序架構也相對更復雜;
四 實現方案
現在 Sharding 相關的軟體實現其實不少,基於資料庫層、DAO 層、不同語言下也都不乏案例。限於篇幅,此處只作一下簡要的介紹。
1、 Mysql Proxy + HASCALE
一套比較有潛力的方案。其中MySQL Proxy 是用 Lua 腳本實現的,介於客戶端與伺服器端之間,扮演 Proxy
的角色,提供查詢分析、失敗接管、查詢過濾、調整等功能。目前的 0.6 版本還做不到讀、寫分離。HSCALE 則是針對 MySQL Proxy 插件,也是用
Lua 實現的,對 Sharding 過程簡化了許多。需要指出的是,MySQL Proxy 與 HSCALE
各自會帶來一定的開銷,但這個開銷與集中式數據處理方式單條查詢的開銷還是要小的。
MySQLProxy是MySQL官方提供的一個資料庫代理層產品,和MySQLServer一樣,同樣是一個基於GPL開源協議的開源產品。可用來監視、分析或者傳輸他們之間的通訊信息。他的靈活性允許你最大限度的使用它,目前具備的功能主要有連接路由,Query分析,Query過濾和修改,負載均衡,以及基本的HA機制等。
實際上,MySQLProxy本身並不具有上述所有的這些功能,而是提供了實現上述功能的基礎。要實現這些功能,還需要通過我們自行編寫LUA腳本來實現。
MySQLProxy實際上是在客戶端請求與MySQLServer之間建立了一個連接池。所有客戶端請求都是發向MySQLProxy,然後經由MySQLProxy進行相應的分析,判斷出是讀操作還是寫操作,分發至對應的MySQLServer上。對於多節點Slave集群,也可以起做到負載均衡的效果。以下是MySQLProxy的基本架構圖:
Sharding詳解" title="MySQL Sharding詳解" height="480" width="420">
通過上面的架構簡圖,我們可以很清晰的看出MySQLProxy在實際應用中所處的位置,以及能做的基本事情。關於MySQLProxy更為詳細的實施細則在MySQL官方文檔中有非常詳細的介紹和示例,感興趣的讀者朋友可以直接從MySQL官方網站免費下載或者在線閱讀,我這里就不累述浪費紙張了。
http://forge.mysql.com/wiki/MySQL_Proxy
2、 Hibernate Shards
這是 Google 技術團隊貢獻的項目(http://www.hibernate.org/414.html),該項目是在對Google 財務系統數據
Sharding 過程中誕生的。因為是在框架層實現的,所以有其獨特的特性:標準的 Hibernate 編程模型,會用 Hibernate
就能搞定,技術成本較低;相對彈性的 Sharding 策略以及支持虛擬 Shard 等。
3、 Spock Proxy
這也是在實際需求中產生的一個開源項目,基於Mysql Proxy擴展。Spock(http://www.spock.com/)是一個人員查找的 Web
2.0 網站。通過對自己的單一 DB 進行有效 Sharding化 而產生了Spock
Proxy(http://spockproxy.sourceforge.net/ ) 項目,Spock Proxy 算得上 MySQL Proxy
的一個分支,提供基於范圍的 Sharding 機制。Spock 是基於 Rails 的,所以Spock Proxy 也是基於 Rails 構建,關注 ROR
的朋友不應錯過這個項目。
http://spockproxy.sourceforge.net/
4、 Amoeba for MySQL
Amoeba是一個基於Java開發的,專注於解決分布式資料庫數據源整合Proxy程序的開源框架,基於GPL3開源協議。目前,Amoeba已經具有Query路由,Query過濾,讀寫分離,負載均衡以及HA機制等相關內容。
Amoeba 主要解決的以下幾個問題:
(1)數據切分後復雜數據源整合;
(2)提供數據切分規則並降低數據切分規則給資料庫帶來的影響;
(3)降低資料庫與客戶端的連接數;
(4)讀寫分離路由。
我們可以看出,Amoeba所做的事情,正好就是我們通過數據切分來提升資料庫的擴展性所需要的。
Amoeba並不是一個代理層的Proxy程序,而是一個開發資料庫代理層Proxy程序的開發框架,目前基於Amoeba所開發的Proxy程序有AmoebaForMySQL和AmoebaForAladin兩個。
AmoebaForMySQL主要是專門針對MySQL資料庫的解決方案,前端應用程序請求的協議以及後端連接的數據源資料庫都必須是MySQL。對於客戶端的任何應用程序來說,AmoebaForMySQL和一個MySQL資料庫沒有什麼區別,任何使用MySQL協議的客戶端請求,都可以被AmoebaForMySQL解析並進行相應的處理。下如可以告訴我們AmoebaForMySQL的架構信息(出自Amoeba開發者博客):
Sharding詳解" title="MySQL Sharding詳解" height="480" width="384">
AmoebaForAladin則是一個適用更為廣泛,功能更為強大的Proxy程序。他可以同時連接不同資料庫的數據源為前端應用程序提供服務,但是僅僅接受符合MySQL協議的客戶端應用程序請求。也就是說,只要前端應用程序通過MySQL協議連接上來之後,AmoebaForAladin會自動分析Query語句,根據Query語句中所請求的數據來自動識別出該所Query的數據源是在什麼類型資料庫的哪一個物理主機上面。下圖展示了AmoebaForAladin的架構細節(出自Amoeba開發者博客):
Sharding詳解" title="MySQL Sharding詳解" height="480" width="384">
咋一看,兩者好像完全一樣嘛。細看之後,才會發現兩者主要的區別僅在於通過MySQLProtocalAdapter處理之後,根據分析結果判斷出數據源資料庫,然後選擇特定的JDBC驅動和相應協議連接後端資料庫。
其實通過上面兩個架構圖大家可能也已經發現了Amoeba的特點了,他僅僅只是一個開發框架,我們除了選擇他已經提供的ForMySQL和ForAladin這兩款產品之外,還可以基於自身的需求進行相應的二次開發,得到更適應我們自己應用特點的Proxy程序。
當對於使用MySQL資料庫來說,不論是AmoebaForMySQL還是AmoebaForAladin都可以很好的使用。當然,考慮到任何一個系統越是復雜,其性能肯定就會有一定的損失,維護成本自然也會相對更高一些。所以,對於僅僅需要使用MySQL資料庫的時候,我還是建議使用AmoebaForMySQL。
AmoebaForMySQL的使用非常簡單,所有的配置文件都是標準的XML文件,總共有四個配置文件。分別為:
(1)amoeba.xml:主配置文件,配置所有數據源以及Amoeba自身的參數設置;
(2)rule.xml:配置所有Query路由規則的信息;
(3)functionMap.xml:配置用於解析Query中的函數所對應的Java實現類;
(4)rullFunctionMap.xml:配置路由規則中需要使用到的特定函數的實現類;
如果您的規則不是太復雜,基本上僅需要使用到上面四個配置文件中的前面兩個就可完成所有工作。Proxy程序常用的功能如讀寫分離,負載均衡等配置都在amoeba.xml中進行。此外,Amoeba已經支持了實現數據的垂直切分和水平切分的自動路由,路由規則可以在rule.xml進行設置。
目前Amoeba少有欠缺的主要就是其在線管理功能以及對事務的支持了,曾經在與相關開發者的溝通過程中提出過相關的建議,希望能夠提供一個可以進行在線維護管理的命令行管理工具,方便在線維護使用,得到的反饋是管理專門的管理模塊已經納入開發日程了。另外在事務支持方面暫時還是Amoeba無法做到的,即使客戶端應用在提交給Amoeba的請求是包含事務信息的,Amoeba也會忽略事務相關信息。當然,在經過不斷完善之後,我相信事務支持肯定是Amoeba重點考慮增加的feature。
關於Amoeba更為詳細的使用方法讀者朋友可以通過Amoeba開發者博客(http://amoeba.sf.net)上面提供的使用手冊獲取,這里就不再細述了。
案例(http://pengranxiang.iteye.com/blog/1145342)
操作文檔(http://docs.hexnova.com/amoeba/chap-getting-started.html)
5、 HiveDB
和前面的MySQLProxy以及Amoeba一樣,HiveDB同樣是一個基於Java針對MySQL資料庫的提供數據切分及整合的開源框架,只是目前的HiveDB僅僅支持數據的水平切分。主要解決大數據量下資料庫的擴展性及數據的高性能訪問問題,同時支持數據的冗餘及基本的HA機制。
HiveDB的實現機制與MySQLProxy和Amoeba有一定的差異,他並不是藉助MySQL的Replication功能來實現數據的冗餘,而是自行實現了數據冗餘機制,而其底層主要是基於HibernateShards來實現的數據切分工作。
在HiveDB中,通過用戶自定義的各種Partitionkeys(其實就是制定數據切分規則),將數據分散到多個MySQLServer中。在訪問的時候,在運行Query請求的時候,會自動分析過濾條件,並行從多個MySQLServer中讀取數據,並合並結果集返回給客戶端應用程序。
單純從功能方面來講,HiveDB可能並不如MySQLProxy和Amoeba那樣強大,但是其數據切分的思路與前面二者並無本質差異。此外,HiveDB並不僅僅只是一個開源愛好者所共享的內容,而是存在商業公司支持的開源項目。
下面是HiveDB官方網站上面一章圖片,描述了HiveDB如何來組織數據的基本信息,雖然不能詳細的表現出太多架構方面的信息,但是也基本可以展示出其在數據切分方面獨特的一面了。
Sharding詳解" title="MySQL Sharding詳解" height="471" width="553">
http://www.hivedb.org/
6、 DataFabric
application-level sharding
master/slave replication
https://github.com/bpot/data_fabric
7、PL/Proxy
前面幾個都是針對MySQL 的 Sharding 方案,PL/Proxy 則是針對 PostgreSQL 的,設計思想類似 Teradata 的
Hash 機制,數據存儲對客戶端是透明的,客戶請求發送到 PL/Proxy 後,由這里分布式存儲過程調用,統一分發。 PL/Proxy
的設計初衷就是在這一層充當」數據匯流排」的職責,所以,當數據吞吐量支撐不住的時候,只需要增加更多的 PL/Proxy 伺服器即可。大名鼎鼎的 Skype 用的就是
PL/Proxy 的解決方案。
8、Pyshards
這是個基於Python的解決方案。該工具的設計目標還有個 Re-balancing 在裡面,這倒是個比較激進的想法。目前只支持 MySQL
資料庫。
http://code.google.com/p/pyshards/wiki/Pyshards
9、其他實現數據切分及整合的解決方案
除了上面介紹的幾個數據切分及整合的整體解決方案之外,還存在很多其他同樣提供了數據切分與整合的解決方案。如基於MySQLProxy的基礎上做了進一步擴展的HSCALE,通過Rails構建的SpockProxy,以及基於Pathon的Pyshards等等。
不管大家選擇使用哪一種解決方案,總體設計思路基本上都不應該會有任何變化,那就是通過數據的垂直和水平切分,增強資料庫的整體服務能力,讓應用系統的整體擴展能力盡可能的提升,擴展方式盡可能的便捷。
只要我們通過中間層Proxy應用程序較好的解決了數據切分和數據源整合問題,那麼資料庫的線性擴展能力將很容易做到像我們的應用程序一樣方便,只需要通過添加廉價的PCServer伺服器,即可線性增加資料庫集群的整體服務能力,讓資料庫不再輕易成為應用系統的性能瓶頸。
五 注意事項
下面我們所說的分區,主要是指水平分區。
1、在實施分區前,我們可以查看所安裝版本的mysql是否支持分區:
mysql> show variables like "%partition%";
如果支持則會顯示:
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| have_partitioning | YES |
+-------------------+-------+
2、分區適用於一個表的所有數據和索引,不能只對數據分區而不對索引分區,反之亦然,同時也不能只對表的一部分進行分區。
3、分區類型
(1)RANGE 分區:基於屬於一個給定連續區間的列值,把多行分配給分區。
(2)LIST 分區:類似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。
(3)HASH分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算(新浪微博採用的方案)。
(4)KEY 分區:類似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL
伺服器提供其自身的哈希函數。必須有一列或多列包含整數值。
無論使用何種類型的分區,分區總是在創建時就自動的順序編號,且從0開始記錄。當有一新行插入到一個分區表中時,就是使用這些分區編號來識別正確的分區。
4、MySQL提供了許多修改分區表的方式。添加、刪除、重新定義、合並或拆分已經存在的分區是可能的。所有這些操作都可以通過使用ALTER TABLE
命令的分區擴展來實現。
5、可以對已經存在的表進行分區,直接使用alter table命令即可。