MySQL分片高可用集羣之MySQL Cluster部署使用

MySQL Cluster 是MySQL官方出品的分佈式數據庫解決方案,使用的數據庫引擎爲NDB,跟單機下的MyISAM和Innodb引擎有所不同,操作界面之一就是MySQL,此外提供原生API,可以節省資源並加快執行速度。該方案比業界其他MySQL集羣方案在數據量大時有更大優勢,開發者使用上跟單庫操作幾乎無差異,原先使用MySQL的話幾乎可以無縫遷移,就可以享受集羣帶來的力量。當然也有個明顯的缺點:內存開銷非常大,如果要選擇該方案,需要足夠的硬件內存資源。下面我們詳細地講述MySQL Cluster 的部署使用。


第一步:下載安裝

我們可以從MySQL的官網上下載到http://dev.mysql.com/downloads/cluster/ 
此處我們下載的是源碼版mysql-cluster-gpl-7.4.8.tar.gz,您可根據自己的情況選擇其他二進制版本,免去依賴的安裝。編譯依賴比mysql多幾個,主要注意下這裏需要jdk7。只有jre是不夠的,jdk8目前不支持。其他的依賴都沒有特別的。

$ BUILD/autorun.sh
$ ./configure --prefix=/home/lyw/db/mysql-cluster
$ make -j4
$ sudo make install

安裝好後我們可以看看bin目錄下的內容,裏面不僅有mysql開頭的mysql相關文件,而且多了很多ndb開頭的文件,這些ndb開頭的文件就是MySQL Cluster的核心所在了。


第二步:用工具自動部署

從7.3版本開始,MySQL Cluster提供了一個自動部署工具,這真的是大大降低的入門的難度。

1.    啓動自動部署工具
如果我們用的是桌面版,我們運行下面的命令,會自動用瀏覽器打開一個部署頁面,

$ bin/ndb_setup.py

如果是服務器版,需要增加兩個參數,免得在自己機器上打不開網頁,如果有防火牆請允許對應端口訪問。

$ bin/ndb_setup.py  -N 192.168.1.8  -p 8081

然後根據提示打開對應的網頁,這裏是http://192.168.1.8:8081/welcome.html
我們點擊頁面上的文字鏈接“Create New MySQL Cluster”,進入下面的頁面

wKioL1Y7Dmmyg9rXAADxD6jXEl4312.jpg


Application area中:
        第一項simple testing意思是隻分配很少的內存,因此只能存一點點數據
        第二項Web application則會盡量多分配內存。(具體多少根據下面幾頁配置決定)
        第三項realtime是在Web application的基礎上,縮短心跳的間隔,能更快的發現機器故障。
Write load中:
        三項的對應的寫吞吐率,第一項小於100/s,第二項100~1000/s,第三項1000/s以上。
一般測試我們選擇Web application和Medium就好了,一般都能應付。
下面的SSH property部分需要在多臺機器部署時有用,如果跟hadoop一樣已經有免密碼登陸,則不用改,如果需要密碼登陸,則寫上機器的用戶名密碼。我們這裏是本機部署因此無所謂。

2.    進入下一頁服務器配置:

wKiom1Y7Diqigd-xAADNgtbz9Ik113.jpg

默認情況下Memory會配置爲本機的所有內存,這樣會導致內存不足而啓動失敗,請少配置一點。不過也不能太少,單機時最少1.8G,當配置小於1.8G時,基本上存不了什麼數據,那時操作會報一些看起來奇怪的錯誤,因爲跟其他的引擎錯誤不同。
如果您有很多機器,可以點擊左下角的AddHost按鈕多增加幾臺,每臺的內存需要在450M以上,總內存還是需要在1.8G以上。


3.    進入下一頁進程配置:

wKioL1Y7DmqA_eG7AADmqAPDcx4758.jpg


默認情況下會配置1個管理節點,2個數據節點,2個MySQL節點,另外還有3個API結點(直接用Ndb API連接及ndb工具運行時使用)。
自動配置時一般每個Data節點和MySQL節點都需要450M以上內存(普通MySQL只需要100M,這裏會特別費內存),最好稍微計算下內存是否夠用。如果內存足夠,可以點擊左下角的Add process按鈕增加幾個數據節點,其他節點測試時一般不用增加。如下圖。

wKiom1Y7DiqCa3HUAACeej_pWfM341.jpg


4.    再下一頁是配置修改

wKioL1Y7DmujjQD3AAGLg1imffo312.jpg


我們可以點擊綠色圈的“+”修改一下端口,路徑等。管理節點的默認端口號是1186,如果修改了端口號,那後面的操作都需要增加參數。SQL節點使用了3306, 3307這樣的默認端口,如果本機跑了其他MySQL佔用了這兩個端口,請修改下。

5.    最後進入下一頁部署啓動

wKiom1Y7DiuCOim9AAHrhw4RU0s212.jpg


只要點擊下面中間那個”Deply and start cluster”按鈕,然後等待一分鐘左右,讓進度條走完,除API外狀態都變綠圈圈,MySQL Cluster就部署成功了。

wKioL1Y7DmvSDLnTAADK9nMYTPg046.jpg


 

我們現在就可以用mysql客戶端去登陸了,您也可以用您喜歡的圖形界面來查看。

$ bin/mysql -uroot -h127.0.0.1 -P3306
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| ndbinfo            |
| performance_schema |
| test               |
| tmp                |
+--------------------+
6 rows in set (0.00 sec)

mysql> create database lyw;
Query OK, 1 row affected (0.05 sec)

mysql> use lyw;
Database changed

mysql> create table t1 (id int primary key, a int, v varchar(32)) engine ndbcluster;
Query OK, 0 rows affected (0.77 sec)

mysql> insert into t1 values (1, 1, 'a'), (2, 2, 'b');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+----+------+------+
| id | a    | v    |
+----+------+------+
|  1 |    1 | a    |
|  2 |    2 | b    |
+----+------+------+
2 rows in set (0.00 sec)

我們發現默認的數據庫比平常多兩個,特別是 ndbinfo,當然是存儲 ndb相關的一些數據了。當我們創建表格時,我們要在後面指定存儲引擎 engine ndbcluster,否則創建出來的表格還是默認的innodb,只在單機上有數據。我們下面用多種工具校驗下數據確實存儲到了ndb引擎。
方法一:查看創建語句 show create table t1;  如果返回的內容裏面有ENGINE=ndbcluster,說明用的是ndb引擎。

方法二:鏈接上我們的另外一個MySQL節點。看是否有對應的數據

$ bin/mysql -uroot -h127.0.0.1 -P3307
mysql> select * from lyw.t1;
+----+------+------+
| id | a    | v    |
+----+------+------+
|  1 |    1 | a    |
|  2 |    2 | b    |
+----+------+------+
2 rows in set (0.00 sec)

數據能從另外的節點查到,說明數據已經在ndb上,如果您自己創建一個其他引擎的表,數據在其他庫是查不到的。

方法三:用ndb_desc命令,後面兩個參數是數據庫名和表名。管理者端口改了,或不是本機,需要增加參數 -c 192.168.1.8:1186

$ bin/ndb_desc -p -d lyw t1
或
$ bin/ndb_desc -p -d lyw t1 -c 192.168.1.8:1186

如果有一大屏幕的內容,說明這個表已經在ndb引擎裏了,並且顯示了關於該表的各種信息。


第三步:創建磁盤表

ndb默認創建的表格是內存表,意思是所有數據都加載在內存中,當內存不能夠放下所有數據時,將不能插入數據。數據再磁盤中也會存,但那些只是在宕機重啓後用於加載的,平常不會去讀。如果數據全部在內存,而我們的內存並非很大,需要存儲的數據卻很多,那怎麼辦呢,7.3版本開始ndb引擎支持磁盤表,創建時需要多兩個步驟,我們下面來創建一下。
首先我們要創建一個日誌文件組lg1:

mysql> create logfile group lg1 add undofile 'undo.lg1' initial_size 16M engine ndbcluster;

然後創建一個表空間ts1:

mysql> create tablespace ts1 add datafile 'data.ts1' use logfile group lg1 initial_size 64M engine ndbcluster;

這時我們就可以創建表格了:

mysql> create table t2 (id int primary key, a int, v varchar(32)) tablespace ts1 storage disk engine ndbcluster;

這裏比上面有多個幾個關鍵字 tablespace ts1 storage disk。
這裏的數據和日誌文件就相當於innodb引擎裏的數據文件和日誌文件,一般日誌文件不用太大,而數據文件需要足夠放表裏的數據。如果運行到一定時間發現不夠了,我們也可以添加的。

mysql> alter tablespace ts1 add datafile 'data2.ts1' initial_size 128M engine ndbcluster;

這樣ts1這個表空間裏面就有兩個數據文件了,總大小是64+128=192M了。
日誌組也同樣可以增加文件,這個一般在寫入吞吐率增加時才需要增加。

mysql> alter logfile group lg1 add undofile 'undo2.lg1' initial_size 16M engine ndbcluster;


表空間創建好後我們可以用ndb_show_tables命令查看是否真的建立成功了

$ bin/ndb_show_tables  |grep -E "lg1|ts1"
37    Tablespace           Online   -                             ts1
36    Undofile             Online   -                             undo.lg1
39    Datafile             Online   -                             data2.ts1
38    Datafile             Online   -                             data.ts1
40    Undofile             Online   -                             undo2.lg1
35    LogfileGroup         Online   -                             lg1

另外我們也可以到文件系統上去看,是否有了對應的文件。


第四步:自己手動部署集羣

前面我們部署的集羣是用了自動化工具的,有些配置不能輕易修改,只適合快速和初學使用,實際應用的時候我們還是應該要手動地去部署。同時也爲我們後面的集羣擴容做準備。我們參考自動部署產生的配置文件,在上面修改一下。
數字49目錄下的config.ini就是我們最關鍵的配置了。剛纔我們生成的配置文件如下

[NDB_MGMD DEFAULT]
Portnumber=1186

[NDB_MGMD]
NodeId=49
HostName=127.0.0.1
DataDir=/home/lyw/db/mysql-cluster/run/data/49/
Portnumber=1186

[TCP DEFAULT]
SendBufferMemory=4M
ReceiveBufferMemory=4M

[NDBD DEFAULT]
BackupMaxWriteSize=1M
BackupDataBufferSize=16M
BackupLogBufferSize=4M
BackupMemory=20M
BackupReportFrequency=10
MemReportFrequency=30
LogLevelStartup=15
LogLevelShutdown=15
LogLevelCheckpoint=8
LogLevelNodeRestart=15
DataMemory=135M
IndexMemory=22M
MaxNoOfTables=4096
MaxNoOfTriggers=3500
NoOfReplicas=2
StringMemory=25
DiskPageBufferMemory=64M
SharedGlobalMemory=20M
LongMessageBuffer=32M
MaxNoOfConcurrentTransactions=16384
BatchSizePerLocalScan=512
FragmentLogFileSize=256M
NoOfFragmentLogFiles=3
RedoBuffer=32M
MaxNoOfExecutionThreads=2
StopOnError=false
LockPagesInMainMemory=1
TimeBetweenEpochsTimeout=32000
TimeBetweenWatchdogCheckInitial=60000
TransactionInactiveTimeout=60000
HeartbeatIntervalDbDb=15000
HeartbeatIntervalDbApi=15000

[NDBD]
NodeId=1
HostName=127.0.0.1
DataDir=/home/lyw/db/mysql-cluster/run/data/1/

[NDBD]
NodeId=2
HostName=127.0.0.1
DataDir=/home/lyw/db/mysql-cluster/run/data/2/

[MYSQLD DEFAULT]

[MYSQLD]
NodeId=53
HostName=127.0.0.1

[MYSQLD]
NodeId=54
HostName=127.0.0.1

[API]
NodeId=50
HostName=127.0.0.1

[API]
NodeId=51
HostName=127.0.0.1

[API]
NodeId=52
HostName=127.0.0.1


[NDB_MGMD] 組沒有多少內容,可以根據自己的情況改改端口路徑等。
[NDBD DEFAULT] 組配置了各數據節點相同的參數,我們可以看到這個文件中配置的內存都是挺大的,我們可以自行調整,如果機器內存較小,可以把所有內存都配小一點,如果內存較大,(每個節點16G以內),只要將DataMemoryIndexMemory改大一點就好了。
我們可能需要將數據配置到其他路徑下,就修改下對應的路徑。
FragmentLogFileSize*NoOfFragmentLogFiles因大於DataMemory的值,否則會出現內存用不完而硬盤不夠放的情況。
增加幾個 [NDBD] 組的內容即可增加幾個數據節點,注意NDBD 的id範圍在1~48之間。
增加幾個 [MYSQLD] 組的內容即可增加幾個MySQL節點。這種id範圍在1~255之間。
由於數據節點範圍是1~48,資源很寶貴,因此儘量將這個區間保留給數據節點,其他節點使用49~255的範圍。
[API] 組一般不用動,如果編程時大量使用原生API編程,需要增加一些。bin目錄下的ndb_開頭的工具都是使用API組的連接,不過他們屬於短連接,使用完就釋放了。

我們再看一下53或54目錄下的my.cnf,這是mysql的配置文件

[mysqld]
log-error=mysqld.53.err
datadir="/home/lyw/db/mysql-cluster/run/data/53/"
tmpdir="/home/lyw/db/mysql-cluster/run/data/53/tmp"
basedir="/home/lyw/db/mysql-cluster/"
port=3306
ndbcluster=on
ndb-nodeid=53
ndb-connectstring=127.0.0.1:1186,
socket="/home/lyw/db/mysql-cluster/run/data/53/mysql.socket"

可以看到裏面多了3行ndb相關的參數,您可以自行在配置文件裏增加參數,比如innodb相關的,因爲innodb引擎已經不再使用,默認128M的內存,48M的日誌文件顯得過大,我們完全可以將他們調小。設置下server-id,方便後面說的主從複製。

innodb_buffer_pool_size = 16M
innodb_additional_mem_pool_size = 2M
innodb_log_file_size = 5M
innodb_log_buffer_size = 5M
server-id = 53

如果是單機下,我們準備一個初始化和啓動腳本initial.sh,最好加上執行權限:

basedir=/home/lyw/db/mysql-cluster/run/data
bindir=/home/lyw/db/mysql-cluster
$bindir/bin/ndb_mgmd --ndb-nodeid=49 --config-dir=$basedir/49 --config-file=$basedir/49/config.ini  --initial
sleep 3
# 更多的數據節點,就增加幾個數字
for id in 1  2
do
    mkdir $id
    $bindir/bin/ndbmtd --ndb-nodeid=$id --ndb-connectstring=127.0.0.1:1186  --initial
    sleep 10
done
sleep 10
cd $bindir
for id2 in 53  54
do
    mkdir -p $basedir/$id2/tmp
    $bindir/scripts/mysql_install_db --defaults-file=$basedir/$id2/my.cnf 
    $bindir/bin/mysqld_safe --defaults-file=$basedir/$id2/my.cnf &
done
sleep 3
ps aux|grep mysql

然後我們將前面配置的3種4個配置文件下面目錄組織起來。

.
├── 49
│   └── config.ini
├── 53
│   └── my.cnf
├── 54
│   └── my.cnf
└── initial.sh

執行我們寫好的腳本initial.sh,大約需要一分鐘,顯示一大堆的內容後,我們的集羣就部署並啓動好了。我們回過頭去看下啓動腳本,說明下啓動的步驟:

1. 啓動管理節點ndb_mgmd,注意,參數需要指定全路徑,有個--initial,這個參數自在第一次啓動時使用。

$bindir/bin/ndb_mgmd --ndb-nodeid=49 --config-dir=$basedir/49 --config-file=$basedir/49/config.ini  --initial

2. 啓動每個數據節點ndbmtd,這裏也一樣第一次啓動需要--initial參數進行初始化,目錄需要事先創建好。

mkdir $id
$bindir/bin/ndbmtd --ndb-nodeid=$id --ndb-connectstring=127.0.0.1:1186  --initial

3. 初始化每個數據庫 mysql_install_db

mkdir -p $basedir/$id2/tmp
$bindir/scripts/mysql_install_db --defaults-file=$basedir/$id2/my.cnf

4. 啓動每個數據庫mysqld

$bindir/bin/mysqld_safe --defaults-file=$basedir/$id2/my.cnf &

這樣所有節點就全部啓動好了。我們可以跟前面一樣測試下系統是否工作正常。


第五步:集羣在線擴容

我們前面部署的集羣只有兩個數據節點,能夠存儲的數據量有限,當我們數據越來越多時,就需要擴充集羣容量,MySQL Cluster最強大的功能之一就是在線擴容,擴容期間服務看不出停頓。我們就來看看在線擴容是如何操作的吧。
我們用前面準備的集羣,並且在集羣中寫入若干數據(寫入過程略)。我這裏寫了lyw.sbtest1表100000條數據,我們用ndb_desc命令查看數據的分佈情況

$ bin/ndb_desc -d lyw sbtest1 -pn
。。。。。。
FragmentCount: 2
。。。。。。
-- Per partition info -- 
Partition    Row count    Commit count    Frag fixed memory    Frag varsized memory    Extent_space    Free extent_space    Nodes    
0            49950        49950           10715136             0                        0                0                     1,2    
1            50050        50050           10747904             0                        0                0                     2,1

可以看到數據基本平均分佈在兩個分片裏。默認情況下,分片數是跟節點數相同的,這個可以配置,在分片章節再講。

我們用另外一個命令看一下集羣的健康狀況

$ bin/ndb_mgm
-- NDB Cluster -- Management Client --

ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)]    2 node(s)
id=1    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0, *)
id=2    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0)
[ndb_mgmd(MGM)]    1 node(s)
id=49    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8)
[mysqld(API)]    5 node(s)
id=50 (not connected, accepting connect from 127.0.0.1)
id=51 (not connected, accepting connect from 127.0.0.1)
id=52 (not connected, accepting connect from 127.0.0.1)
id=53    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8)
id=54    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8)

ndb_mgm> all report memory
Node 1: Data usage is 18%(781 32K pages of total 4320)
Node 1: Index usage is 6%(196 8K pages of total 2848)
Node 2: Data usage is 18%(781 32K pages of total 4320)
Node 2: Index usage is 6%(196 8K pages of total 2848)

show命令查看各節點的存活狀態如何。
all report memory 命令查看各數據節點的內存使用情況。

接下來我們打算將集羣從2個數據節點擴充到4個數據節點。首先我們在49/config.ini配置文件裏增加2個數據節點的配置:

[NDBD]
NodeId=3
HostName=127.0.0.1
DataDir=/home/lyw/db/mysql-cluster/run/data/3/

[NDBD]
NodeId=4
HostName=127.0.0.1
DataDir=/home/lyw/db/mysql-cluster/run/data/4/

我們用ndb_mgm客戶端工具停止ndb_mgmd節點

ndb_mgm> 49 stop

ndb_mgmd節點停止了並不會影響集羣的數據操作,因此您不用着急,慢慢來就好了。
再用命令行啓動,這裏的參數跟前面的不同,原先--initial 變成--reload,另外注意參數最好用全路徑

$ /home/lyw/db/mysql-cluster/bin/ndb_mgmd --ndb-nodeid=49 --config-dir=/home/lyw/db/mysql-cluster/run/data/49 --config-file=/home/lyw/db/mysql-cluster/run/data/49/config.ini --reload

檢查下是否啓動正常

ndb_mgm> show
Cluster Configuration
---------------------
[ndbd(NDB)]    4 node(s)
id=1    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0, *)
id=2    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0)
id=3 (not connected, accepting connect from 127.0.0.1)
id=4 (not connected, accepting connect from 127.0.0.1)
[ndb_mgmd(MGM)]    1 node(s)
id=49    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8)
[mysqld(API)]    5 node(s)
id=50 (not connected, accepting connect from 127.0.0.1)
id=51 (not connected, accepting connect from 127.0.0.1)
id=52 (not connected, accepting connect from 127.0.0.1)
id=53    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8)
id=54    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8)

我們發現 ndb_mgmd節點已啓動, 新增的2個數據節點3, 4並沒有連接。我們還不着急啓動他們倆,我們先將現在活着的節點逐個重啓一下,讓他們都知道很快就會有新同事來了。節點的重啓需要花費數十秒,請耐心等待“Node 1: Started  (version 7.4.8)”字樣的出現。(這些字符不是命令的輸入),然後再操作下一條語句。

ndb_mgm> 1 restart
Node 1: Node shutdown initiated
Node 1: Node shutdown completed, restarting, no start.
Node 1 is being restarted
ndb_mgm> Node 1: Start initiated (version 7.4.8)
Node 1: Started (version 7.4.8)

ndb_mgm> 2 restart
Node 2: Node shutdown initiated
Node 2: Node shutdown completed, restarting, no start.
Node 2 is being restarted
ndb_mgm> Node 2: Start initiated (version 7.4.8)
Node 2: Started (version 7.4.8)

2個mysql節點也要逐個重啓下

$ bin/mysqladmin -uroot -h127.0.0.1 -P3306 shutdown
$ bin/mysqld_safe --defaults-file=/home/lyw/db/mysql-cluster/run/data/53/my.cnf &

$ bin/mysqladmin -uroot -h127.0.0.1 -P3307 shutdown
$ bin/mysqld_safe --defaults-file=/home/lyw/db/mysql-cluster/run/data/54/my.cnf &

我們用ndb_mgm> show命令檢查一下,是否都啓動成功(顯示內容略)
至此原先環境的所有進程都已經重啓好了,我們啓動新加入的兩個節點,注意最後的--initial參數

$ mkdir 3 4
$ /home/lyw/db/mysql-cluster/bin/ndbmtd --ndb-nodeid=3 --ndb-connectstring=127.0.0.1:1186  --initial    
$ /home/lyw/db/mysql-cluster/bin/ndbmtd --ndb-nodeid=4 --ndb-connectstring=127.0.0.1:1186  --initial

數十秒後,用show命令檢查,顯示如下:

ndb_mgm> show
[ndbd(NDB)]    4 node(s)
id=1    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0, *)
id=2    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0)
id=3    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, no nodegroup)
id=4    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, no nodegroup)
。。。。。。

節點都已啓動成功,不過3,4兩個節點後面顯示爲 “no nodegroup”,而1,2兩個節點顯示爲“Nodegroup: 0”。根據MySQL Cluster的結構,一個集羣可由多個nodegroup組成,一個nodegroup可由多個datanode組成,數據分片fragement在相同nodegroup的多個datanode間相互同步。至於還沒有加入任何組的數據節點是不會提供服務的。我們需要爲這兩個節點建立一個組。

ndb_mgm> create nodegroup 3,4
Nodegroup 1 created
ndb_mgm> show
[ndbd(NDB)]    4 node(s)
id=1    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0, *)
id=2    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 0)
id=3    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 1)
id=4    @127.0.0.1  (mysql-5.6.27 ndb-7.4.8, Nodegroup: 1)

這樣我們就有兩個nodegroup了。再來看下我們之前插入的100000條數據的分佈情況,

$ bin/ndb_desc -d lyw sbtest1 -pn
。。。。。。
FragmentCount: 2
。。。。。。
-- Per partition info -- 
Partition    Row count    Commit count    Frag fixed memory    Frag varsized memory    Extent_space    Free extent_space    Nodes    
0            49950        49950           10715136             0                        0                0                     1,2    
1            50050        50050           10747904             0                        0                0                     2,1

我們發現還是跟以前一樣是兩個分片,且都在1,2兩個數據節點上。就算是等上一天也不會改變,似乎我們的新節點還沒有生效。我們加一個新表lyw2.sbtest1 試試,也寫入100000條。

$ bin/ndb_desc -d lyw2 sbtest1 -pn
。。。。。。
FragmentCount: 4
。。。。。。
-- Per partition info -- 
Partition    Row count    Commit count    Frag fixed memory    Frag varsized memory    Extent_space    Free extent_space    Nodes    
0            24943        24943           5373952              0                        0                0                     1,2    
2            25007        25007           5373952              0                        0                0                     2,1    
3            24961        24961           5373952              0                        0                0                     4,3    
1            25089        25089           5373952              0                        0                0                     3,4

我們發現新表的數據是可以自動分佈到新的節點上去了。
如果我們想讓原先表 lyw.sbtest1的數據也均勻分佈到新節點上,還需要在mysql客戶端做下面的操作。

mysql> alter online table lyw.sbtest1 reorganize partition;

這時再用ndb_desc查看分佈,數據已經分佈到新節點上去了

$ bin/ndb_desc -d lyw sbtest1 -pn
。。。。。。
FragmentCount: 4
。。。。。。
-- Per partition info -- 
Partition    Row count    Commit count    Frag fixed memory    Frag varsized memory    Extent_space    Free extent_space    Nodes    
0            24943        99964           10715136             0                        0                0                     1,2    
1            25089        99972           10747904             0                        0                0                     2,1    
2            25007        25007           5373952              0                        0                0                     3,4    
3            24961        24961           5373952              0                        0                0                     4,3

 不過還是會發現0,1 兩個分片的內存使用量(Frag fixed memory列)並沒有下降,目前版本這個內存只會在刪除表的情況下才會釋放,個人覺得這是個較大缺陷,估計後面的版本會改進吧。


第六步:表的分片設定

1.    分片數量控制

前面創建的表格的分片數都是系統根據節點數自動設置的,一般跟節點數相同,實際上這個分片數也是可以指定的,用partitions參數:

mysql> create table t3( id int primary key, a int, v varchar(32)) engine ndbcluster partition by key(id) partitions 1;
mysql> create table t8( id int primary key, a int, v varchar(32)) engine ndbcluster partition by key(id) partitions 8;

如果某些表估計數據量不大,就可以考慮將分片數設置爲1,這種情況下就相當於是單庫操作。如果某些表數據量巨大,就可以增大分片數,最大分片數是8*nodegroup數。

2.    多主鍵下的分片控制

當我們創建的表格需要兩個主鍵的時候會是怎樣的呢?我們也來創建一個:

mysql> create table d1(id1 int, id2 int, a int, v varchar(32), primary key (id1, id2)) engine ndbcluster;
mysql> insert into d1 values(1,1,1,'a'), (1,2,3,'a'), (1,3,4, 'b'), (1,4,5,'d');

這裏我們插入的數據id1都相同,id2是不同的,然後我們查看數據的分佈:

$ bin/ndb_desc -d lyw d1 -pn
。。。。。。
-- Attributes --
id1 Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
id2 Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
。。。。。。
-- Per partition info -- 
Partition    Row count    Commit count    Frag fixed memory    Frag varsized memory    Extent_space    Free extent_space    Nodes    
0            1            1               32768                32768                   0                0                     1,2    
2            1            1               32768                32768                   0                0                     2,1    
1            1            1               32768                32768                   0                0                     3,4    
3            1            1               32768                32768                   0                0                     4,3

4個分片裏面全有數據,實際上這裏的分片規則是根據兩個key一起決定的,我們再看錶屬性裏面id1 和id2 都有 “DISTRIBUTION KEY” 字樣,也是說明了這一點。
如果是這樣分片很有可能不是我們想要的分片方式,我們經常會希望讓id1相同的數據都在一起,在一個分片上就能查找到,這樣能夠減少數據庫的查詢開銷。要想達到這個目的,我們建表時需要多寫一點內容。

mysql> create table d2(id1 int, id2 int, a int, v varchar(32), primary key (id1, id2)) engine ndbcluster partition by key(id1);
mysql> insert into d2 values(1,1,1,'a'), (1,2,3,'a'), (1,3,4, 'b'), (1,4,5,'d');

建表語句後面增加了partition by key(id1)。我們插入同樣的4行,再來看錶屬性

$ bin/ndb_desc -d lyw d2 -pn
。。。。。。
-- Attributes --
id1 Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
id2 Int PRIMARY KEY AT=FIXED ST=MEMORY
。。。。。。
-- Per partition info -- 
Partition    Row count    Commit count    Frag fixed memory    Frag varsized memory    Extent_space    Free extent_space    Nodes    
3            4            4               32768                32768                   0                0                     4,3

所有數據都在3號分片上,這絕非是巧合,您可以自己多插入些數據試試。另外我們看到id2屬性比id1 少了“ DISTRIBUTION KEY”這部分內容,也說明了該表只按照id1進行分片。

我們也可以指定只按照id2進行分片,但是不可以按照非主鍵的列進行分片:

mysql> create table d3(id1 int, id2 int, a int, v varchar(32), primary key (id1, id2)) engine ndbcluster partition by key(id2);
Query OK, 0 rows affected (1.04 sec)

mysql> create table d4(id1 int, id2 int, a int, v varchar(32), primary key (id1, id2)) engine ndbcluster partition by key(a);
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function


第七步:NDB引擎的事務

InnoDB引擎支持所有4個級別的事務,而NDB引擎卻只支持READ COMMITTED級別事務,比InnoDB引擎的默認級別低了一級,也就是說,本來在InnoDB引擎下運行良好的程序,遷移到NDB引擎有可能會產生一些錯誤。遷移前需要做好足夠的檢查和測試。下面我們用一個例子說明下NDB引擎的事務情況。我們用

mysql-A>和mysql-B>>區分兩個客戶端
mysql-A> create table t1 (id int primary key, a int, v varchar(32)) engine ndbcluster;
mysql-A> insert into t1 values (1, 1, 'a'), (2, 2, 'b');
mysql-A> begin;
Query OK, 0 rows affected (0.02 sec)

mysql-B>> begin;
Query OK, 0 rows affected (0.00 sec)

mysql-A> update t1 set a = 100 where id = 1;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0 

mysql-B>> select * from t1 where id = 1;
+----+------+------+
| id | a    | v    |
+----+------+------+
|  1 |    1 | a    |
+----+------+------+
1 row in set (0.00 sec)

mysql-A> commit;
Query OK, 0 rows affected (0.00 sec)

mysql-B>> select * from t1 where id = 1;
+----+------+------+
| id | a    | v    |
+----+------+------+
|  1 |  100 | a    |
+----+------+------+
1 row in set (0.00 sec)

可以看到在事務A裏面commit前事務B並不能查到更改,但是commit後,B就能查到了更改。而在InnoDB引擎裏面,B是永遠都查不到外界的任何修改的。如果原先的代碼中依賴可重複讀,那麼遷移時需要修改下。


第八步:分佈式權限管理

NDB使用的權限系統就是MySQL這一套,只是到目前爲止的權限還是配置在MySQL節點上,並且各個MySQL節點的權限數據可以不同,如果修改了其中一個節點的權限,其他節點的權限並沒有修改。爲了使所有的MySQL節點的權限是分佈式一致的,我們需要做一定的調整。
NDB提供了一個sql腳本share/ndb_dist_priv.sql幫助我們做這件事情,這個腳本會創建幾個函數供我們使用,我們在任意一個MySQL節點執行下面這個兩行代碼即可。

$ bin/mysql -uroot -h127.0.0.1 -P3306
mysql> source share/ndb_dist_priv.sql;
mysql> call mysql.mysql_cluster_move_privileges();

我們來測試下權限情況:
先來刪掉兩個無密碼的用戶。在任意一個MySQL節點執行刪除語句。

mysql> delete from mysql.user where user='';

在每個MySQL節點執行下面這條語句刷新權限。

mysql> flush privileges;

在任意一個MySQL節點添加一個用戶。

mysql> grant all on *.* to 'lyw'@'%' identified by '123456';

執行後我們嘗試用新用戶登錄

$ bin/mysql -ulyw -h127.0.0.1 -P3306 -p123456
mysql>
$ bin/mysql -ulyw -h127.0.0.1 -P3307 -p123456
mysql>

我們發現兩個MySQL節點都已經有了lyw這個新用戶,並且已經生效。以後如果使用grant方法進行權限的更改,都能夠同步到每一個MySQL節點上。而直接操作user表修改權限,需要flush privileges時,需要在每個MySQL節點上執行flush privileges命令才能全部生效。


第九步:管理節點高可用

前面集羣配置裏面的管理節點ndb_mgmd進程是單個的,只是單臺的話可用性較低。雖然說該節點宕機並不影響讀寫等操作,但還是會影響到集羣的節點配置變更,因此最好還是配置爲高可用。ndb_mgmd自身是支持高可用的,在前面的配置基礎上稍作調整即可。
1.    config.ini配置增加一個 [NDB_MGMD] 分組

[NDB_MGMD]
NodeId=149
HostName=127.0.0.1
DataDir=/home/lyw/db/mysql-cluster/run/data2/149/
Portnumber=1187

2.    並且將這份配置文件複製出一份,49和149兩個配置文件內容必須完全相同:

cp –r 49 149

3.    所有節點的 --ndb-connectstring 參數配置多個端口或IP,逗號分隔:

在 ndb_mtd 啓動參數中修改爲 
--ndb-connectstring=127.0.0.1:1186,127.0.0.1:1187,

在 my.cnf 配置文件中修改爲 
ndb-connectstring=127.0.0.1:1186,127.0.0.1:1187,

4.    啓動時先將所有ndb_mgmd進程啓動,因此前面的啓動腳本 initial.sh 要多加一行:

$bindir/bin/ndb_mgmd --ndb-nodeid=149 --config-dir=$basedir/149 --config-file=$basedir/149/config.ini  --initial

5.    然後就可以執行啓動腳本啓動了。

./initial.sh

這樣配置後,掛掉任意一臺 ndb_mgmd 是不會影響任何服務的,線上機器最好這樣配置。ndb_mgmd 壓力非常小,無需獨立兩臺機器,跟其他數據節點 ndb_mtd 等混合部署即可。

第十步:其他集羣管理

1. 關閉集羣
ndb相關節點關閉用ndb_mgm客戶端

ndb_mgm> shutdown
或
bin/ndb_mgm -e shutdown

mysql 節點用mysql的關閉方法

bin/mysqladmin -uroot -h127.0.0.1 -P3306 shutdown
或
sudo service mysql stop

2. 啓動集羣
前面集羣的第一次啓動,命令行參數後面都有個--initial,從第二次啓動開始,就不需要這個參數了。單機時可以稍微修改下前面的初始化腳本爲啓動腳本。

$ /home/lyw/db/mysql-cluster/bin/ndb_mgmd --ndb-nodeid=49 --config-dir=/home/lyw/db/mysql-cluster/run/data/49 --config-file=/home/lyw/db/mysql-cluster/run/data/49/config.ini
$ /home/lyw/db/mysql-cluster/bin/ndbmtd --ndb-nodeid=1 --ndb-connectstring=127.0.0.1:1186
。。。。。。

3. 主從複製(熱備份)
跟普通的MySQL主從複製一樣,只是這裏可以在集羣A任意選擇一臺MySQL節點作爲主,在集羣B任意選擇一臺MySQL節點作爲從,讓他們之間建立主從即可,傳統方式和GTID方式均可。這樣集羣A的任何修改都會同步到集羣B,當然是異步的。可以作爲異地災備方案。
同樣的,可以利用主從配置方法配置出更多結構:一主多從,雙主,三主等。

4. NDB冷備份
NDB提供類似mysqldump的在線冷備份功能

ndb_mgm> start backup

執行後,會在數據節點目錄下多一個BACKUP目錄,備份內容就在該目錄下,並自動命名爲BACKUP-1。以後執行數字依次遞增。數字也可以手動指定,如

ndb_mgm> start backup 20151111
$ ls 1/BACKUP/
BACKUP-1   BACKUP-20151111

內容就備份到BACKUP-20151111目錄下了。

以上就是MySQL Cluster的基本功能了,更多的細節功能需要在使用中去逐步發現和體會。

在多種集羣之間選擇猶豫時,可以參考下《MySQL Cluster, Fabric, Cobar 三大集羣特性對比》這篇文章,一定會對你有所幫助的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章