一、环境准备
我们需要准备两台服务器并使用docker分别在两台服务器上安装MySql。
二、主从复制
1. 配置主服务器
1.1 创建MySQL docker 并配置主服务器
# 不应该换行的,这里为了方便查看,我给它分行了
docker run -p 3320:3306 --name mysql_master
-v /docker/mysql_master/conf:/etc/mysql/conf.d
-v /docker/mysql_master/logs:/logs
-v /docker/mysql_master/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -d mariadb
按如上的方法创建的 mariadb 我只需要在 /docker/mysql_master/conf 这个目录下创建 my.cnf 文件就好了。
[mysqld]
## 同一局域网内注意要唯一
server-id=1
## 开启二进制日志功能,可以随便取(关键)
log-bin=mysql-bin
1.2 重启 mariadb docker 容器
docker restart mysql_master
1.3 查看 skip_networking 的状态
确保在主服务器上 skip_networking 选项处于 OFF 关闭状态, 这是默认值。
如果是启用的,则从站无法与主站通信,并且复制失败。
mysql> show variables like '%skip_networking%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| skip_networking | OFF |
+-----------------+-------+
1 row in set (0.00 sec)
1.4 创建一个专门用来复制的用户
CREATE USER 'repl'@'%' identified by '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
2. 配置从服务器
2.1 创建MySQL docker 并配置从服务器
docker run -p 3330:3306 --name mysql_slave
-v /docker/mysql_from/conf:/etc/mysql/conf.d
-v /docker/mysql_from/logs:/logs
-v /docker/mysql_from/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -d mariadb
和上面一样,配置从服务器的 my.cnf
[mysqld]
server-id=2
2.2 重启 mysql docker 容器
docker restart mysql_master
2.3 配置连接到主服务器的相关信息
在从服务器配置连接到主服务器的相关信息 (在容器里面的mysql执行)
# MASTER_HOST 填写自己服务器的IP地址
mysql> CHANGE MASTER TO MASTER_HOST='xxxxx', MASTER_PORT=3320,MASTER_USER='repl',MASTER_PASSWORD='123456';
启动的那个从服务器的线程
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
2.4 查看同步状态
mysql> show slave status \G;
如果出现如下状况:
这个报错的原因可能是由于:(1)已创建过该用户 (2)已有该用户的授权信息
解决方法:
删除此用户,刷新,并重启slave
#删除该用户
mysql> drop user 'zhangsan'@'%';
mysql> FLUSH PRIVILEGES;
# 重启同步
mysql> stop slave;
mysql> start slave;
# 最后查看是否同步正常
mysql> show slave status\G
三、主主复制
1、修改上面的从服务器的my.cnf文件,和主服务器的一样(注意这个server-id不能一样)然后重启服务器
2、在主、从服务器里面创建一个复制用户创建命令一样(这里修改一下用户名可以改为 repl2)
grant replication slave on *.* to 'repl'@'%' identified by '123456';
3、在主服务器从服务器里面运行下面这个代码
# 主
CHANGE MASTER TO MASTER_HOST='从服务器IP地址', MASTER_PORT=3306,MASTER_USER='repl',MASTER_PASSWORD='123456';
# 从
CHANGE MASTER TO MASTER_HOST='主服务器IP地址', MASTER_PORT=3306,MASTER_USER='repl',MASTER_PASSWORD='123456';
start slave;
四、用keepalived实现故障转移
- 创建keepalived文件夹,进入文件夹并下载keepalived
mkdir keepalived
cd keepalived
wget http://www.keepalived.org/software/keepalived-2.0.6.tar.gz
# 解压文件
tar -xzvf keepalived-2.0.6.tar.gz
- 安装相关依赖
sudo apt-get install openssl
sudo apt-get install net-snmp
sudo apt-get install libnl-3-dev
sudo apt-get install libnl-route-3-dev
sudo apt-get install -y ipvsadm
- 安装keepalived
cd keepalived-2.0.6
./configure
make && make install
编译安装结束后,会根据系统环境生成启动脚本:
cat /usr/lib/systemd/system/keepalived.service
4. 将keepalved加进系统服务并且在/etc/sysconfig/写入配置文件以及将keepalived命令加进/usr/bin 和 /usr/sbin(下面命令中注释在使用中忽略):
cp keepalived/keepalived-2.0.6/etc/init.d/keepalived /etc/init.d/keepalived #最好查看下keeplaived是否有执行权限
mkdir /etc/keepalived/
cp /usr/local/etc/keepalived/keepalived.conf /etc/keepalived/
cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/
cp /usr/local/sbin/keepalived /usr/bin/ #方便以后查看keepalived的版本,用keepalived -v可以查看
cp /usr/local/sbin/keepalived /usr/sbin/
- 修改配置文件
vim /etc/keepalived/keepalived.conf
主机配置文件(不可直接复制,根据实际情况自己修改):
! Configuration File for keepalived
global_defs {
router_id MYSQL_MASTER #主备须一致
vrrp_skip_check_adv_addr
#vrrp_iptables
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER #本实例启动状态:MASTER/BACKUP
interface eno1 #监控的网络接口
virtual_router_id 51 #vrrp实例(同一个组主备服务器设置一样)
priority 100 #优先级高的为master,不能超过255。(BACKUP可设置为50)
advert_int 1 #均衡器检测间隔1秒(服务器设置都一样)
authentication { #验证类型及密码(服务器设置都一样)
auth_type PASS #认证方式,PASS或AH
auth_pass 1111 #认证密码
}
unicast_src_ip 17.120.53.212 #单播的源地址,写本机上的ip即可
unicast_peer { #注意:花括号前有空格
17.120.53.100 #如果有多个主机组成集群,把其它主机ip都写上
}
virtual_ipaddress { #虚拟ip地址virtual_ipaddress,可以定义多个
17.120.53.222/21 brd 17.120.55.255 dev eno1 label eno1:1
}
}
virtual_server 17.120.53.222 3320 {
delay_loop 3 #健康检查时间间隔,3秒
lb_algo rr #负载均衡调度算法:rr|wrr|lc|wlc|sh|dh|lblc
lb_kind NAT #负载均衡转发规则:NAT|DR|TUN
persistence_timeout 50 #回话保持时间50秒,动态服务建议开启
protocol TCP #转发协议protocol,一般有tcp和udp两种
real_server 17.120.53.212 3320 { # 指定real server1的IP地址
weight 3 # 配置节点权值,数字越大权重越高
notify_down /root/shutdown.sh #检测3320端口为down状态就执行此脚本(只有keepalived关闭,VIP才漂移 )
TCP_CHECK { #健康检查方式:HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 3320
}
}
}
备机配置文件(不可直接复制,根据实际情况自己修改):
! Configuration File for keepalived
global_defs {
router_id MYSQL_SLAVE #主备须一致
vrrp_skip_check_adv_addr
#vrrp_iptables
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state BACKUP #本实例启动状态:MASTER/BACKUP
interface enp0s31f6 #监控的网络接口
virtual_router_id 51 #vrrp实例(同一个组主备服务器设置一样)
priority 50 #优先级高的为master,不能超过255。(BACKUP可设置为50)
advert_int 1 #均衡器检测间隔1秒(服务器设置都一样)
authentication { #验证类型及密码(服务器设置都一样)
auth_type PASS #认证方式,PASS或AH
auth_pass 1111 #认证密码
}
unicast_src_ip 17.120.53.100 ##自己ip
unicast_peer { ##单播模式
17.120.53.212 ##另一个ip
}
virtual_ipaddress { #虚拟ip地址virtual_ipaddress,可以定义多个
17.120.53.222/21 brd 17.120.55.255 dev enp0s31f6 label enp0s31f6:1
}
}
virtual_server 17.120.53.222 3320 {
delay_loop 3 #健康检查时间间隔,3秒
lb_algo rr #负载均衡调度算法:rr|wrr|lc|wlc|sh|dh|lblc
lb_kind NAT #负载均衡转发规则:NAT|DR|TUN
persistence_timeout 50 #回话保持时间50秒,动态服务建议开启
protocol TCP #转发协议protocol,一般有tcp和udp两种
real_server 17.120.53.100 3320 { # 指定real server1的IP地址
weight 3 # 配置节点权值,数字越大权重越高
notify_down /root/shutdown.sh #检测3320端口为down状态就执行此脚本(只有keepalived关闭,VIP才漂移 )
TCP_CHECK { #健康检查方式:HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 3320
}
}
}
- 编写检测服务down后所要执行的脚本shutdown.sh:
vim /root/shutdown.sh
# 内容是:
#!/bin/bash
pkill keepalive
注:此脚本是上面配置文件notify_down选项所用到的,keepalived使用notify_down选项来检查real_server的服务状态,当发现real_server服务故障时,便触发此脚本,此处监控3320端口,如果发现3320端口掉线则将主机的keepalived杀死,VIP就会漂移到备用机上。我们可以看到,脚本就一个命令,通过pkill keepalived强制杀死keepalived进程,从而实现了MySQL故障自动转移。另外,我们不用担心两个MySQL会同时提供数据更新操作,因为每台MySQL上的keepalived的配置里面只有本机MySQL的IP+VIP,而不是两台MySQL的IP+VIP。
- 启动keepalived并查看日志
service keepalived start #启动服务
service keepalived stop #停止服务
service keepalived restart #重启服务
systemctl enable keepalived.service #设置开机启动
启动后查看日志:
tail -f /var/log/messages
- keepalived的配置详解
# 全局配置
global_defs {
# 邮件通知信息
notification_email {
# 定义收件人
acassen@firewall.loc
}
# 定义发件人
notification_email_from Alexandre.Cassen@firewall.loc
# SMTP服务器地址
smtp_server 192.168.200.1
smtp_connect_timeout 30
# 路由器标识,一般不用改,也可以写成每个主机自己的主机名
router_id LVS_DEVEL
# VRRP的ipv4和ipv6的广播地址,配置了VIP的网卡向这个地址广播来宣告自己的配置信息,下面是默认值
vrrp_mcast_group4 224.0.0.18
vrrp_mcast_group6 ff02::12
}
# 定义用于实例执行的脚本内容,比如可以在线降低优先级,用于强制切换
vrrp_script SCRIPT_NAME {
}
# 一个vrrp_instance就是定义一个虚拟路由器的,实例名称
vrrp_instance VI_1 {
# 定义初始状态,可以是MASTER或者BACKUP
state MASTER
# 工作接口,通告选举使用哪个接口进行
interface ens33
# 虚拟路由ID,如果是一组虚拟路由就定义一个ID,如果是多组就要定义多个,而且这个虚拟
# ID还是虚拟MAC最后一段地址的信息,取值范围0-255
virtual_router_id 51
# 使用哪个虚拟MAC地址
use_vmac XX:XX:XX:XX:XX
# 监控本机上的哪个网卡,网卡一旦故障则需要把VIP转移出去
track_interface {
eth0
ens33
}
# 如果你上面定义了MASTER,这里的优先级就需要定义的比其他的高
priority 100
# 通告频率,单位为秒
advert_int 1
# 通信认证机制,这里是明文认证还有一种是加密认证
authentication {
auth_type PASS
auth_pass 1111
}
# 设置虚拟VIP地址,一般就设置一个,在LVS中这个就是为LVS主机设置VIP的,这样你就不用自己手动设置了
virtual_ipaddress {
# IP/掩码 dev 配置在哪个网卡
192.168.200.16/24 dev eth1
# IP/掩码 dev 配置在哪个网卡的哪个别名上
192.168.200.17/24 dev label eth1:1
}
# 虚拟路由,在需要的情况下可以设置lvs主机 数据包在哪个网卡进来从哪个网卡出去
virtual_routes {
192.168.110.0/24 dev eth2
}
# 工作模式,nopreempt表示工作在非抢占模式,默认是抢占模式 preempt
nopreempt|preempt
# 如果是抢占默认则可以设置等多久再抢占,默认5分钟
preempt delay 300
# 追踪脚本,通常用于去执行上面的vrrp_script定义的脚本内容
track_script {
}
# 三个指令,如果主机状态变成Master|Backup|Fault之后会去执行的通知脚本,脚本要自己写
notify_master ""
notify_backup ""
notify_fault ""
}
# 定义LVS集群服务,可以是IP+PORT;也可以是fwmark 数字,也就是防火墙规则
# 所以通过这里就可以看出来keepalive天生就是为ipvs而设计的
virtual_server 10.10.10.2 1358 {
delay_loop 6
# 算法
lb_algo rr|wrr|lc|wlc|lblc|sh|dh
# LVS的模式
lb_kind NAT|DR|TUN
# 子网掩码,这个掩码是VIP的掩码
nat_mask 255.255.255.0
# 持久连接超时时间
persistence_timeout 50
# 定义协议
protocol TCP
# 如果后端应用服务器都不可用,就会定向到那个服务器上
sorry_server 192.168.200.200 1358
# 后端应用服务器 IP PORT
real_server 192.168.200.2 1358 {
# 权重
weight 1
# MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
# 针对应用服务器做健康检查的方法
MISC_CHECK {}
# 用于检查SMTP服务器的
SMTP_CHEKC {}
# 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
TCP_CHECK {
# 向哪一个端口检查,如果不指定默认使用上面定义的端口
connect_port <PORT>
# 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
bindto <IP>
# 连接超时时间
connect_timeout 3
}
# 如果对方是HTTPS服务器就用SSL_GET方法去检查,里面配置的内容和HTTP_GET一样
SSL_GET {}
# 应用服务器UP或者DOWN,就执行那个脚本
notify_up "这里写的是路径,如果脚本后有参数,整体路径+参数引起来"
notify_down "/PATH/SCRIPTS.sh 参数"
# 使用HTTP_GET方法去检查
HTTP_GET {
# 检测URL
url {
# 具体检测哪一个URL
path /testurl/test.jsp
# 检测内容的哈希值
digest 640205b7b0fc66c1ea91c463fac6334d
# 除了检测哈希值还可以检测状态码,比如HTTP的200 表示正常,两种方法二选一即可
status_code 200
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
# 向哪一个端口检查,如果不指定默认使用上面定义的端口
connect_port <PORT>
# 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
bindto <IP>
# 连接超时时间
connect_timeout 3
# 尝试次数
nb_get_retry 3
# 每次尝试之间间隔几秒
delay_before_retry 3
}
}
real_server 192.168.200.3 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}