部署步骤 介绍:
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 请查看优先级 是否存在主/备 在失败优先级降低了后 仍然高于