MySQL之九—分散式架構(Mycat/DBLE)

MyCAT基礎架構圖

 

雙主雙從結構

MyCAT基礎架構準備

準備環境

 環境準備:
 兩台虛擬機 db01 db02
 每台創建四個mysql實例:3307 3308 3309 3310

刪除歷史環境

 pkill mysqld
 rm -rf /data/330* 
 \mv /etc/my.cnf /etc/my.cnf.bak

初始化數據

 mkdir /data/33{07..10}/data -p
 mysqld --initialize-insecure  --user=mysql --datadir=/data/3307/data --basedir=/usr/local/mysql
 mysqld --initialize-insecure  --user=mysql --datadir=/data/3308/data --basedir=/usr/local/mysql
 mysqld --initialize-insecure  --user=mysql --datadir=/data/3309/data --basedir=/usr/local/mysql
 mysqld --initialize-insecure  --user=mysql --datadir=/data/3310/data --basedir=/usr/local/mysql

配置文件

========db01==============

 cat >/data/3307/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3307/data
 socket=/data/3307/mysql.sock
 port=3307
 log-error=/data/3307/mysql.log
 log_bin=/data/3307/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=7
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 cat >/data/3308/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3308/data
 port=3308
 socket=/data/3308/mysql.sock
 log-error=/data/3308/mysql.log
 log_bin=/data/3308/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=8
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 ​
 cat >/data/3309/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3309/data
 socket=/data/3309/mysql.sock
 port=3309
 log-error=/data/3309/mysql.log
 log_bin=/data/3309/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=9
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 ​
 cat >/data/3310/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3310/data
 socket=/data/3310/mysql.sock
 port=3310
 log-error=/data/3310/mysql.log
 log_bin=/data/3310/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=10
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 ​
 cat >/etc/systemd/system/mysqld3307.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
 LimitNOFILE = 5000
 EOF
 ​
 ​
 cat >/etc/systemd/system/mysqld3308.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
 LimitNOFILE = 5000
 EOF
 ​
 cat >/etc/systemd/system/mysqld3309.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
 LimitNOFILE = 5000
 EOF
 ​
 ​
 cat >/etc/systemd/system/mysqld3310.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 ​
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf 
LimitNOFILE = 5000 
EOF

========db02===============

 cat >/data/3307/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3307/data
 socket=/data/3307/mysql.sock
 port=3307
 log-error=/data/3307/mysql.log
 log_bin=/data/3307/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=17
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 ​
 cat >/data/3308/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3308/data
 port=3308
 socket=/data/3308/mysql.sock
 log-error=/data/3308/mysql.log
 log_bin=/data/3308/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=18
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 ​
 cat >/data/3309/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3309/data
 socket=/data/3309/mysql.sock
 port=3309
 log-error=/data/3309/mysql.log
 log_bin=/data/3309/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=19
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 ​
 cat >/data/3310/my.cnf<<EOF
 [mysqld]
 basedir=/usr/local/mysql
 datadir=/data/3310/data
 socket=/data/3310/mysql.sock
 port=3310
 log-error=/data/3310/mysql.log
 log_bin=/data/3310/mysql-bin
 binlog_format=row
 skip-name-resolve
 server-id=20
 gtid-mode=on
 enforce-gtid-consistency=true
 log-slave-updates=1
 EOF
 ​
 cat >/etc/systemd/system/mysqld3307.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
 LimitNOFILE = 5000
 EOF
 ​
 cat >/etc/systemd/system/mysqld3308.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
 LimitNOFILE = 5000
 EOF
 ​
 cat >/etc/systemd/system/mysqld3309.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
 LimitNOFILE = 5000
 EOF
 ​
 ​
 cat >/etc/systemd/system/mysqld3310.service<<EOF
 [Unit]
 Description=MySQL Server
 Documentation=man:mysqld(8)
 Documentation=//dev.mysql.com/doc/refman/en/using-systemd.html
 After=network.target
 After=syslog.target
 [Install]
 WantedBy=multi-user.target
 [Service]
 User=mysql
 Group=mysql
 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf
 LimitNOFILE = 5000 
EOF

 

 

啟動多實例

 chown -R mysql.mysql /data/*
 systemctl start mysqld3307
 systemctl start mysqld3308
 systemctl start mysqld3309
 systemctl start mysqld3310
 ​
 mysql -S /data/3307/mysql.sock -e "show variables like 'server_id'"
 mysql -S /data/3308/mysql.sock -e "show variables like 'server_id'"
 mysql -S /data/3309/mysql.sock -e "show variables like 'server_id'"
 mysql -S /data/3310/mysql.sock -e "show variables like 'server_id'"

配置主從環境

 shard1
 10.0.0.51:3307 <-----> 10.0.0.52:3307
 # db02
 mysql  -S /data/3307/mysql.sock -e "create user repl@'10.0.0.%' identified with mysql_native_password by '123'; grant replication slave on *.* to repl@'10.0.0.%'; "
 mysql  -S /data/3307/mysql.sock -e "create user root@'10.0.0.%' identified with mysql_native_password by '123'; grant all  on *.* to root@'10.0.0.%'; "
 # db01
 mysql  -S /data/3307/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3307/mysql.sock -e "start slave;"
 mysql  -S /data/3307/mysql.sock -e "show slave status \G"|grep Running
 # db02
 mysql  -S /data/3307/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3307/mysql.sock -e "start slave;"
 mysql  -S /data/3307/mysql.sock -e "show slave status\G" |grep Running
 10.0.0.51:3309 ------> 10.0.0.51:3307
  db01
 mysql  -S /data/3309/mysql.sock  -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3309/mysql.sock  -e "start slave;"
 mysql  -S /data/3309/mysql.sock  -e "show slave status\G"|grep Running
 10.0.0.52:3309 ------> 10.0.0.52:3307
 # db02
 mysql  -S /data/3309/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3309/mysql.sock -e "start slave;"
 mysql  -S /data/3309/mysql.sock -e "show slave status\G"|grep Running
 ====================================================================
 ​
 ​
 # shard2
 ## 10.0.0.52:3308 <-----> 10.0.0.51:3308
 # db01
 mysql  -S /data/3308/mysql.sock -e "create user repl@'10.0.0.%' identified with mysql_native_password by '123'; grant replication slave on *.* to repl@'10.0.0.%';"
 mysql  -S /data/3308/mysql.sock -e "create user root@'10.0.0.%' identified with mysql_native_password by '123'; grant all  on *.* to root@'10.0.0.%'; "
 ​
 # db02
 mysql  -S /data/3308/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3308/mysql.sock -e "start slave;"
 mysql  -S /data/3308/mysql.sock -e "show slave status\G" |grep Running
 # db01
 mysql  -S /data/3308/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3308/mysql.sock -e "start slave;"
 mysql  -S /data/3308/mysql.sock -e "show slave status\G"|grep Running
 ## 10.0.0.52:3310 -----> 10.0.0.52:3308
 # db02
 mysql  -S /data/3310/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3310/mysql.sock -e "start slave;"
 mysql  -S /data/3310/mysql.sock -e "show slave status\G" |grep Running
 ##10.0.0.51:3310 -----> 10.0.0.51:3308
 # db01
 mysql  -S /data/3310/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
 mysql  -S /data/3310/mysql.sock -e "start slave;"
 mysql  -S /data/3310/mysql.sock -e "show slave status\G"|grep Running

檢測主從狀態

 mysql -S /data/3307/mysql.sock -e "show slave status\G"|grep Yes
 mysql -S /data/3308/mysql.sock -e "show slave status\G"|grep Yes
 mysql -S /data/3309/mysql.sock -e "show slave status\G"|grep Yes
 mysql -S /data/3310/mysql.sock -e "show slave status\G"|grep Yes

註:如果中間出現錯誤,在每個節點進行執行以下命令,從配置主從環境開始執行 mysql -S /data/3307/mysql.sock -e “stop slave; reset slave all;” mysql -S /data/3308/mysql.sock -e “stop slave; reset slave all;” mysql -S /data/3309/mysql.sock -e “stop slave; reset slave all;” mysql -S /data/3310/mysql.sock -e “stop slave; reset slave all;”

節點主從規劃

 箭頭指向誰是主庫
     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
 ​
     10.0.0.52:3308  <----->    10.0.0.51:3308
     10.0.0.52:3310  ----->     10.0.0.52:3308
     10.0.0.51:3310  ----->     10.0.0.51:3308

MySQL分散式架構介紹

 

 1. schema拆分及業務分庫
2. 垂直拆分-分庫分表
3. 水平拆分-分片

企業代表產品

 360 Atlas-Sharding
 Alibaba cobar
 Mycat
 TDDL
 Heisenberg
 Oceanus
 Vitess
 OneProxy
 DRDS

MyCAT安裝

開源組織和社區開發人員,在淘寶cobar(TDDL)基礎上二次開發,Mycat後來被愛可生改寫成了DBLE

安裝Java運行環境

 yum install -y java

下載

//dl.mycat.org.cn/1.6.7.4/

//dl.mycat.org.cn/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz

解壓文件

 [root@db02 opt]#rz 
 [root@db02 opt]# tar xf Mycat-server-1.6.7.4-release-20200105164103-linux_.tar.gz 

軟體目錄結構

 ls
 bin  catlet  conf  lib  logs  version.txt

啟動和連接

 配置環境變數
 [root@db02 opt]#vim /etc/profile
 export PATH=/opt/mycat/bin:$PATH
 [root@db02 opt]#source /etc/profile

 啟動
 [root@db02 opt]#mycat start

 連接mycat:    
 [root@db02 opt]#mysql -uroot -p123456 -h10.0.0.52 -P8066 --default-auth=mysql_native_password
8.0之前[root@db02 opt]#mysql -uroot -p123456 -h10.0.0.52 -P8066

配置文件介紹

 bin 目錄
 程式目錄
 conf
 配置文件目錄
 schema.xml
 主配置文件:節點資訊、讀寫分離、高可用設置、調用分片策略..
 rule.xml
 分片策略的定義、功能、使用用方法
 server.xml
 mycat服務有關配置: 用戶、網路、許可權、策略、資源...
 xx.txt文件
 分片參數定義文件
 log4j2.xml
 Mycat 相關日誌記錄配置
 logs
 wrapper.log: 啟動日誌  
 mycat.log : 工作日誌

應用環境準備

用戶創建及資料庫導入

 schema.xml配置文件結構
 [root@db02 conf]# cd /opt/mycat/conf/
 [root@db02 conf]#mv schema.xml schema.xml.bak
 [root@db02 conf]#vim schema.xml
 <?xml version="1.0"?>  
 <!DOCTYPE mycat:schema SYSTEM "schema.dtd">  
 <mycat:schema xmlns:mycat="//io.mycat/">
 <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> 
 </schema>  
     <dataNode name="dn1" dataHost="localhost1" database= "world" />  
     <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1"> 
     <heartbeat>select user()</heartbeat>  
     <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123"> 
     <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" /> 
     </writeHost> 
     </dataHost>  
 </mycat:schema>
     

 ########################測試環境準備
 [root@db02 conf]# mysql -S /data/3307/mysql.sock -e  "source /root/world.sql"
 [root@db02 conf]# mysql -S /data/3308/mysql.sock -e  "source /root/world.sql"    
 [root@db02 conf]# mycat restart  重啟mycat
     
 ######################## 讀寫分離測試    
  # 測試讀
 mysql -uroot -p123456 -h 10.0.0.52 -P8066 --default-auth=mysql_native_password  -e "select @@server_id;"     
  mysql: [Warning] Using a password on the command line interface can be insecure.
 +-------------+
 | @@server_id |
 +-------------+
 |           9 |
 +-------------+   
  # 測試寫
 mysql -uroot -p123456 -h 10.0.0.52 -P8066 --default-auth=mysql_native_password  -e "begin ; select @@server_id;commit;"
 mysql: [Warning] Using a password on the command line interface can be insecure.
 +-------------+
 | @@server_id |
 +-------------+
 |           7 |
 +-------------+

         
 ############################總結:
 以上案例實現了1主1從的讀寫分離功能,寫操作落到主庫,讀操作落到從庫.如果主庫宕機,從庫不能在繼續提供服務了。

配置文件詳細介紹

邏輯庫:schema

 <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> 
 </schema>  

數據節點:datanode

 <dataNode name="dn1" dataHost="localhost1" database= "world" />  

數據主機:datahost(w和r)

 <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  
dbDriver="native" switchType="1"> <heartbeat>select user()</heartbeat> <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123"> <readHost host="db2" url="10.0.0.52:3309" user="root" password="123" /> </writeHost> </dataHost>

 

 

配置讀寫分離及高可用

 [root@db02 conf]# mv schema.x
 [root@db02 conf]# mv schema.xml schema.xml.rw
 [root@db02 conf]# vim schema.xml
 <?xml version="1.0"?>  
 <!DOCTYPE mycat:schema SYSTEM "schema.dtd">  
 <mycat:schema xmlns:mycat="//io.mycat/">
 <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1"> 
 </schema>  
     <dataNode name="sh1" dataHost="oldguo1" database= "world" />  
     <dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1"> 
         <heartbeat>select user()</heartbeat>  
     <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123"> 
             <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" /> 
     </writeHost> 
     <writeHost host="db3" url="10.0.0.52:3307" user="root" password="123"> 
             <readHost host="db4" url="10.0.0.52:3309" user="root" password="123" /> 
     </writeHost>        
     </dataHost>  
 </mycat:schema>
ml schema.xml.rw
 [root@db02 conf]# vim schema.xml
 <?xml version="1.0"?>  
 <!DOCTYPE mycat:schema SYSTEM "schema.dtd">  
 <mycat:schema xmlns:mycat="//io.mycat/">
 <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1"> 
 </schema>  
     <dataNode name="sh1" dataHost="oldguo1" database= "world" />  
     <dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1"> 
         <heartbeat>select user()</heartbeat>  
     <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123"> 
             <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" /> 
     </writeHost> 
     <writeHost host="db3" url="10.0.0.52:3307" user="root" password="123"> 
             <readHost host="db4" url="10.0.0.52:3309" user="root" password="123" /> 
     </writeHost>        
     </dataHost>  
 </mycat:schema>

真正的` writehost:負責寫操作的writehost standby writeHost:和readhost一樣,只提供讀服務 當寫節點宕機後,後面跟的readhost也不提供服務,這時候standby的writehost就提供寫服務, 後面跟的readhost提供讀服務 測試: mysql -uroot -p123456 -h 127.0.0.1 -P 8066 show variables like ‘server_id’; 讀寫分離測試 mysql -uroot -p -h 127.0.0.1 -P8066 show variables like ‘server_id’; show variables like ‘server_id’; show variables like ‘server_id’; begin; show variables like ‘server_id’; 對db01 3307節點進行關閉和啟動,測試讀寫操作

重啟

[root@db02 conf]#mycat restart

測試讀(三讀)

 [root@db02 conf]# mysql -uroot -p123456 -h 10.0.0.52 -P8066 --default-auth=mysql_native_password  -e "select @@server_id;"
 +-------------+
 | @@server_id |
 +-------------+
 |          19 |
 +-------------+
 +-------------+
 | @@server_id |
 +-------------+
 |          17 |
 +-------------+
 +-------------+
 | @@server_id |
 +-------------+
 |           9 |
 +-------------+

測試寫(一寫)

 [root@db02 conf]# mysql -uroot -p123456 -h 10.0.0.52 -P8066 --default-auth=mysql_native_password  -e "begin ; select @@server_id;commit;"
 +-------------+
 | @@server_id |
 +-------------+
 |           7 |
 +-------------+    

測試高可用

[root@db01 ~]# systemctl stop mysqld3307
 [root@db02 conf]# mysql -uroot -p123456 -h10.0.0.52 -P8066 --default-auth=mysql_native_password -e "select @@server_id;"
 +-------------+
 | @@server_id |
 +-------------+
 |          19 |
 +-------------+
 ​
 [root@db02 conf]# mysql -uroot -p123456 -h10.0.0.52 -P8066 --default-auth=mysql_native_password -e "begin ; select @@server_id;commit;"
 +-------------+
 | @@server_id |
 +-------------+
 |          17 |
 +-------------+    
 [root@db01 ~]# systemctl start  mysqld3307  
 [root@db02 conf]# mysql -uroot -p123456 -h10.0.0.52 -P8066 --default-auth=mysql_native_password -e "select @@server_id;"
   +-------------+
 | @@server_id |
 +-------------+
 |          19 |
 +-------------+
 +-------------+
 | @@server_id |
 +-------------+
 |           7 |
 +-------------+
 +-------------+
 | @@server_id |
 +-------------+
 |           9 |
 +-------------+
 ​
 [root@db02 conf]# mysql -uroot -p123456 -h10.0.0.52 -P8066 --default-auth=mysql_native_password -e "begin ; select @@server_id;commit;"
  +-------------+
 | @@server_id |
 +-------------+
 |          17 |
 +-------------+

配置中的屬性介紹:

balance屬性

 負載均衡類型,目前的取值有3種: 
 1. balance="0", 不開啟讀寫分離機制,所有讀操作都發送到當前可用的writeHost上。
 2. balance="1",默認參數 三讀一寫 全部的readHost與standby writeHost參與select語句的負載均衡,簡單的說,
  當雙主雙從模式(M1->S1,M2->S2,並且M1與 M2互為主備),正常情況下,M2,S1,S2都參與select語句的負載均衡。
 3. balance="2",所有讀操作都隨機的在writeHost、readhost上分發。

writeType屬性

 負載均衡類型,目前的取值有2種: 
 1.writeType="0", 所有寫操作發送到配置的第一個writeHost,
 第一個掛了切到還生存的第二個writeHost,重新啟動後已切換後的為主,切換記錄在配置文件中:dnindex.properties .
 2.writeType=「1」,所有寫操作都隨機的發送到配置的writeHost,但不推薦使用

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>  監測心跳

Mycat 分散式架構—-垂直分表

 taobao庫:   user (sh1),order_t(sh2)   ,others(sh3) 
 [root@db02 conf]# mv  schema.xml  schema.xml.ha 
 [root@db02 conf]# vim schema.xml
 <?xml version="1.0"?>
 <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
 <mycat:schema xmlns:mycat="//io.mycat/">
 <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
         <table name="user" dataNode="sh1"/>
         <table name="order_t" dataNode="sh2"/>
 </schema>
     <dataNode name="sh1" dataHost="oldguo1" database= "taobao" />
     <dataNode name="sh2" dataHost="oldguo2" database= "taobao" />
     <dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
         <heartbeat>select user()</heartbeat>
     <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123">
             <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" />
     </writeHost>
     <writeHost host="db3" url="10.0.0.52:3307" user="root" password="123">
             <readHost host="db4" url="10.0.0.52:3309" user="root" password="123" />
     </writeHost>
     </dataHost>
     
     <dataHost name="oldguo2" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
         <heartbeat>select user()</heartbeat>
     <writeHost host="db1" url="10.0.0.51:3308" user="root" password="123">
             <readHost host="db2" url="10.0.0.51:3310" user="root" password="123" />
     </writeHost>
     <writeHost host="db3" url="10.0.0.52:3308" user="root" password="123">
             <readHost host="db4" url="10.0.0.52:3310" user="root" password="123" />
     </writeHost>
     </dataHost> 
 </mycat:schema>

創建測試庫和表

 [root@db02 conf]# mysql -S /data/3307/mysql.sock -e "create database taobao charset utf8;"
 [root@db02 conf]# mysql -S /data/3308/mysql.sock -e "create database taobao charset utf8;"
 [root@db02 conf]# mysql -S /data/3307/mysql.sock -e "use taobao;create table user(id int,name varchar(20))";
 [root@db02 conf]# mysql -S /data/3308/mysql.sock -e "use taobao;create table order_t(id int,name varchar(20))";

重啟mycat

 [root@db02 conf]# mycat restart 

mycat數據插入

 [root@db02 conf]# mysql -uroot -p123456 -h 10.0.0.52  -P 8066 --default-auth=mysql_native_password 
 insert into user values(1,'a');
 insert into user values(2,'b');
 insert into user values(3,'c');
 commit;
 insert into order_t values(1,'x'),(2,'y');
 commit;
 show databases;
 use TESTDB;
 show tables
 select * from order_t;
 +------+------+
 | id   | name |
 +------+------+
 |    1 | x    |
 |    2 | y    |
 +------+------+
 2 rows in set (0.05 sec)
 ​
 mysql> select * from user;
 +------+------+
 | id   | name |
 +------+------+
 |    1 | a    |
 |    2 | b    |
 |    3 | c    |
 +------+------+

 [root@db02 conf]# mysql -S /data/3307/mysql.sock -e "show tables from taobao"
 +------------------+
 | Tables_in_taobao |
 +------------------+
 | user             |
 +------------------+
 [root@db02 conf]# mysql -S /data/3308/mysql.sock -e "show tables from taobao"
 +------------------+
 | Tables_in_taobao |
 +------------------+
 | order_t          |
 +------------------+
 [root@db02 conf]# mysql -S /data/3307/mysql.sock -e "select * from taobao.user"
 +------+------+
 | id   | name |
 +------+------+
 |    1 | a    |
 |    2 | b    |
 |    3 | c    |
 +------+------+
 [root@db02 conf]# mysql -S /data/3308/mysql.sock -e "select * from taobao.order_t"
 +------+------+
 | id   | name |
 +------+------+
 |    1 | x    |
 |    2 | y    |
 +------+------

MyCAT核心特性——分片(水平拆分)

 分片:對一個"bigtable",比如說t3表
 (1)行數非常多,800w
 (2)訪問非常頻繁
 分片的目的:
 1)將大數據量進行分布存儲
 2)提供均衡的訪問路由
 分片策略:
 幾乎融合經典業務中大部分的分片策略。Mycat已經開發了相應演算法,非常方便調用。
 範圍分片
 取模
 枚舉
 日期
 HASH
 等。
 分片鍵: 作為分片條件的列。

範圍分片(range)

  比如說t3表
 行數非常多,2000w(1-1000w:sh1   1000w01-2000w:sh2)
 訪問非常頻繁,用戶順序訪問較多

訂製分片策略

 [root@db02 conf]#cp schema.xml schema.xml.1 
 [root@db02 conf]#vim schema.xml
    <table name="user" dataNode="sh1"/>
  <table name="order_t" dataNode="sh2"/>  
 下方添加:
    <table name="t3" dataNode="sh1,sh2" rule="auto-sharding-long" />
 </schema>   

定義和使用分片策略

 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>

定義範圍

 [root@db02 conf]#vim autopartition-long.txt
 0-10=0
 10-20=1

創建測試表

 [root@db02 conf]# 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);"
 [root@db02 conf]# 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並測試

 [root@db02 conf]# mycat restart
 [root@db02 conf]# mysql -uroot -p123456 -h 10.0.0.52 -P 8066  --default-auth=mysql_native_password 
 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');
 mysql> show databases;
 +----------+
 | DATABASE |
 +----------+
 | TESTDB   |
 +----------+
 mysql> use TESTDB;
 mysql> show tables;
 +------------------+
 | Tables_in_taobao |
 +------------------+
 | order_t          |
 | t3               |
 | user             |
 +------------------+
 #####邏輯上合併
 mysql> select * from t3;
 +----+------+
 | id | name |
 +----+------+
 |  1 | a    |
 |  2 | b    |
 |  3 | c    |
 |  4 | d    |
 | 11 | aa   |
 | 12 | bb   |
 | 13 | cc   |
 | 14 | dd   |
 +----+------+
 ​
 ###物理上分開
 [root@db02 conf]# mysql -S /data/3308/mysql.sock  -e "select * from taobao.t3"
   +----+------+
 | id | name |
 +----+------+
 | 11 | aa   |
 | 12 | bb   |
 | 13 | cc   |
 | 14 | dd   |
 +----+------+
 [root@db02 conf]# mysql -S /data/3307/mysql.sock  -e "select * from taobao.t3"
   +----+------+
 | id | name |
 +----+------+
 |  1 | a    |
 |  2 | b    |
 |  3 | c    |
 |  4 | d    |

 +----+------+

取模分片(mod-long)

 1%3 1
 2%3 2
 3%3 0
 4%3 1
 5%3 2
 任何正整數數字和N(正整數)取模,得的值永遠都是 0~N-1
 id % 分片數量取模
 N % 5 =  0-4   idx

修改配置文件

 取余分片方式:分片鍵(一個列)與節點數量進行取余,得到餘數,將數據寫入對應節點
 [root@db02 conf]#vim schema.xml
 添加:....t3之後
    <table name="t4" dataNode="sh1,sh2" rule="mod-long" />

查看和定義分片使用

 [root@db02 conf]#vim rule.xml
 <property name="count">3</property>
     <property name="count">2</property>   #將3修改為2

準備測試環境

創建測試表

 [root@db02 conf]# 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);" [root@db02 conf]# 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

 [root@db02 conf]# mycat restart 

測試

 [root@db01 ~]# mysql -uroot -p123456 -h 10.0.0.52 -P8066 --default-auth=mysql_native_password 
 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');
 insert into t4(id,name) values(6,'x'),(8,'y'),(10,'z');

登錄端節點查詢數據

 [root@db02 conf]# mysql -S /data/3308/mysql.sock -e "select * from taobao.t4"
  +----+------+
 | id | name |
 +----+------+
 |  1 | a    |
 |  3 | c    |
 +----+------+  
 [root@db02 conf]# mysql -S /data/3307/mysql.sock -e "select * from taobao.t4"
    +----+------+
 | id | name |
 +----+------+
 |  2 | b    |
 |  4 | d    |
 |  6 | x    |
 |  8 | y    |
 | 10 | z    |
 +----+------+

枚舉分片(區域,zone)

 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
 添加t4之後
 <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>
 </function>
 vim  partition-hash-int.txt 配置: 
 bj=0 
 sh=1
 DEFAULT_NODE=1      #默認分

準備測試環境

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.52 -P8066 --default-auth=mysql_native_password 
 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');

測試

 mysql -S /data/3308/mysql.sock -e "select * from taobao.t5"
 +----+------+
 | id | name |
 +----+------+
 |  2 | sh   |
 |  4 | sh   |
 |  5 | tj   |
 +----+------+
 mysql -S /data/3307/mysql.sock -e "select * from taobao.t5"
 +----+------+
 | id | name |
 +----+------+
 |  1 | bj   |
 |  3 | bj   |
 +----+------+

Mycat全局表

 a   b   c  d   .....
 join
 t 
 a  
 id   name   age 
 1    zs     18   sh1 
 id    addr  aid 
 1001  bj    1 
 1002  sh    2 
 2    ls     19   sh2 
 id    addr  aid 
 1001  bj    1 
 1002  sh    2 
 t 
 id    addr  aid 
 1001  bj    1 
 1002  sh    2 

使用場景

如果你的業務中有些數據類似於數據字典,比如配置文件的配置, 常用業務的配置或者數據量不大很少變動的表,這些表往往不是特別大, 而且大部分的業務場景都會用到,那麼這種表適合於Mycat全局表,無須對數據進行切分, 要在所有的分片上保存一份數據即可,Mycat 在Join操作中,業務表與全局表進行Join聚合會優先選擇相同分片內的全局表join, 避免跨庫Join,在進行數據插入操作時,mycat將把數據分發到全局表對應的所有分片執行,在進行數據讀取時候將會隨機獲取一個節點讀取數據。

設置全局表策略

 [root@db02 conf]#vim schema.xml 
 <table name="t_area" primaryKey="id" type="global" dataNode="sh1,sh2" /> 

後端數據準備

[root@db02 conf]# mysql -S /data/3307/mysql.sock -e "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 -e "use taobao;create table t_area (id int not null primary key auto_increment,name varchar(20) not null);"

重啟mycat

 [root@db02 conf]# mycat restart 

測試

 [root@db02 conf]# mysql -uroot -p123456 -h10.0.0.52 -P8066 --default-auth=mysql_native_password 

 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');
 mysql -S /data/3308/mysql.sock -e "select * from taobao.t_area"
 +----+------+
 | id | name |
 +----+------+
 |  1 | a    |
 |  2 | b    |
 |  3 | c    |
 |  4 | d    |
 +----+------+
 mysql -S /data/3307/mysql.sock -e "select * from taobao.t_area"
 +----+------+
 | id | name |
 +----+------+
 |  1 | a    |
 |  2 | b    |
 |  3 | c    |
 |  4 | d    |
 +----+------+

E-R分片(有關聯的表)

 a
 join 
 b 
 on  a.xx =b.yy 
 a        
 id  name
 --------------             
 1   a       sh1 
 3   c  
 ----------------
 2   b       sh2 
 4   d   
 ​
 b 
 id   addr  aid
 1001  bj   1        sh1  
 1002  sh   2 
 ​
 1003  tj   3        sh2 
 1004  wh   4 

修改配置文件

 vim schema.xml
 <table name="a" dataNode="sh1,sh2" rule="mod-long_oldguo"> 
        <childTable name="b" joinKey="aid" parentKey="id" /> 
 </table>

修改分片策略

 vim rule.xml
 #mod-long之後
 <tableRule name="mod-long_oldguo">               
 <rule>                       
 <columns>id</columns>        
 <algorithm>mod-long_oldguo</algorithm>              
 </rule>        
 </tableRule>   
 ​
 ###<property name="count">2</property>
         </function>
 添加之後
 <function name="mod-long_oldguo" class="io.mycat.route.function.PartitionByMod">               <!-- how many data nodes -->              
 <property name="count">2</property>       
 </function>

創建測試表

mysql -S /data/3307/mysql.sock -e "use taobao;create table a 
(id int not null primary key auto_increment,name varchar(20) not null);"
 mysql -S /data/3307/mysql.sock -e "use taobao;create table b 
(id int not null primary key auto_increment,addr varchar(20) not null ,aid int );"
 mysql -S /data/3308/mysql.sock -e "use taobao;create table a 
(id int not null primary key auto_increment,name varchar(20) not null);"
 mysql -S /data/3308/mysql.sock -e "use taobao;create table b
 (id int not null primary key auto_increment,addr varchar(20) not null ,aid int );"

重啟mycat 測試

 mycat restart
 mysql -uroot -p123456 -h10.0.0.52 -P8066 --default-auth=mysql_native_password 
 use TESTDB                          
 insert into a(id,name) values(1,'a');                           
 insert into a(id,name) values(2,'b');                           
 insert into a(id,name) values(3,'c');                           
 insert into a(id,name) values(4,'d');                           
 insert into a(id,name) values(5,'e');                       
 insert into b(id,addr,aid) values(1001,'bj',1);                 
 insert into b(id,addr,aid) values(1002,'sj',3);                 
 insert into b(id,addr,aid) values(1003,'sd',4);                 
 insert into b(id,addr,aid) values(1004,'we',2);                 
 insert into b(id,addr,aid) values(1005,'er',5); 

後端數據節點數據分布

 mysql -S /data/3307/mysql.sock  -e "select * from taobao.a"     
 +----+------+
 | id | name |
 +----+------+
 |  2 | b    |
 |  4 | d    |
 +----+------+
 mysql -S /data/3307/mysql.sock  -e "select * from taobao.b"     +------+------+------+
 | id   | addr | aid  |
 +------+------+------+
 | 1003 | sd   |    4 |
 | 1004 | we   |    2 |
 +------+------+------+                      
 mysql -S /data/3308/mysql.sock  -e "select * from taobao.a"     
 +----+------+
 | id | name |
 +----+------+
 |  1 | a    |
 |  3 | c    |
 |  5 | e    |
 +----+------+
 mysql -S /data/3308/mysql.sock  -e "select * from taobao.b" 
 +------+------+------+
 | id   | addr | aid  |
 +------+------+------+
 | 1001 | bj   |    1 |
 | 1002 | sj   |    3 |
 | 1005 | er   |    5 |
 +------+------+------+