1.应用程序通过HaProxy访问Mycat
2.Mycat实现分库分表以及根据访问的表选择不同的数据库
3.读写user表时通过Mycat节点1访问数据库并使用Percona-xtraDB-Cluster(pxc)实现强同步
4.读写ordertest表时则通过Mycat节点2访问数据库,两个数据库之间一主一从实现读写分离
5.user表引入了zookeeper工具,利用zkID生成器保证ID不会重复。
6.服务器ip地址:192.168.187.129
7.教程中展示了基于docker搭建master01和slave01,请仿照搭建master02和slave02,作为上图最后前4台mysql节点,后2台主从节点教程中会给出步骤。
8.请自行在mysql节点中建立M2Test数据库以及user表和ordertest表。
9.最终效果图及端口配置请拉至底部
10.关闭防火墙或者开启相应端口
11.关于各个工具的详细作用请自行查阅。
1)docker创建master
mkdir /data/mysql/master01 -p
cd /data/mysql/master01/
mkdir conf data
chmod 777 * -R
cd conf/
vim my.cnf
[mysqld]
server-id = 21
binlog-format = row
log-bin=mysql-bin
2)创建名为percona-masetr01的容器并搭建Master
|root@Node_Slave:~# docker create --name percona-master01 -v /data/mysql/master01/data:/var/lib/mysql -v /data/mysql/master01/conf:/etc/mysql/conf.d/ -p 3306:3306 -e MYSQL_ROOT_PASSWORD=666666 percona:5.7.22
命令说明:
注意:务必确认主机目录和容器目录存在,否则my.cnf配置无法生效,可通过先创建容器里的mysql去查看路径再回来修改。
-p 3306:3306:将容器的 3306 端口映射到主机的 3306 端口。
-v /data/mysql/master01/data:/var/lib/mysql :将主机当前目录/data/mysql/master01/data目录挂载到容器目录/var/lib/mysql。
-v /data/mysql/master01/conf:/etc/mysql/conf.d/:将主机当前目录下的 data/mysql/master01/conf挂载到容器的 /etc/mysql/conf.d/。
-e MYSQL_ROOT_PASSWORD=666666:初始化 root 用户的密码。
3)启动并进入创建的容器
root@Node_Slave:~# docker start percona-master01 && docker logs -f percona-master01
root@Node_Slave:~#docker exec -it percona-master01 bash
4)在容器里启动mysql
root@e1603b0f6621:/# mysql -u root -p
5)创建用户并授予权限
mysql> create user 'itcast'@'%' identified by '666666';
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on *.* to 'itcast'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
6)查看master status,为slave做准备
mysql> show master status;
root@Node_Slave:~# mkdir /data/mysql/slave01
root@Node_Slave:~# cd /data/mysql/slave01/
root@Node_Slave:/data/mysql/slave01# mkdir conf data
root@Node_Slave:/data/mysql/slave01# chmod 777 * -R
root@Node_Slave:/data/mysql/slave01# cd /data/mysql/slave01/conf/
vim my.cnf
[mysqld]
server-id = 22
8)创建slave容器并进入
root@Node_Slave:~# docker create --name percona-slave01 -v /data/mysql/slave01/data:/var/lib/mysql -v /data/mysql/slave01/conf:/etc/mysql/conf.d/ -p 3307:3306 -e MYSQL_ROOT_PASSWORD=666666 percona:5.7.22
root@Node_Slave:~# docker start percona-slave01 && docker logs -f percona-slave01
root@Node_Slave:~#docker exec -it percona-slave01 bash
root@e1603b0f6621:/# mysql -u root -p
9)配置Slave指向Master
如果配置集群,记得master非3306的,指定master_port=xxxx
mysql> change master to master_host='192.168.187.129',master_user='itcast',master_password='666666',master_log_file='mysql-bin.000001',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.10 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
注意: Linux下部署安装MySQL,默认不忽略表名大小写,需要手动到/etc/my.cnf 下配置
lower_case_table_names=1
使Linux环境下MySQL忽略表名大小写,否则使用MyCAT的时候会提示找不到表的错误!如果一开始是区分大小写建的数据库和表
则需要导出再重建导入了。切记:数据库表名不要引用mysql关键字比如order,否则mycat端会打不开。
1)安装mycat
创建mycat配置文件夹
mkdir /usr/local/mycat
mkdir /usr/local/mycat/conf
创建docker文件夹
mkdir /usr/local/docker/mycat/
cd /usr/local/docker/mycat
下载mycat安装包
wget http://dl.mycat.io/1.6.6.1/Mycat-server-1.6.6.1-release-
20181031195535-linux.tar.gz
mv Mycat-server-1.6.6.1-release-20181031195535-linux.tar.gz mycat.tar.gz
解压并复制文件
tar -zxvf mycat.tar.gz
cp -r mycat/conf/ /usr/local/mycat/conf/
创建Dockerfile文件
touch Dockerfile
vim Dockerfile
#基于opjdk8创建镜像,可自行替换centos等
FROM openjdk:8
ADD mycat.tar.gz /usr/local/
VOLUME /usr/local/mycat/conf
ENV MYCAT_HOME=/usr/local/mycat
EXPOSE 8066 9066
CMD ["/usr/local/mycat/bin/mycat", "console","&"]
### 说明 ####
将mycat解压到/usr/local目录中,得到 /usr/local/mycat
#将mycat的配置文件的地址暴露出映射地址,启动时直接映射宿主机的文件夹
#设置MYCAT_HOME
#暴露出MyCat的所需端口
#以前台进程的方式启动MyCat服务
构建镜像
docker build -t mycat-1.6.6.1 .
启动容器
docker run --name mycat -p 8066:8066 -p 9066:9066 -v /usr/local/
mycat/conf/:/usr/local/mycat/conf/ -d mycat-1.6.6.1
补充:
vim server.xml
666666
M2Test
666666
M2Test
true
3)vim schema.xml
schema.xml记得xml文件首行不能有空格 首字符顶到头
schema、dataNode、dataHost标签在schema.xml文件中,必须按照顺序书写。
select user()
select user()
name属性: 唯一标识dataHost标签,供上层标签使用。
macCon属性:指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、readHost标签都会使用这个属性的值来实例化出连接池的最大连接数。
minCon属性:指定每个读写实例连接池的最小连接,初始化连接池的大小
4.balance属性: 负载均衡类型,目前的取值有以下4种。 balance=0: 不开启读写分离,所有读操作都发送到当前可用的writeHost上。 balance=1: 全部的readHost与Stand by
writeHost都参与select语句的负载均衡,简而言之,当双主双从模式(M1–>S1,
M2—>S2,并且M1与M2互为主备)时,在正常情况下,M2,S1和S2都参与select的负载均衡。 balance=2:
所有的读操作都随机在writeHost,readHost上分发。 balance=3:
所有的读请求都随机分配到writeHost对应的readHost上执行,writeHost不负担读压力,注意balance=3只在mycat1.4之后版本中有效。
5.writeType属性:负载均衡类型,目前的取值有3种:
1. writeType=“0”, 所有写操作都发送到可用的writeHost上。
2. writeType=“1”,所有写操作都随机的发送到readHost。
3. writeType=“2”,所有写操作都随机的在writeHost、readhost分上发。
6.dbType属性:指定后端连接的数据库类型,目前支持二进制的mysql协议,还有其他使用JDBC连接的数据库。如mongodb,spark等。7.dbDriver属性: 指定连接后端数据库使用的Driver,目前可选的值有native和JDBC。使用native的话,因为这个值执行的是二进制的mysql协议,所以可以使用mysql和maridb。其他类型的数据库则需要使用JDBC驱动来支持。
8.switchType属性:
-1:表示不自动切换。 1 :默认值,表示自动切换 2:表示基于MySQL主从同步状态决定是否切换,心跳语句: show slave status. 3:表示基于mysql galary cluster的切换机制,适合mycat1.4之上的版本,心跳语句show
status like “%esrep%”;9.tempReadHostAvailable属性: 如果配置了writehost,下面的readhost依旧可用。 • heratbeat标签: 这个标签内指明用于和后端数据库进行心跳检查的语句。例如,MYSQL可以使用select
user(),Oracle可以使用select 1 from dual等。mycat1.4中主从切换语句必须是show slave
status.
• writeHost标签,readHost标签:这两个标签指定后端数据库的相关配置给mycat,用于实例化后端连接池。唯一不同的是,writeHost指定写实例、readHost指定读实例,组合这些读写实例来满足系统的要求。
在一个dataHost内可以定义多个writeHost和readHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。另一方面,这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去。
o host属性:用于标识不同的实例,对于writehost,一般使用M1;对于readhost一般使用S1.
o url属性:后端实例连接地址,如果使用native的dbDriver,则一般为address:port这种形式,用JDBC或其他的dbDriver,则需要特殊指定。当使用JDBC时则可以这么写:jdbc:mysql://localhost:3306/。
o user属性:后端存储实例的用户名。 o password属性:后端存储实例的密码
o weight属性:在readHost中作为读节点的权重(mycat1.4版本之后才有的)
o usingDecrypt属性:同server.xml中。
4)vim rule.xml
1.tableRule(tableRule是针对表的规则 columns是列名)
id
mod-long
2.function
2
3.function 配置是分片规则的配置。
name 为切分规则的名称,名字人员取,但是需要与tableRule 中匹配。 class
是切分规则对应的切分类,写死,需要哪种规则则配置哪种,例如本例子是PartitionByMod分片:class=“io.mycat.route.function.PartitionByMod”
property 标签是切分规则对应的不同属性,不同的切分规则配置不同。partitionCount、partitionLength
5)vi sequence_conf.properties
USER.HISIDS=
USER.MINID=1001
USER.MAXID=2000
USER.CURID=1000
7)两种推荐的方式连接测试mycat
1.Linux下的MYSQL客户端命令行
Ps:此方法可以避免因为mycat的分库分表操作带来的ID等重复问题 注意: 1)使用zookeeper要配置好JDK
2)在/usr/local/mycat/conf/下配置完server.xml、schema.xml和rule.xml 等等参数之后需要执行
cp -f schema.xml server.xml rule.xml zkconf/
进行强制覆盖zkconf的参数然后到/usr/local/mycat/bin/下执行./init_zk_
data.sh
加载zk,如果不强制覆盖,/mycat/conf/zkconf/会反过来覆盖/mycat/conf/(或者直接在/mycat/conf/zkconf/下编辑然后都/bin执行./init_zk_data.sh)
1.安装JDK(如已安装请忽略):
到官网
https://www.oracle.com/technetwork/java/javase/downloads/index.html
下载JDK必须是如下开头版本,普通的版本linux无法安装
3.配置环境变量: vim /etc/profile
export JAVA_HOME=/usr/local/java8
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH
4.执行 source /etc/profile
5.查看是否成功安装 java -version
2)安装zookeeper:
注意:重启后如果无法启动 进入/usr/local/zookeeper/data/ 把zookeeper_server.pid删除重启即可
1.下载zookeeper:
wget
http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
2.将zookeeper.tar.gz解压至 /usr/local/zookeeper/
3.进入zookeeper的conf目录下,复制zoo_sample.cfg文件并自定义配置
cp zoo_sample.cfg zoo.cfg
4.编辑配置文件: vi zoo.cfg
# The number of milliseconds of each tick ZK中的一个时间单元2000ms
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take Leader允许Follower在initLimit时间内完成初始化工作。
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.就是把内存中的数据存储成快照文件snapshot的目录
# do not use /tmp for storage, /tmp here is just
# example sakes.记得创建下面这两个目录
dataDir= /usr/local/zookeeper/data
dataLogDir= /usr/local/zookeeper/datalog
# the port at which the clients will connect
clientPort=2181
server.1=192.168.187.129:2888:3888
#.1跟/usr/local/zookeeper/data/下的myid要一致,"="后面是本机ip地址,配置集群则是多个ip地址,然后更换server.xxx
cd /usr/local/zookeeper/data
vi myid 输入1 并保存退出
此处的数字1与zoo.cfg里server.XX要一致
cd /usr/local/zookeeper/bin
启动 ./zkServer.sh start
9.查看server状态 ./zkServer.sh status 下图为单机模式
10.启动客户端./zkCli.sh start
3)mycat连接至zookeeper
Mycat保证id唯一的方式有如下几个:
1)本地文件方式
2)数据库方式
3)时间戳方式
4)ZKID生成器
5)ZK递增ID推荐使用第4,5种
以上5中方式都要***统一在server.xml文件中开启全局序列号的配置和在schema.xml文件中配置逻辑表的autoIncrement属性为true
***
接下来为Mycat配置ZKID生成器教程:
1.server.xml:sequnceHandlerType进行相应全局序列号策略选项设置,在mycat中对应的源码是MyCATSequnceProcessor.java
1.sequnceHandlerType可取的值有以下几个:
0:本地文件方式 1:数据库方式 2:时间戳方式 3:ZKID生成器 4:ZK递增ID
设置server.xml: 3
2.设置schema.xml: autoIncrement=“true”
3.开启zookeeper配置
cd /usr/local/mycat/conf
4.vim myid.properties
loadZk=true
zkURL=192.168.187.129:2181
clusterId=mycat-cluster-1
myid=mycat_fz_01
clusterSize=1
clusterNodes=mycat_fz_01
#server booster ; booster install on db same server,will reset all minCon to 2
type=server
boosterDataHosts=dataHost1
以下为代码解释
loadZk=true #启用zookeeper
zkURL=192.168.187.129:2181 # zk集群地址,多个用","隔开
clusterId=mycat-cluster-1 #zk集群内Mycat集群ID
myid=mycat_fz_01 # Mycat集群内本实例ID,禁止重复,要属于clusterNodes中的一个
clusterSize=3 # Mycat集群内节点个数
clusterNodes=mycat_fz_01,mycat_fz_02,mycat_fz_03
#server booster ;
booster install on db same server,will reset all minCon to 1
type=server
boosterDataHosts=dataHost1
5.vim sequence_distributed_conf.properties
INSTANCEID=ZK
CLUSTERID=01
6.使用Mycat脚本初始化mycat在ZK中的节点数据
cd /usr/local/mycat/bin/
./init_zk_data.sh
7.启动mycat
可在/mycat/bin# 执行 ./mycat start 然后 ./mycat console 查看输出信息
如果是在docker创建的可以:
docker start mycat && docker logs -f mycat
4)使用navicat插入数据测试
1.插入相应的列值,使用ZKID生成
INSERT INTO user (id,name) VALUES ( 1292866567750684672,'gg');
2.查看是否成功生成
1)创建容器存储路径:/var/lib/docker/volumes
docker volume create quan-v1
docker volume create quan-v2
docker volume create quan-v3
docker volume create quan-v4
2)创建docker网段
docker network create --subnet=172.30.0.0/24 pxc-network
3)创建容器
注意:
1.node2和node4分别加入node1和node3形成两个集群
2.CLUSTER_JOIN=pxc_node1,表示node2加入node1集群)
docker create -p 13306:3306 -v quan-v1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=666666 -e CLUSTER_NAME=pxc --name=pxc_node1 --net=pxc-network --ip=172.30.0.2 pxc:5.7.22
docker create -p 13307:3306 -v quan-v2:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=666666 -e CLUSTER_NAME=pxc --name=pxc_node2 -e CLUSTER_JOIN=pxc_node1 --net=pxc-network --ip=172.30.0.3 pxc:5.7.22
docker create -p 13308:3306 -v quan-v3:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=666666 -e CLUSTER_NAME=pxc --name=pxc_node3 --net=pxc-network --ip=172.30.0.4 pxc:5.7.22
docker create -p 13309:3306 -v quan-v4:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=666666 -e CLUSTER_NAME=pxc --name=pxc_node4 -e CLUSTER_JOIN=pxc_node3 --net=pxc-network --ip=172.30.0.5 pxc:5.7.22
4)启动容器
docker start pxc_node1 && docker logs -f pxc_node1
docker start pxc_node2 && docker logs -f pxc_node2
docker start pxc_node3 && docker logs -f pxc_node3
docker start pxc_node4 && docker logs -f pxc_node4
5)在节点1和3创建数据库,看是否自动同步至2和4
1)docker创建master
mkdir /data/mysql/quan/master01 -p
cd /data/mysql/quan/master01/
mkdir conf data
chmod 777 * -R
cd conf/
vim my.cnf
[mysqld]
server-id = 41
binlog-format = row
log-bin=mysql-bin
2)创建名为percona-masetr01的容器并搭建Master
root@Node_Slave:~# docker create --name percona-quan-master01 -v /data/mysql/quan/master01/data:/var/lib/mysql -v /data/mysql/quan/master01/conf:/etc/mysql/conf.d/ -p 23306:3306 -e MYSQL_ROOT_PASSWORD=666666 percona:5.7.22
3)启动并进入创建的容器
root@Node_Slave:~# docker start percona-quan-master01 && docker logs -f percona-quan-master01
root@Node_Slave:~#docker exec -it percona-quan-master01 bash
4)在容器里启动mysql
root@e1603b0f6621:/# mysql -u root -p
5)创建用户并授予权限
mysql> create user 'itcast'@'%' identified by '666666';
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on *.* to 'itcast'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
6)查看master status记录下Execute_Gtid_Set和Position为slave做准备
mysql> show master status;
7)搭建Slave01
root@Node_Slave:~# mkdir /data/mysql/quan/slave01
root@Node_Slave:~# cd /data/mysql/quan/slave01/
root@Node_Slave:/data/mysql/slave01# mkdir conf data
root@Node_Slave:/data/mysql/slave01# chmod 777 * -R
root@Node_Slave:/data/mysql/slave01# cd /data/mysql/quan/slave01/conf/
vim my.cnf
[mysqld]
server-id = 42
8)创建slave容器并进入
root@Node_Slave:~# docker create --name percona-quan-slave01 -v /data/mysql/quan/slave01/data:/var/lib/mysql -v /data/mysql/quan/slave01/conf:/etc/mysql/conf.d/ -p 23307:3306 -e MYSQL_ROOT_PASSWORD=666666 percona:5.7.22
root@Node_Slave:~# docker start percona-quan-slave01 && docker logs -f percona-quan-slave01
root@Node_Slave:~#docker exec -it percona-quan-slave01 bash
root@e1603b0f6621:/# mysql -u root -p
9)配置Slave指向Master
如果配置集群,记得master非3306端口的,指定master_port=xxxx
mysql> change master to master_host='192.168.187.129',master_user='itcast',master_port=23306,master_password='666666',master_log_file='mysql-bin.000001',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.10 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
1)配置mycat
root@MycatHarproxy:~# mkdir /data/mycat
root@MycatHarproxy:~# cd /data/mycat/
root@MycatHarproxy:/data/mycat# ls
root@MycatHarproxy:/data/mycat# cd /usr/local/mycat
root@MycatHarproxy:/usr/local/mycat# cp * /data/mycat -r
root@MycatHarproxy:/data/mycat# cd conf/
2)配置server.xml
server.xml添加管理端口
1
0
druidparser
2
0
0
1
1m
1k
0
389m
18067
19067
666666
M2Test
123456
M2Test
true
30)设置jmx端口
4)配置schema.xml 此处dn1和dn2的balance变为2
select user()
select user()
select user()
1.第一、二集群 修改balance=2 读写操作随机分发至writeHost和readHost,第三集群是主从复制集群balance=3,主从读写分离。
2.dn1和dn2与MysqlClutsre1相对应,dn3和MysqlCluster2对应
5)执行jps查看mycat启动情况,有的话kill掉
6)正式启动mycat并输出相关信息
./startup_nowrap.sh && tail -f ../logs/mycat.log
8)设置mycat-node2
1.进入新的mycat文件夹
2.将其复制为第二个mycat节点
3.修改mycat-node2端口wrapper.conf为11986
root@MycHaPro:/data/mycat-node2# cd conf/
root@MycHaPro:/data/mycat-node2/conf# vim wrapper.conf
4.修改server.xml端口如下
5.连接测试
1)建立相应haproxy文件夹
mkdir /quan/haproxy -p
2)配置haproxy文件以及修改端口,此端口与默认端口不同因为之前配置过避免冲突,默认端口请自行查询
vim /quan/haproxy/haproxy.cfg
global
log 127.0.0.1 local2
maxconn 4000
daemon
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
listen admin_stats
bind 0.0.0.0:4001
mode http
stats uri /dbs
stats realm Global\ statistics
stats auth admin:666666
listen proxy-mysql
bind 0.0.0.0:4002
mode tcp
balance roundrobin
option tcplog
server mycat_1 192.168.187.129:18067 check port 18067 maxconn 2000
server mycat_2 192.168.187.129:18068 check port 18068 maxconn 2000
3)创建容器,如果前面已经创建则直接启动即可
docker create --name haproxy --net host -v /quan/haproxy:/usr/local/etc/haproxy haproxy:1.9.3
4)启动容器
docker start haproxy && docker logs -f haproxy
至此,所有工具搭建完毕,实现高可用集群。
2.在haproxy新建查询往user表插入数据
3.可见mycat节点1生成了数据
4.Mysql cluster1下的3306端口写入数据
5.Mysql-3306端口数据通过pxc强同步至3307端口
6.在haproxy往ordertest表写入数据
7.Mycat节点2接收到数据
8.Mysql Cluster2下的23306端口的mysql数据库写入数据
9.查看由zkID生成的ID,可保证ID不重复
补充:node启动错误
2019-08-02T15:28:40.598516Z 0 [ERROR] WSREP: It may not be safe to
bootstrap the cluster from this node. It was not the last one to leave
the cluster and may not contain all the updates. To force cluster
bootstrap with this node, edit the grastate.dat file manually and set
safe_to_bootstrap to 1 . 2019-08-02T15:28:40.598520Z 0 [ERROR] WSREP:
Provider/Node (gcomm://) failed to establish connection with cluster
(reason: 7) 2019-08-02T15:28:40.598523Z 0 [ERROR] Aborting
故障处理
集群本身无问题,只是非正常关闭。
cd /var/lib/docker/volumes/quan-v1/_data/
vim grastate.dat
修改第一个启动节点的grastate.dat文件,将
GALERA saved state version: 2.1 uuid:
8ed447b7-dafa-11e7-8071-a6ba78498531 seqno: -1 safe_to_bootstrap:
0 改为 1 然后可以直接启动