部署步骤

介绍:

MySQL 双主架构,抢占式,主 MySQL 服务出现问题 自动切换为主备,主 MySQL 服务修复成功后将又切换回来,虚拟 ip 对外提供服务。(可改为非抢占式和基于 GTID 的复制 本文是基于 binlog 的复制)

MySQL 部署在容器环境数据容易出现问题,所以本文选择物理机方式安装部署。

职责 IP 地址 系统版本 MySQL 版本
主 MASTER01 192.168.229.136 CentOS 7.6 MySQL 5.7
主 MASTER02(备) 192.168.229.137 CentOS 7.6 MySQL 5.7

虚拟 IP:192.168.229.130


1、准备工作

关闭 selinux

1
2
3
Shell
setenforce 0
sed -i '/^SELINUX=/c\SELINUX=disabled' /etc/selinux/config

关闭防火墙(云服务器在网站配置安全组)

1
2
3
4
5
6
7
8
9
10
11
# 查看所有打开端口 需提前安装 yum install firewalld 并开启服务。
firewall-cmd --zone=public --list-ports

# 开放端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent

# 批量永久开放端口
firewall-cmd --zone=public --add-port=80-90/tcp --permanent

# 刷新 开放之后必执行
firewall-cmd --reload

2、使用 MySQL Replication 实现主主同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

# 配置阿里yum源 加快下载速度,看需求配置。注意Centos版本。
# 若没有安装wget 先使用 yum install -y wget 安装
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 清除原有yum缓存:
yum clean all

# 生成新的缓存:
yum makecache



# 安装MySQL的yum源,下面是RHEL6系列的下载地址
rpm -Uvh http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm

# 安装yum-config-manager
yum install yum-utils -y

# 禁用MySQL5.6的源
yum-config-manager --disable mysql56-community

# 启用MySQL5.7的源
yum-config-manager --enable mysql57-community-dmr

# 用下面的命令查看是否配置正确 出现5.7
yum repolist enabled | grep mysql

# 修改/etc/yum.repos.d/mysql-community.repo文件
baseurl=http://repo.mysql.com/yum/mysql-5.7-community/el/7/$basearch/
gpgcheck=0


# 安装MySQL5.7
yum install module disable mysql
yum install mysql-community-server

# 禁用selinux
setenforce 0
sed -i '/^SELINUX=/c\SELINUX=disabled' /etc/selinux/config

# 启动mysqld,启动之前先修改/etc/my.cnf配置文件。 简单配置
#-----------------------
# master01 - my.cnf
server_id=1 #服务器ID
log-bin=master01-bin #二进制日志文件名
slave_parallel_workers=4
slave_parallel_type='LOGICAL_CLOCK'

auto_increment_increment=2
auto_increment_offset=1


# --- 可以附加的----------
# relay log

max_relay_log_size = 0

relay_log=$datadir/relay-bin # 若已有数据 则可以不开启 不然会导致原先日志失效

relay_log_purge = 1

relay_log_recovery = 1

sync_relay_log =0

sync_relay_log_info = 0

# ---

#-----------------------

# master02 - my.cnf
server_id=2 # 服务器ID
log-bin=master02-bin # 二进制日志文件名

slave_parallel_workers=4 # 5.7可开启多线程复制
slave_parallel_type='LOGICAL_CLOCK'

auto_increment_increment=2
auto_increment_offset=2

#------------------------

# 开启服务
service mysqld start

# 查找初试密码 进入mysql
grep "password" /var/log/mysqld.log

# 取消密码限制
set global validate_password_policy=0;
set global validate_password_length=1;

# 设置root密码不过期
ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;

# 修改密码
SET PASSWORD = PASSWORD('root');

# 任意ip访问
grant all privileges on *.* to root@"%" identified by "wyt123!";

grant all privileges on *.* to root@"localhost" identified by "wyt123!";

# 刷新
flush privileges;

# 配置主主架构 即正反做2次主从复制,采用binlog方式进行,可以自行改为基于GTID的复制


# 创建slave01用户 通过此用户 master02 访问 master01
CREATE USER 'slave01'@'%' IDENTIFIED BY 'slave01';
GRANT REPLICATION SLAVE ON *.* TO 'slave01'@'%';


# master01 设置主 master02 设置从

# 在master02 操作

# master02的主库绑定为master01 注意 LOG_FILE 和 LOG_POS 需要提前在主库show master status; 查询
CHANGE MASTER TO
MASTER_HOST='192.168.229.136',
MASTER_PORT=3306,
MASTER_USER='slave01',
MASTER_PASSWORD='slave01',
MASTER_LOG_FILE='mysql01-bin.000003',
MASTER_LOG_POS=611;

# 开启从库功能
start slave;

# 查看从库状态 IO_Running 和 SQL_Running 为 YES 即为成功
show slave status\G

# 由于开启了主从功能 在master01上创建的用户也会在master02上创建 若单独在master02上创建 可能会导致主从不一致
# 所以我们在master01上创建用户slave02 master01 通过此用户 访问master02


# 在master01 操作
CREATE USER 'slave02'@'%' IDENTIFIED BY 'slave02';
GRANT REPLICATION SLAVE ON *.* TO 'slave02'@'%';

# master01 的 主库绑定为 master02
CHANGE MASTER TO
MASTER_HOST='192.168.229.137',
MASTER_PORT=3306,
MASTER_USER='slave02',
MASTER_PASSWORD='slave02',
MASTER_LOG_FILE='master02-bin.000004',
MASTER_LOG_POS=1695;


# 若报错连接失败 测试是否是防火墙问题

3、部署 Keepalived

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
Shell
# 安装
yum install -y openssl-devel

cd /usr/local/src/

wget http://www.keepalived.org/software/keepalived-1.3.5.tar.gz

tar -zvxf keepalived-1.3.5.tar.gz

cd keepalived-1.3.5

./configure --prefix=/usr/local/keepalived

# 若出现警告
WARNING - this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS.
# 自己安装
yum -y install libnl libnl-devel


# 若出现错误:
configure: error: libnfnetlink headers missing

# 自己安装
yum install -y libnfnetlink-devel

# 若gcc ---- no

# 自己安装gcc
yum -y install gcc

# 再次执行configure 这一步可能会出现很多错误 往往都是需要自己手动安装某些包 成功后如下所示
Keepalived configuration
------------------------
Keepalived version : 1.3.5
Compiler : gcc
Preprocessor flags :
Compiler flags : -Wall -Wunused -Wstrict-prototypes -Wextra -g -O2
Linker flags :
Extra Lib : -lcrypto -lssl -lnl
Use IPVS Framework : Yes
IPVS use libnl : Yes
IPVS syncd attributes : No
IPVS 64 bit stats : No
fwmark socket support : Yes
Use VRRP Framework : Yes
Use VRRP VMAC : Yes
Use VRRP authentication : Yes
With ip rules/routes : Yes
SNMP vrrp support : No
SNMP checker support : No
SNMP RFCv2 support : No
SNMP RFCv3 support : No
DBUS support : No
SHA1 support : No
Use Debug flags : No
Stacktrace support : No
Memory alloc check : No
libnl version : 1
Use IPv4 devconf : No
Use libiptc : No
Use libipset : No
init type : systemd
Build genhash : Yes
Build documentation : No


# 编译没有错就安装
make && make install


# 复制到默认配置
cp /usr/local/src/keepalived-1.3.5/keepalived/etc/init.d/keepalived /etc/rc.d/init.d/

cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

mkdir /etc/keepalived/

cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/

cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

echo "/etc/init.d/keepalived start" >> /etc/rc.local

# 修改配置文件

# 这个配置才生效 在status中可看到.service运行的路径 中的pid路径改为/var/run/keepalived.pid
# 不修改会报错 cant Open PID
# 再把 KillMode 注释掉 或改为control-group (默认值) 不然使用systemctl stop keepalived 只会停止主要进程导致进程残留,导致下次重启失败
vim /usr/lib/systemd/system/keepalived.service

# 若未生效 启动keepalived报错 cant Open PID 则把这个路径配置文件 .pid路径也修改成/var/run/keepalived.pid
vim /usr/local/src/keepalived-1.3.5/keepalived/keepalived.service

[Unit]
Description=LVS and VRRP High Availability Monitor
After=syslog.target network-online.target

[Service]
Type=forking
PIDFile=/var/run/keepalived.pid
EnvironmentFile=-/usr/local/keepalived/etc/sysconfig/keepalived
ExecStart=/usr/local/keepalived/sbin/keepalived $KEEPALIVED_OPTIONS
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target




# 在master01上配置 keepalived.conf

cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
vim /etc/keepalived/keepalived.conf # 清空默认内容,直接采用下面配置:cp /dev/null /etc/keepalived/keepalived.conf

! Configuration File for keepalived

vrrp_script chk_mysql_port { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
script "/opt/chk_mysql.sh" #这里通过脚本监测
interval 2 #脚本执行间隔,每2s检测一次
weight -5 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
rise 1 #检测1次成功就算成功。但不修改优先级
}

vrrp_instance VI_1 {
state MASTER # 抢占模式
interface ens33 #指定虚拟ip的网卡接口 云服务器一般是 eth0 虚拟机一般是 ens33
mcast_src_ip 192.168.229.136
virtual_router_id 51 #路由器标识,MASTER和BACKUP必须是一致的
priority 101 #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.229.130 # 虚拟ip 需要和2台master 网段一样
}

track_script {
chk_mysql_port
}
}


# 在master01 上编写切换脚本
vim /opt/chk_mysql.sh

#!/bin/bash
MYSQL=/bin/mysql #注意 需要填自己mysql路径
MYSQL_HOST=localhost
MYSQL_USER=root
MYSQL_PASSWORD=wyt123!
CHECK_TIME=3

#mysql is working MYSQL_OK is 1 , mysql down MYSQL_OK is 0

MYSQL_OK=1

function check_mysql_helth (){
$MYSQL -h $MYSQL_HOST -u $MYSQL_USER -p${MYSQL_PASSWORD} -e "show status;" >/dev/null 2>&1
if [ $? = 0 ] ;then
MYSQL_OK=1
else
MYSQL_OK=0
fi
return $MYSQL_OK
}
while [ $CHECK_TIME -ne 0 ]
do
let "CHECK_TIME -= 1"
check_mysql_helth
if [ $MYSQL_OK = 1 ] ; then
CHECK_TIME=0
exit 0
fi
if [ $MYSQL_OK -eq 0 ] && [ $CHECK_TIME -eq 0 ]
then
pkill keepalived
exit 1
fi
sleep 1
done



# 启动
systemctl start keepalived


# 在master02 上 执行操作

cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak

>/etc/keepalived/keepalived.conf

vim /etc/keepalived/keepalived.conf

! Configuration File for keepalived

vrrp_script chk_mysql_port {
script "/opt/chk_mysql.sh"
interval 2
weight -3 # 每次-3 区别于主 假设先启动从99 失败 -5 = 94 由于后续启动成功也不会修改优先级 再启动主无论是否失败 优先级都 # 高于从 所以当从修复好之后 主就算已经是失败状态也不会把vip转接给从,反之 由于是抢占模式主修复好后必然会接管VIP
fall 2 # 所以我们需要遵循的原则是 从启动失败一次后的优先级 要大于主启动失败一次的优先级 不然由于启动的先后顺序会导致从
rise 1 # 无法正确接管主机
}

vrrp_instance VI_1 {
state BACKUP
interface ens33
mcast_src_ip 192.168.229.137
virtual_router_id 51
priority 99 # 优先级改为100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.229.130
}

track_script {
chk_mysql_port
}
}


# 和master01 脚本一样
vim /opt/chk_mysql.sh

chmod 755 /opt/chk_mysql.sh

systemctl start keepalived

# 测试
mysql -h192.168.229.130 -uroot -pwyt123!

show variables like 'AUTO_INC%';

# 用自己电脑 连接 虚拟ip 上的MySQL show variables like 'AUTO_INC%'; 发现id是1
# 停掉master01的mysql服务后 再次 show variables like 'AUTO_INC%'; 发现id是2 切换成功
# 再次启动master01的mysql服务 执行 show variables like 'AUTO_INC%'; 发现id又是1 至此部署成功。


# 由于keepalived的邮件发送太难用 我们需要重新使用其他形式的邮件发送方式 以达到切换时的邮件通知功能。


# 注意 若中途重启keepalived后 备用机或者主机无法正确接管vip 请查看优先级 是否存在主/备 在失败优先级降低了后 仍然高于