文章目录

  • 节点规划
  • 主机名、防火墙、时钟源设置
  • NFS配置
  • 配置nginx
  • 配置LVS
  • 配置php
  • 配置tomcat
  • 数据库配置
  • 配置MHA
  • redis配置
  • session会话共享配置

思路:

  • lvs+keepalived实现四层负载均衡
  • nginx做七层负载均衡和反向代理
  • nfs做静态资源异地容灾
  • tomcat+php做后端动态页面解析
  • mysql主从复制做存储层
  • redis主从复制做session会话共享
  • mha对mysql进行故障自动切换

两台lvs+keepalived服务器,提供VIP,保证高可用并实现四层负载均衡,将请求转发到两台nginx服务器,nginx服务器做七层负载均衡和反向代理并实现动静分离,静态资源存放至NFS服务器做冗余容灾,动态请求转发至后端Tomcat和PHP服务器进行解析,redis一主一从三哨兵+keepalived提供VIP实现会话共享。mysql 数据库服务器做一主两从复制,使用mha提供VIP并实现数据库故障的自动切换,保证数据的安全及稳定性。

节点规划

因为实验资源受限,所以一台主机会充当多个角色

主机名 IP 角色 备注
ds-master IP:192.168.126.90 VIP:192.168.126.100 LVS maste、php服务器、tomcat服务器 部署lvs与keepalived,VIP为浮动IP,同时部署php和tomcat
ds-slave IP:192.168.126.91 VIP:192.168.126.100 LVS slave、php服务器、tomcat服务器 部署lvs与keepalived,VIP为浮动IP,同时部署php和tomcat
rs1 192.168.126.92 VIP:192.168.126.200(mysql) VIP:192.168.126.250(redis) nginx服务器1、mysql主服务器 、redis主+keepalived、redis哨兵 1提供WEB静态资源及对动态资源请求转发至后端tomcat服务器、mysql主(mysql主节点,负责写数据)
rs2 192.168.126.93 nginx服务器2 、mysql服务器、redis从+keepalived、redis哨兵2 提供WEB静态资源及对动态资源请求转发至后端tomcat服务器、mysql从1(mysql从节点,负责读数据,备选master)
nfs 192.168.126.94 数据共享服务器 、mysql服务器、redis哨兵3 提供网页共享静态WEB资源、mysql从2(mysql从节点,负责读数据)
mha 192.168.126.95 MHA manger MySQL 高可用方案,故障切换

主机名、防火墙、时钟源设置

hostnamectl set-hostname xxxx
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
yum install ntpdate -y
ntpdate ntp1.aliyun.com
hwclock -w

NFS配置

安装服务

[root@nfs ~]# yum -y install nfs-utils rpcbind
[root@nfs ~]# rpm -qa nfs-utils rpcbind
nfs-utils-1.3.0-0.68.el7.1.x86_64
rpcbind-0.2.0-49.el7.x86_64

配置 exports文件

[root@nfs ~]# mkdir -p /data/
[root@nfs ~]# vim /etc/exports
/data/ 192.168.126.0/24(rw,sync)
[root@nfs ~]# chown -R nfsnobody:nfsnobody /data
drwxr-xr-x. 2 nfsnobody nfsnobody 6 Sep 21 19:03 /data
[root@nfs ~]# systemctl start nfs
[root@nfs ~]# systemctl enable nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.

启动服务

[root@nfs ~]# systemctl start nfs

在rs1,rs2上配置nfs客户端

[root@rs1 ~]# yum install nfs-utils -y
[root@rs1 ~]# showmount -e 192.168.126.94
Export list for 192.168.126.94:
/data 192.168.126.0/24

在rs2上执行相同的操作

配置nginx

rs1:

安装nginx

[root@rs1 ~]# vim /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true[root@rs1 ~]# yum makecache fast[root@rs1 ~]# yum repolist | grep nginx-stable
nginx-stable/7/x86_64                nginx stable repo                       242[root@rs1 ~]# yum install nginx -y
[root@rs1 ~]# rpm -qa nginx
nginx-1.20.1-1.el7.ngx.x86_64[root@rs1 ~]# egrep -v '^$|#' /etc/nginx/conf.d/default.conf
server {listen       80;server_name  localhost;location ^~ /static/ {root /usr/share/nginx/html;index  index1.html;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   /usr/share/nginx/html;}
}
[root@rs1 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful[root@rs1 ~]# mkdir -p /usr/share/nginx/html/static
[root@rs1 ~]# vim /etc/fstab
192.168.126.94:/data /usr/share/nginx/html nfs defaults 0 0
[root@rs1 ~]# mount -a
[root@rs1 ~]# df -h | grep data
192.168.126.94:/data     9.8G  2.8G  7.1G  29% /usr/share/nginx/html[root@rs1 ~]# echo "It is test from rs1 192.168.126.92" > /usr/share/nginx/html/static/index1.html[root@rs1 ~]# systemctl start nginx
[root@rs1 ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

测试:

rs2:

[root@rs2 ~]# vim /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true[root@rs2 ~]# yum makecache fast[root@rs2 ~]# yum repolist | grep nginx-stable
nginx-stable/7/x86_64                nginx stable repo                       242[root@rs2 ~]# yum install nginx -y
[root@rs2 ~]# rpm -qa nginx
nginx-1.20.1-1.el7.ngx.x86_64[root@rs2 ~]# egrep -v '^$|#' /etc/nginx/conf.d/default.conf
server {listen       80;server_name  localhost;location ^~ /static/ {root /usr/share/nginx/html;index  index2.html;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   /usr/share/nginx/html;}
}
[root@rs2 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful[root@rs2 ~]# vim /etc/fstab
192.168.126.94:/data /usr/share/nginx/html nfs defaults 0 0
[root@rs2 ~]# mount -a
[root@rs2 ~]# df -h | grep data
192.168.126.94:/data     9.8G  2.8G  7.1G  29% /usr/share/nginx/html[root@rs2 ~]# echo "It is test from rs2 192.168.126.93" > /usr/share/nginx/html/static/index2.html[root@rs2 ~]# systemctl start nginx
[root@rs2 ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

测试:

配置LVS

lvs_dr模式dr无法主动识别rs上的web服务器是否停止工作,为解决这一问题,用到keepalived,集成高可用集群和负载均衡为一体(keepalived–>HA+LB)

ds-master配置:

[root@ds-master ~]# yum -y install keepalived ipvsadm[root@ds-master ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id LVS_DEVEL
}vrrp_instance VI_1 {state MASTERinterface ens32virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.126.100}
}virtual_server 192.168.126.100 80 {delay_loop 6lb_algo rrlb_kind DRpersistence_timeout 50protocol TCPreal_server 192.168.126.92 80 {weight 100TCP_CHECK {connect_timeout 10       # 10秒无反应超时nb_get_retry 3delay_before_retry 3connet_port 80}}real_server 192.168.126.93 80 {weight 100TCP_CHECK {connect_timeout 10nb_get_retry 3delay_before_retry 3connet_port 80}}
}

ds-slave配置:

[root@ds-slave ~]# yum -y install keepalived ipvsadm[root@ds-slave ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id LVS_DEVEL
}vrrp_instance VI_1 {state BACKUPinterface ens32virtual_router_id 51priority 90advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.126.100}
}virtual_server 192.168.126.100 80 {delay_loop 6lb_algo rrlb_kind DRpersistence_timeout 50protocol TCPreal_server 192.168.126.92 80 {weight 100TCP_CHECK {connect_timeout 10       # 10秒无反应超时nb_get_retry 3delay_before_retry 3connet_port 80}}real_server 192.168.126.93 80 {weight 100TCP_CHECK {connect_timeout 10 nb_get_retry 3delay_before_retry 3connet_port 80}}
}

ds-master和ds-slave配置完成后,启动keepalived

[root@ds-master ~]# systemctl start keepalived
[root@ds-master ~]# systemctl enable keepalived
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/keepalived.service.[root@ds-slave ~]# systemctl start keepalived
[root@ds-slave ~]# systemctl enable keepalived
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/keepalived.service.# 查看ds-master的VIP是否生成(slave没有VIP(当主停掉时,备才启动))
[root@ds-master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000link/ether 00:0c:29:a1:54:3f brd ff:ff:ff:ff:ff:ffinet 192.168.126.90/24 brd 192.168.126.255 scope global ens32valid_lft forever preferred_lft foreverinet 192.168.126.100/32 scope global ens32  # 已生成valid_lft forever preferred_lft forever# 分别查看ipvsadm规则
[root@ds-master ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.126.100:80 rr persistent 50-> 192.168.126.92:80            Route   100    0          0         -> 192.168.126.93:80            Route   100    0          0  [root@ds-slave ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.126.100:80 rr persistent 50-> 192.168.126.92:80            Route   100    0          0         -> 192.168.126.93:80            Route   100    0          0

rs1和rs2配置:

# 把vip绑定在lo上,是为了实现rs直接把结果返回给客户端
[root@rs1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.126.100
NETMASK=255.255.255.255
ONBOOT=yes[root@rs1 ~]# systemctl restart network
[root@rs1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet 192.168.126.100/32 brd 192.168.126.100 scope global lo:0valid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000link/ether 00:0c:29:2b:48:05 brd ff:ff:ff:ff:ff:ffinet 192.168.126.92/24 brd 192.168.126.255 scope global ens32valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fe2b:4805/64 scope link valid_lft forever preferred_lft forever# 以下操作为更改arp内核参数,目的是为了让rs顺利发送mac地址给客户端
[root@rs1 ~]# vim /etc/sysctl.conf
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
[root@rs1 ~]# sysctl -p

测试

为了便于短时间内观察效果,需要关闭长链接,禁用浏览器缓存等操作:
(1)在windows浏览器中选择禁用缓存

(2)将ipvs会话保持时间设置小点

[root@ds-master ~]# ipvsadm --set 1 1 1
[root@ds-master ~]# ipvsadm -L --timeout
Timeout (tcp tcpfin udp): 1 1 1
[root@ds-master ~]# vim /etc/keepalived/keepalived.conf
persistence_timeout 3
[root@ds-master ~]# systemctl restart keepalived[root@ds-slave ~]# ipvsadm --set 1 1 1
[root@ds-slave ~]# vim /etc/keepalived/keepalived.conf
persistence_timeout 3
[root@ds-slave ~]# systemctl restart keepalived

(3)将nginx中的长连接设置小点

[root@rs1 ~]# vim /etc/nginx/nginx.conf
…………keepalive_timeout  3;
…………
[root@rs1 ~]# nginx -s reload[root@rs2 ~]# vim /etc/nginx/nginx.conf
…………keepalive_timeout  3;
…………
[root@rs2 ~]# nginx -s reload


通过以上设置会话保持时间大约在3秒并且因为使用rr轮询算法,所以每次间隔3秒访问 192.168.126.100/static/ 时,client每次访问VIP,那么DS会按照依次循环的方式将请求调度到后端的RS服务器上

lvs+keepalived 主要作用:

  • 应对高并发连接做负载均衡。将客户端请求按照设定的策略分发到后端服务器上

  • 保证业务的高可用。

    停止rs1的nginx服务,客户机访问虚拟IP。结果:成功跳过不能访问的rs1,rs1的转发规则也被清掉(重启nginx,又会加回来)

    停掉ds-master上的主keepalived,查看主备状态。结果:备用keepalived接管,重新启动主keepalived时,主重启接管

配置php

nfs服务器:

配置nfs服务器上的php网页资源

[root@nfs ~]# mkdir -p /data/php
[root@nfs ~]# vim /data/php/index.php
<?php
system("/var/www/html/ip.sh");   # 为了后面便于观察最后到底是将请求分发到具体的哪个php服务器上,所以该php网页测试页面的作用是:通过php页面来调用shell脚本显示当前执行请求的php服务器IP地址
?>
[root@nfs ~]# vim /data/php/ip.sh # shell脚本
#!/bin/bash
/usr/sbin/ifconfig ens32 | awk 'NR==2 {print $2}'
[root@nfs ~]# chmod 755 /data/php/ip.sh

ds-master:

下载安装

# 安装jdk
[root@ds-master ~]# ls
jdk-8u112-linux-x64.rpm
[root@ds-master ~]# yum localinstall jdk-8u112-linux-x64.rpm -y
[root@ds-master ~]# java -version
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)# 下载安装php
[root@ds-master ~]# yum -y install php-fpm php-mbstring.x86_64 php-gd.x86_64 php-mysql.x86_64 php

配置php

[root@ds-master ~]# vim /etc/php-fpm.d/www.conf
listen = 0.0.0.0:9000         开监听地址为任意。
;listen.allowed_clients = 127.0.0.1    把这一行注释# 网页文件可直接挂载至nfs服务器上
[root@ds-master ~]# yum install nfs-utils -y
[root@ds-master ~]# showmount -e 192.168.126.94
Export list for 192.168.126.94:
/data 192.168.126.0/24 [root@ds-master ~]# vim /etc/fstab
192.168.126.94:/data/php /var/www/html nfs defaults 0 0
[root@ds-master ~]# mount -a
[root@ds-master ~]# df -h | grep /data/php
192.168.126.94:/data/php  9.8G  2.8G  7.1G  29% /var/www/html[root@ds-master ~]# systemctl start php-fpm
[root@ds-master ~]# systemctl enable php-fpm
Created symlink from /etc/systemd/system/multi-user.target.wants/php-fpm.service to /usr/lib/systemd/system/php-fpm.service.

ds-slave:

下载安装

# 安装jdk
[root@ds-slave ~]# ls
jdk-8u112-linux-x64.rpm
[root@ds-slave ~]# yum localinstall jdk-8u112-linux-x64.rpm -y
[root@ds-slave ~]# java -version
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)# 下载安装php
[root@ds-slave ~]# yum -y install php-fpm php-mbstring.x86_64 php-gd.x86_64 php-mysql.x86_64 php

配置php

[root@ds-slave ~]# vim /etc/php-fpm.d/www.conf
listen = 0.0.0.0:9000         开监听地址为任意。
;listen.allowed_clients = 127.0.0.1    把这一行注释[root@ds-slave ~]# yum install nfs-utils -y
[root@ds-slave ~]# showmount -e 192.168.126.94
Export list for 192.168.126.94:
/data 192.168.126.0/24 [root@ds-salve ~]# vim /etc/fstab
192.168.126.94:/data/php /var/www/html nfs defaults 0 0
[root@ds-salve ~]# mount -a
[root@ds-salve ~]# df -h | grep /data/php
192.168.126.94:/data/php  9.8G  2.8G  7.1G  29% /var/www/html[root@ds-slave ~]# systemctl start php-fpm
[root@ds-slave ~]# systemctl enable php-fpm
Created symlink from /etc/systemd/system/multi-user.target.wants/php-fpm.service to /usr/lib/systemd/system/php-fpm.service.

在nginx配置文件中写入php的location匹配规则

rs1:

[root@rs1 ~]# egrep -v '^$|#' /etc/nginx/conf.d/default.conf
upstream php {server 192.168.126.90:9000;server 192.168.126.91:9000;
}
server {listen       80;server_name  localhost;location ~* \.php$ {fastcgi_pass php;fastcgi_index index.php;fastcgi_param  SCRIPT_FILENAME        /var/www/html/$fastcgi_script_name;include fastcgi_params;}location ^~ /static/ {root /usr/share/nginx/html;index  index1.html;}
}
[root@rs1 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@rs1 ~]# nginx -s reload

rs2:

[root@rs2 ~]# egrep -v '^$|#' /etc/nginx/conf.d/default.conf
upstream php {server 192.168.126.90:9000;server 192.168.126.91:9000;
}
server {listen       80;server_name  localhost;location ~* \.php$ {fastcgi_pass php;fastcgi_index index.php;fastcgi_param  SCRIPT_FILENAME        /var/www/html/$fastcgi_script_name;include fastcgi_params;}location ^~ /static/ {root /usr/share/nginx/html;index  index2.html;}
}
[root@rs2 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@rs2 ~]# nginx -s reload

测试

结果:以轮询的方式将请求发送到后端php服务器群

数据流: client发送对LVS的VIP请求关于index.php页面—> LVS将请求按照rr算法(keepalived中配置为rr)转发到后端nginx服务器—>nginx服务器根据location匹配规则再将请求通过fastcgi_pass指令转发到定义好的php负载均衡服务器集群(上面定义为php),根据upstream中的算法(上面设定为rr)将请求调度到指定的php服务器上进行解析并将结果进行原路返回

配置tomcat

ds-master:

安装tomcat

[root@ds-master ~]# ls
apache-tomcat-8.0.36.tar.gz
[root@ds-master ~]# mkdir /usr/local/tomcat
[root@ds-master ~]# tar -xf apache-tomcat-8.0.36.tar.gz -C /usr/local/tomcat

创建网页

[root@ds-master ~]# vim /usr/local/tomcat/apache-tomcat-8.0.36/webapps/ROOT/test.jsp
<html><body bgcolor="green"><center><h1>192.168.126.90</h1><h1>port:8080</h1><h1>this is ds-master! </h1></center></body>
</html>

ds-slave:
    安装tomcat

[root@ds-slave ~]# ls
apache-tomcat-8.0.36.tar.gz
[root@ds-slave ~]# mkdir /usr/local/tomcat
[root@ds-slave ~]# tar -xf apache-tomcat-8.0.36.tar.gz -C /usr/local/tomcat

创建网页

[root@ds-slave ~]# vim /usr/local/tomcat/apache-tomcat-8.0.36/webapps/ROOT/test.jsp
<html><body bgcolor="blue"><center><h1>192.168.126.91</h1><h1>port:8080</h1><h1>this is ds-slave! </h1></center></body>
</html>

在nginx配置文件中写入js的location匹配规则

rs1:

[root@rs1 ~]# egrep -v '#|^$' /etc/nginx/conf.d/default.conf
upstream php {server 192.168.126.90:9000;server 192.168.126.91:9000;
}
upstream js {server 192.168.126.90:8080;server 192.168.126.91:8080;
}
server {listen       80;server_name  localhost;location ~* \.php$ {fastcgi_pass php;fastcgi_index index.php;fastcgi_param  SCRIPT_FILENAME        /var/www/html/$fastcgi_script_name;include fastcgi_params;}location ~ \.jsp$ {proxy_pass http://js;}   location ^~ /static/ {root /usr/share/nginx/html;index  index1.html;}
}
[root@rs1 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@rs1 ~]# nginx -s reload

rs2:

[root@rs2 ~]# egrep -v '#|^$' /etc/nginx/conf.d/default.conf
upstream php {server 192.168.126.90:9000;server 192.168.126.91:9000;
}
upstream js {server 192.168.126.90:8080;server 192.168.126.91:8080;
}
server {listen       80;server_name  localhost;location ~* \.php$ {fastcgi_pass php;fastcgi_index index.php;fastcgi_param  SCRIPT_FILENAME        /var/www/html/$fastcgi_script_name;include fastcgi_params;}location ~ \.jsp$ {proxy_pass http://js;}   location ^~ /static/ {root /usr/share/nginx/html;index  index2.html;}
}
[root@rs2 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@rs2 ~]# nginx -s reload

启动tomcat

# 为了便于观察效果,将tomcat会话保持时间尽可能缩小
[root@ds-slave ~]# vim /usr/local/tomcat/apache-tomcat-8.0.36/conf/web.xml<session-config><session-timeout>3</session-timeout></session-config>
[root@ds-master ~]# vim /usr/local/tomcat/apache-tomcat-8.0.36/conf/web.xml<session-config><session-timeout>3</session-timeout></session-config# 启动tomcat
# ds-master
[root@ds-master ~]# /usr/local/tomcat/apache-tomcat-8.0.36/bin/startup.sh
Using CATALINA_BASE:   /usr/local/tomcat/apache-tomcat-8.0.36
Using CATALINA_HOME:   /usr/local/tomcat/apache-tomcat-8.0.36
Using CATALINA_TMPDIR: /usr/local/tomcat/apache-tomcat-8.0.36/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/local/tomcat/apache-tomcat-8.0.36/bin/bootstrap.jar:/usr/local/tomcat/apache-tomcat-8.0.36/bin/tomcat-juli.jar
Tomcat started.
[root@ds-master ~]# jps
3814 Jps
3791 Bootstrap# ds-slave
[root@ds-slave ~]# /usr/local/tomcat/apache-tomcat-8.0.36/bin/startup.sh
Using CATALINA_BASE:   /usr/local/tomcat/apache-tomcat-8.0.36
Using CATALINA_HOME:   /usr/local/tomcat/apache-tomcat-8.0.36
Using CATALINA_TMPDIR: /usr/local/tomcat/apache-tomcat-8.0.36/temp
Using JRE_HOME:        /usr/java/jdk1.8.0_161
Using CLASSPATH:       /usr/local/tomcat/apache-tomcat-8.0.36/bin/bootstrap.jar:/usr/local/tomcat/apache-tomcat-8.0.36/bin/tomcat-juli.jar
Tomcat started.
[root@ds-slave ~]# jps
51704 Jps
51673 Bootstrap

测试



结果:以轮询的方式将请求发送到后端tomcat服务器群

数据流: client发送对LVS的VIP请求关于test.jsp页面—> LVS将请求按照指定算法(keepalived中配置为rr)转发到后端nginx服务器—>nginx服务器根据location匹配规则再将请求通过proxy_pass指令转发到定义好的tomcat负载均衡服务器集群(上面定义为js),根据upstream中的算法(上面设定为rr)将请求调度到指定的tomcat服务器上进行解析并将结果进行原路返回

数据库配置

主机名 IP 角色 备注
rs1 192.168.126.92 nginx服务器1、mysql主服务器 提供WEB静态资源及对动态资源请求转发至后端tomcat服务器、mysql主(mysql主节点,负责写数据)
rs2 192.168.126.93 nginx服务器2 、mysql从1(备选master)服务器 提供WEB静态资源及对动态资源请求转发至后端tomcat服务器、mysql从1(mysql从节点,负责读数据,备选master)
nfs 192.168.126.94 数据共享服务器 、mysql从2服务器 提供网页共享静态WEB资源、mysql从2(mysql从节点,负责读数据)
mha-manager 192.168.126.95 MHA manger MySQL 高可用方案,故障切换

卸载mariadb

[root@rs1 ~]# rpm -qa mariadb*
mariadb-libs-5.5.56-2.el7.x86_64
[root@rs1 ~]# rpm -e mariadb-libs-5.5.56-2.el7.x86_64 --nodeps[root@rs2 ~]# rpm -qa mariadb*
mariadb-libs-5.5.56-2.el7.x86_64
[root@rs2 ~]# rpm -e mariadb-libs-5.5.56-2.el7.x86_64 --nodeps
[root@nfs ~]# rpm -qa mariadb*
mariadb-libs-5.5.56-2.el7.x86_64
[root@nfs ~]# rpm -e mariadb-libs-5.5.56-2.el7.x86_64 --nodeps

配置hosts

[root@rs1 ~]# vim /etc/hosts
192.168.126.92 rs1
192.168.126.93 rs2
192.168.126.94 nfs
192.168.126.95 mha-manager
[root@rs1 ~]# scp /etc/hosts rs2:/etc/hosts
[root@rs1 ~]# scp /etc/hosts nfs:/etc/hosts
[root@rs1 ~]# scp /etc/hosts mha-manager:/etc/hosts

初始化mysql并修改密码

[root@rs1 mysql-package]# ls
mysql-8.0.16-2.el7.x86_64.rpm-bundle.tar
[root@rs1 mysql-package]# tar -xf mysql-8.0.16-2.el7.x86_64.rpm-bundle.tar
[root@rs1 mysql-package]# ls
mysql-8.0.16-2.el7.x86_64.rpm-bundle.tar                 mysql-community-libs-8.0.16-2.el7.x86_64.rpm
mysql-community-client-8.0.16-2.el7.x86_64.rpm           mysql-community-libs-compat-8.0.16-2.el7.x86_64.rpm
mysql-community-common-8.0.16-2.el7.x86_64.rpm           mysql-community-server-8.0.16-2.el7.x86_64.rpm
mysql-community-devel-8.0.16-2.el7.x86_64.rpm            mysql-community-test-8.0.16-2.el7.x86_64.rpm
mysql-community-embedded-compat-8.0.16-2.el7.x86_64.rpm
[root@rs1 mysql-package]# yum localinstall *.rpm -y[root@rs1 ~]# mysqld --initialize
[root@rs1 ~]# chown -R mysql:mysql /var/lib/mysql/
[root@rs1 ~]# systemctl start mysqld
[root@rs1 ~]# systemctl enable mysqld# mysql初始化密码
[root@rs1 ~]# sed -n '/password/ p' /var/log/mysqld.log
2021-09-24T13:05:29.872624Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: d,.A/xTkq1-n   # 初始化密码[root@rs1 ~]# mysql -uroot -p
# 或 mysql -uroot -p‘d,.A/xTkq1-n’
Enter password:     # 输入初始化密码
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.16Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> alter user 'root'@'localhost' identified by 'mysql123.COM';   # 修改密码
Query OK, 0 rows affected (0.00 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)mysql> exit
Bye
[root@rs1 ~]# systemctl stop mysqld

rs2,nfs节点的mysql初始化并修改密码步骤同上(方便起见所有节点mysql密码设置为同一个)

修改mysql配置文件

rs1为主库可以实现读写

[root@rs1 ~]# egrep -v '^$|^#' /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
server_id=1 # 必须指定,且各实例均不相同
log_bin=mysql1-bin # 开启二进制日志功能,可以自定义设置二进制文件名前缀,格式为: log_bin=binlog,如果不设置则是以主机名为前缀
log_bin_index=mysql1-bin.index # 二进制日志索引文件
relay_log=relay1-log # 开启中继日志功能并指定日志名称
relay_log_index=relay1-log.index # 中继日志文件的索引文件
sync-binlog=1 # 数据刷盘参数,=1时,只要有1个事务提交就会触发写盘的操作,安全性最高,并发性最差; 数据刷盘参数=0时由文件系统控制写盘的频率,并发性能最好,但是意外丢失数据的风险最大,这里根据实际需求配置,不建议乱配。
log-slave-updates=true # 允许从服务器进行复制更新二进制文件# 排除掉不需要同步的数据库列表
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys[root@rs1 ~]# systemctl start mysqld# 查看是否开启binlog
mysql> show variables like '%log_bin%';
+---------------------------------+---------------------------------+
| Variable_name                   | Value                           |
+---------------------------------+---------------------------------+
| log_bin                         | ON                              |
| log_bin_basename                | /var/lib/mysql/mysql1-bin       |
| log_bin_index                   | /var/lib/mysql/mysql1-bin.index |
| log_bin_trust_function_creators | OFF                             |
| log_bin_use_v1_row_events       | OFF                             |
| sql_log_bin                     | ON                              |
+---------------------------------+---------------------------------+
6 rows in set (0.01 sec)

rs2为从库

[root@rs2 ~]# egrep -v '^$|^#' /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
server_id=2
log_bin=mysql2-bin  # 从库也要开启二进制日志相关功能,因为从服务器可能成为主服务器
log_bin_index=mysql2-bin.index
relay_log=relay2-log
relay_log_index=relay2-log.index
sync-binlog=1
log-slave-updates=true
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys[root@rs2 ~]# systemctl start mysqld# 查看是否开启binlog
[root@rs2 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show variables like '%log_bin%';
+---------------------------------+---------------------------------+
| Variable_name                   | Value                           |
+---------------------------------+---------------------------------+
| log_bin                         | ON                              |
| log_bin_basename                | /var/lib/mysql/mysql2-bin       |
| log_bin_index                   | /var/lib/mysql/mysql2-bin.index |
| log_bin_trust_function_creators | OFF                             |
| log_bin_use_v1_row_events       | OFF                             |
| sql_log_bin                     | ON                              |
+---------------------------------+---------------------------------+
6 rows in set (0.01 sec)

nfs作为从库

[root@nfs ~]# egrep -v '^$|^#' /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
server_id=3
log_bin=mysql3-bin
log_bin_index=mysql3-bin.index
relay_log=relay3-log
relay_log_index=relay3-log.index
log-slave-updates=true
sync-binlog=1
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys[root@nfs ~]# systemctl start mysqld# 查看是否开启binlog
[root@nfs ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show variables like '%log_bin%';
+---------------------------------+---------------------------------+
| Variable_name                   | Value                           |
+---------------------------------+---------------------------------+
| log_bin                         | ON                              |
| log_bin_basename                | /var/lib/mysql/mysql3-bin       |
| log_bin_index                   | /var/lib/mysql/mysql3-bin.index |
| log_bin_trust_function_creators | OFF                             |
| log_bin_use_v1_row_events       | OFF                             |
| sql_log_bin                     | ON                              |
+---------------------------------+---------------------------------+
6 rows in set (0.01 sec)

创建用于在主从之间复制日志的用户并授权

rs1:

[root@rs1 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> create user 'copy'@'192.168.126.%' identified by "linux123.COM";
Query OK, 0 rows affected (0.01 sec)mysql> grant replication slave on *.* to 'copy'@'192.168.126.%';
Query OK, 0 rows affected (0.01 sec)mysql> alter user 'copy'@'192.168.126.%' identified with mysql_native_password by 'linux123.COM';
Query OK, 0 rows affected (0.01 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)mysql> exit
Bye

rs2:

[root@rs2 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> create user 'copy'@'192.168.126.%' identified by "linux123.COM";
Query OK, 0 rows affected (0.01 sec)mysql> grant replication slave on *.* to 'copy'@'192.168.126.%';
Query OK, 0 rows affected (0.00 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)mysql> exit
Bye

nfs:

[root@nfs ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> create user 'copy'@'192.168.126.%' identified by "linux123.COM";
Query OK, 0 rows affected (0.00 sec)mysql> grant replication slave on *.* to 'copy'@'192.168.126.%';
Query OK, 0 rows affected (0.01 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)mysql> exit
Bye

配置一主两从

查看主库(rs1)binlog文件名及位置

[root@rs1 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show master status;
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB                                | Executed_Gtid_Set |
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
| mysql1-bin.000001 |      878 |              | information_schema,mysql,performance_schema,sys |                   |
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
1 row in set (0.00 sec)

rs2从库连接主库rs1

[root@rs2 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> change master to-> master_host='rs1', # 主库的地址(也可以是IP)-> master_user='copy',   # 在主库上创建的复制账号-> master_password='linux123.COM', # 在主库上创建的复制账号密码-> master_log_file='mysql1-bin.000001',  # 开始复制的主库上的二进制文件名(上面在rs1主机上通过show master status;语句获取到的)-> master_log_pos=878;   # 开始复制的二进制文件具体位置(同样是上面在rs1主机上通过show master status;语句获取到的)
Query OK, 0 rows affected, 2 warnings (0.01 sec)mysql> start slave;       # 开启从库
Query OK, 0 rows affected (0.00 sec)# 过段时间查看状态(通过pos的方式定位日志数据进行同步会比较慢,如果是主库数据比较多的情况可以使用mysqldump进行备份然后到从库执行,最后再使用pos方式会比较快)
mysql> show slave status\G;
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: rs1Master_User: copyMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql1-bin.000001Read_Master_Log_Pos: 878Relay_Log_File: relay2-log.000002Relay_Log_Pos: 323Relay_Master_Log_File: mysql1-bin.000001Slave_IO_Running: Yes    # I/O线程是否启动并连接服务器,一般I/O线程出现no,可能是my.cnf配置有误,出现connecting一般是指定服务器有误或用于复制的用户有误Slave_SQL_Running: Yes  # SQL线程是否启动# 当Slave_IO_Running和Slave_SQL_Running状态为YES就证明同步成功。Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 878Relay_Log_Space: 526Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 17d5bab6-1d38-11ec-a801-000c292b4805Master_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: Master_public_key_path: Get_master_public_key: 0Network_Namespace:
1 row in set (0.00 sec)# 限制从库只读((一是鉴于当前数据库架构,如果在从库上写数据,那么无法同步到其他节点;二是如果在主库和从库同时对同一数据的修改,有可能造成数据不一致等问题)
mysql> set global read_only=1;
Query OK, 0 rows affected (0.00 sec)

nfs从库连接主库rs1

[root@nfs ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> change master to-> master_host='rs1',-> master_user='copy',-> master_password='linux123.COM',-> master_log_file='mysql1-bin.000001',-> master_log_pos=878;
Query OK, 0 rows affected, 2 warnings (0.02 sec)mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: rs1Master_User: copyMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql1-bin.000001Read_Master_Log_Pos: 878Relay_Log_File: relay3-log.000002Relay_Log_Pos: 323Relay_Master_Log_File: mysql1-bin.000001Slave_IO_Running: YesSlave_SQL_Running: Yes      # 同步成功Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 878Relay_Log_Space: 526Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 17d5bab6-1d38-11ec-a801-000c292b4805Master_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: Master_public_key_path: Get_master_public_key: 0Network_Namespace:
1 row in set (0.00 sec)# 限制从库只读

主从复制验证

# rs主库上创建库和表并插入数据
[root@rs1 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 34
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> create database test;
Query OK, 1 row affected (0.00 sec)mysql> use test;
Database changed
mysql> create table test.student(id int,-> name varchar(10),-> age int);
Query OK, 0 rows affected (0.02 sec)mysql> insert test.student values (1,"zhangsan",18);
Query OK, 1 row affected (0.01 sec)
mysql> select * from test.student;
+------+----------+------+
| id   | name     | age  |
+------+----------+------+
|    1 | zhangsan |   18 |
+------+----------+------+
1 row in set (0.00 sec)# rs2从库查询验证
[root@rs2 ~]# mysql -uroot -p'mysql123.COM' -e 'select * from test.student'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------+----------+------+
| id   | name     | age  |
+------+----------+------+
|    1 | zhangsan |   18 |
+------+----------+------+# nfs从库查询验证
[root@nfs ~]# mysql -uroot -p'mysql123.COM' -e 'select * from test.student'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------+----------+------+
| id   | name     | age  |
+------+----------+------+
|    1 | zhangsan |   18 |
+------+----------+------+
# 主从复制搭建成功

开启主从之间半同步复制

主库rs1:

#查看是否支持动态安装插件
mysql> select @@have_dynamic_loading;
+------------------------+
| @@have_dynamic_loading |
+------------------------+
| YES                    |
+------------------------+
1 row in set (0.00 sec)
# show plugins; 查看是否安装semic插件
# 主库安装半同步semi插件,soname重命名
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)
# 查看配置参数(未启用)
mysql> show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | OFF        |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.00 sec)
# 开启半同步复制
mysql> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.01 sec)
#设置超时时间
mysql> set global rpl_semi_sync_master_timeout=1000;
Query OK, 0 rows affected (0.00 sec)
# 再次查看是否配置成功
mysql> show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 1000       |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.00 sec)

从库rs2:

# 查看是否支持动态安装插件
mysql> select @@have_dynamic_loading;
+------------------------+
| @@have_dynamic_loading |
+------------------------+
| YES                    |
+------------------------+
1 row in set (0.00 sec)
# 从库安装semi插件(注意,主库和从库的插件不一样,看清楚。)
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)
# 开启半同步
mysql> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.00 sec)
# 查看是否配置成功
mysql> show variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.01 sec)
# 重启slave
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status \G;
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: rs1Master_User: copyMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql1-bin.000002Read_Master_Log_Pos: 155Relay_Log_File: relay2-log.000006Relay_Log_Pos: 323Relay_Master_Log_File: mysql1-bin.000002Slave_IO_Running: YesSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 155Relay_Log_Space: 742Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 17d5bab6-1d38-11ec-a801-000c292b4805Master_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: Master_public_key_path: Get_master_public_key: 0Network_Namespace:
1 row in set (0.00 sec)

nfs从库:

mysql> select @@have_dynamic_loading;
+------------------------+
| @@have_dynamic_loading |
+------------------------+
| YES                    |
+------------------------+
1 row in set (0.00 sec)mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)mysql> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.00 sec)mysql> show variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.01 sec)mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: rs1Master_User: copyMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql1-bin.000002Read_Master_Log_Pos: 155Relay_Log_File: relay3-log.000006Relay_Log_Pos: 323Relay_Master_Log_File: mysql1-bin.000002Slave_IO_Running: YesSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 155Relay_Log_Space: 742Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 17d5bab6-1d38-11ec-a801-000c292b4805Master_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: Master_public_key_path: Get_master_public_key: 0Network_Namespace:
1 row in set (0.00 sec)

配置MHA

配置公钥免密登录

[root@rs1 ~]# ssh-keygen -t dsa -f ~/.ssh/id_dsa -P ""
[root@rs1 ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@rs2
[root@rs1 ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@nfs
[root@rs1 ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@mha-manager[root@rs2 ~]# ssh-keygen -t dsa -f ~/.ssh/id_dsa -P ""
[root@rs2 ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@rs1
[root@rs2 ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@nfs
[root@rs2 ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@mha-manager[root@nfs ~]# ssh-keygen -t dsa -f ~/.ssh/id_dsa -P ""
[root@nfs ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@rs1
[root@nfs ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@rs2
[root@nfs ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@mha-manager[root@mha-manager ~]# ssh-keygen -t dsa -f ~/.ssh/id_dsa -P ""
[root@mha-manager ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@rs1
[root@mha-manager ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@rs2
[root@mha-manager ~]# sshpass -p 123 ssh-copy-id -o StrictHostKeyChecking=no root@nfs

在所有mysql服务器上创建MHA管理账号“mha”并授权

rs1:

[root@rs1 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> create user 'mha'@'192.168.126.%' identified by "linux123.COM";
Query OK, 0 rows affected (0.01 sec)mysql> alter user 'mha'@'192.168.126.%' identified with mysql_native_password by 'linux123.COM';
Query OK, 0 rows affected (0.00 sec)mysql> grant all on *.* to 'mha'@'192.168.126.%';
Query OK, 0 rows affected (0.00 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)mysql> exit
Bye

rs2和nfs节点由于是rs1的从库,那么mha用户也就同时在两个从库上创建了

四台服务器同时安装node节点

rs1:

[root@rs1 ~]# ls
mha4mysql-node-0.57.tar.gz
[root@rs1 ~]# mkdir /usr/local/mha-node
# 解压
[root@rs1 ~]# tar -xf mha4mysql-node-0.57.tar.gz -C /usr/local/mha-node
# 安装所需依赖包
[root@rs1 ~]# yum install -y perl-DBD-MySQL \
> perl-Config-Tiny \
> perl-Log-Dispatch \
> perl-Parallel-ForkManager \
> perl-ExtUtils-CBuilder \
> perl-ExtUtils-MakeMaker \
> perl-CPAN
# 安装mha-node
[root@rs1 ~]# cd /usr/local/mha-node/mha4mysql-node-0.57/
[root@rs1 mha4mysql-node-0.57]# perl Makefile.PL
*** Module::AutoInstall version 1.06
*** Checking for Perl dependencies...
[Core Features]
- DBI        ...loaded. (1.627)
- DBD::mysql ...loaded. (4.023)
*** Module::AutoInstall configuration finished.
Checking if your kit is complete...
Looks good
Writing Makefile for mha4mysql::node[root@rs1 mha4mysql-node-0.57]# make
cp lib/MHA/BinlogManager.pm blib/lib/MHA/BinlogManager.pm
cp lib/MHA/BinlogPosFindManager.pm blib/lib/MHA/BinlogPosFindManager.pm
cp lib/MHA/BinlogPosFinderXid.pm blib/lib/MHA/BinlogPosFinderXid.pm
cp lib/MHA/BinlogHeaderParser.pm blib/lib/MHA/BinlogHeaderParser.pm
cp lib/MHA/BinlogPosFinder.pm blib/lib/MHA/BinlogPosFinder.pm
cp lib/MHA/NodeUtil.pm blib/lib/MHA/NodeUtil.pm
cp lib/MHA/BinlogPosFinderElp.pm blib/lib/MHA/BinlogPosFinderElp.pm
cp lib/MHA/SlaveUtil.pm blib/lib/MHA/SlaveUtil.pm
cp lib/MHA/NodeConst.pm blib/lib/MHA/NodeConst.pm
cp bin/filter_mysqlbinlog blib/script/filter_mysqlbinlog
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/filter_mysqlbinlog
cp bin/apply_diff_relay_logs blib/script/apply_diff_relay_logs
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/apply_diff_relay_logs
cp bin/purge_relay_logs blib/script/purge_relay_logs
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/purge_relay_logs
cp bin/save_binary_logs blib/script/save_binary_logs
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/save_binary_logs
Manifying blib/man1/filter_mysqlbinlog.1
Manifying blib/man1/apply_diff_relay_logs.1
Manifying blib/man1/purge_relay_logs.1
Manifying blib/man1/save_binary_logs.1[root@rs1 mha4mysql-node-0.57]# make install
Installing /usr/local/share/perl5/MHA/BinlogManager.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFindManager.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFinderXid.pm
Installing /usr/local/share/perl5/MHA/BinlogHeaderParser.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFinder.pm
Installing /usr/local/share/perl5/MHA/NodeUtil.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFinderElp.pm
Installing /usr/local/share/perl5/MHA/SlaveUtil.pm
Installing /usr/local/share/perl5/MHA/NodeConst.pm
Installing /usr/local/share/man/man1/filter_mysqlbinlog.1
Installing /usr/local/share/man/man1/apply_diff_relay_logs.1
Installing /usr/local/share/man/man1/purge_relay_logs.1
Installing /usr/local/share/man/man1/save_binary_logs.1
Installing /usr/local/bin/filter_mysqlbinlog
Installing /usr/local/bin/apply_diff_relay_logs
Installing /usr/local/bin/purge_relay_logs
Installing /usr/local/bin/save_binary_logs# node组件安装后在bin下面会生成几个工具(这些工具通常由 MHAManager 的脚本触发,无需人为操作)
[root@rs1 mha4mysql-node-0.57]# ll bin
total 44
-rwxr-xr-x. 1 1001 1001 16381 May 31  2015 apply_diff_relay_logs
-rwxr-xr-x. 1 1001 1001  4807 May 31  2015 filter_mysqlbinlog
-rwxr-xr-x. 1 1001 1001  8261 May 31  2015 purge_relay_logs
-rwxr-xr-x. 1 1001 1001  7525 May 31  2015 save_binary_logs
# 同时会复制到 /usr/local/bin下
[root@rs1 mha4mysql-node-0.57]# ls /usr/local/bin
apply_diff_relay_logs  filter_mysqlbinlog  purge_relay_logs  save_binary_logs

rs2:

[root@rs2 ~]# mkdir /usr/local/mha-node
[root@rs2 ~]# tar -xf mha4mysql-node-0.57.tar.gz -C /usr/local/mha-node
[root@rs2 ~]# yum install -y perl-DBD-MySQL \
> perl-Config-Tiny \
> perl-Log-Dispatch \
> perl-Parallel-ForkManager \
> perl-ExtUtils-CBuilder \
> perl-ExtUtils-MakeMaker \
> perl-CPAN
[root@rs2 ~]# cd /usr/local/mha-node/mha4mysql-node-0.57/
[root@rs2 mha4mysql-node-0.57]# perl Makefile.PL
[root@rs2 mha4mysql-node-0.57]# make && make install

nfs:

[root@nfs ~]# mkdir /usr/local/mha-node
[root@nfs ~]# tar -xf mha4mysql-node-0.57.tar.gz -C /usr/local/mha-node
[root@nfs ~]# yum install -y perl-DBD-MySQL \
> perl-Config-Tiny \
> perl-Log-Dispatch \
> perl-Parallel-ForkManager \
> perl-ExtUtils-CBuilder \
> perl-ExtUtils-MakeMaker \
> perl-CPAN
[root@nfs ~]# cd /usr/local/mha-node/mha4mysql-node-0.57/
[root@nfs mha4mysql-node-0.57]# perl Makefile.PL
[root@nfs mha4mysql-node-0.57]# make && make install

mha-manager:

[root@mha-manager ~]# ls
mha4mysql-node-0.57.tar.gz
[root@mha-manager mha]# mkdir /usr/local/mha-node
[root@mha-manager mha]# tar -xf mha4mysql-node-0.57.tar.gz -C /usr/local/mha-node
[root@mha-manager ~]# yum install -y perl-DBD-MySQL \ # 需要epel源
> perl-Config-Tiny \
> perl-ExtUtils-CBuilder \
> perl-Log-Dispatch \
> perl-Parallel-ForkManager \
> perl-ExtUtils-MakeMaker \
> perl-CPAN
[root@mha-manager ~]# cd /usr/local/mha-node/mha4mysql-node-0.57/
[root@mha-manager mha4mysql-node-0.57]# perl Makefile.PL
[root@mha-manager mha4mysql-node-0.57]# make
[root@mha-manager mha4mysql-node-0.57]# make install

mha-manager节点同时安装并配置MHA

[root@mha-manager ~]# ls
mha4mysql-manager-0.57.tar.gz
[root@mha-manager ~]# mkdir /usr/local/mha-manager
[root@mha-manager ~]# tar xf mha4mysql-manager-0.57.tar.gz -C /usr/local/mha-manager
[root@mha-manager ~]# cd /usr/local/mha-manager/mha4mysql-manager-0.57/
[root@mha-manager mha4mysql-manager-0.57]# perl Makefile.PL
*** Module::AutoInstall version 1.06
*** Checking for Perl dependencies...
[Core Features]
- DBI                   ...loaded. (1.627)
- DBD::mysql            ...loaded. (4.023)
- Time::HiRes           ...loaded. (1.9725)
- Config::Tiny          ...loaded. (2.14)
- Log::Dispatch         ...missing.
- Parallel::ForkManager ...missing.
- MHA::NodeConst        ...loaded. (0.57)
==> Auto-install the 2 mandatory module(s) from CPAN? [y] y
*** Dependencies will be installed the next time you type 'make'.
*** Module::AutoInstall configuration finished.
Checking if your kit is complete...
Looks good
Warning: prerequisite Log::Dispatch 0 not found.
Warning: prerequisite Parallel::ForkManager 0 not found.
Writing Makefile for mha4mysql::manager[root@mha-manager mha4mysql-manager-0.57]# make && make install
# 时间比较长# manager组件安装后在/usr/local/bin下面会生成几个工具
[root@mha-manager mha4mysql-manager-0.57]# ll bin
total 40
-rwxr-xr-x. 1 1001 1001 1995 May 31  2015 masterha_check_repl   # 检查 MySQL 复制状况
-rwxr-xr-x. 1 1001 1001 1779 May 31  2015 masterha_check_ssh    # 检查 MHA 的 SSH 配置状况
-rwxr-xr-x. 1 1001 1001 1865 May 31  2015 masterha_check_status # 检测当前 MHA 运行状态
-rwxr-xr-x. 1 1001 1001 3201 May 31  2015 masterha_conf_host    # 添加或删除配置的 server 信息
-rwxr-xr-x. 1 1001 1001 2517 May 31  2015 masterha_manager      # 启动 manager的脚本
-rwxr-xr-x. 1 1001 1001 2165 May 31  2015 masterha_master_monitor   # 检测 master 是否宕机
-rwxr-xr-x. 1 1001 1001 2373 May 31  2015 masterha_master_switch    # 控制故障转移(自动或者手动)
-rwxr-xr-x. 1 1001 1001 5171 May 31  2015 masterha_secondary_check  # 当MHA manager检测到master不可用时,通过masterha_secondary_check脚本来进一步确认,减低误切的风险。
-rwxr-xr-x. 1 1001 1001 1739 May 31  2015 masterha_stop     # 关闭manager
# 复制上述所有脚本到/usr/local/bin 目录下
[root@mha-manager ~]# cp /usr/local/mha-manager/mha4mysql-manager-0.57/bin/* /usr/local/bin/# 另有如下几个需自定义的脚本:
[root@mha-manager mha4mysql-manager-0.57]# ll samples/scripts/
total 32
-rwxr-xr-x. 1 1001 1001  3648 May 31  2015 master_ip_failover   # 自动切换时 VIP 管理的脚本
-rwxr-xr-x. 1 1001 1001  9870 May 31  2015 master_ip_online_change      # 在线切换时 vip 的管理
-rwxr-xr-x. 1 1001 1001 11867 May 31  2015 power_manager        # 故障发生后关闭主机的脚本
-rwxr-xr-x. 1 1001 1001  1360 May 31  2015 send_report      # 因故障切换后发送报警的脚本# 复制上述所有脚本到/usr/local/bin 目录下
[root@mha-manager mha4mysql-manager-0.57]# cp samples/scripts/* /usr/local/bin/# VIP配置可以采用两种方式,一是通过引入Keepalived来管理VIP,另一种是在上面脚本中手动配置管理。
# 对于keepalived管理VIP,存在脑裂情况,即当主从网络出现问题时,slave会抢占VIP,这样会导致主从数据库都持有VIP,造成IP冲突,所以在网络不是很好的情况下,不建议采用keepalived服务。
# 在实际生产中使用较多的也是第二种,即在脚本中手动管理VIP,所以,对keepalived不感兴趣的童鞋可直接跳过第一种方式。
# 官方对于master_ip_failover,master_ip_online_change,send_report脚本,给出的只是sample,切换的逻辑需要自己定义。
# 修改master_ip_failover脚本,该脚本主要作用是用于自动主从故障切换和VIP的漂移(没有使用 keepalived ,通过脚本的方式管理vip。)
[root@mha-manager mha4mysql-manager-0.57]# vim /usr/local/bin/master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';use Getopt::Long;my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);my $vip = '192.168.126.200/24';    #指定vip的地址
my $ifdev = 'ens32';           #指定vip绑定的网卡
my $key = '1';                 #指定vip绑定的虚拟网卡序列号
my $ssh_start_vip = "/sbin/ifconfig $ifdev:$key $vip"; #代表此变量值为ifconfig ens32:1 192.168.126.200
my $ssh_stop_vip = "/sbin/ifconfig $ifdev:$key down";  #代表此变量值为ifconfig ens32:1 192.168.126.200 down
my $exit_code = 0;GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);exit &main();sub main {print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";if ( $command eq "stop" || $command eq "stopssh" ) {my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
exit 0;
}
else {
&usage();
exit 1;
}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
## A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}# 修改master_ip_online_change脚本,该脚本主要作用是用于在线手动主从切换和VIP的漂移(多用于诸如硬件升级,MySQL数据库迁移等等)[root@mha-manager ~]# vim /usr/local/bin/master_ip_online_change
#!/usr/bin/env perluse strict;
use warnings FATAL => 'all';use Getopt::Long;
use MHA::DBHelper;
use MHA::NodeUtil;
use Time::HiRes qw( sleep gettimeofday tv_interval );
use Data::Dumper;my $vip = '192.168.126.200/24';  # Virtual IP
my $ifdev = 'ens32';
my $key = "1";
my $ssh_start_vip = "/usr/sbin/ifconfig $ifdev:$key $vip";
my $ssh_stop_vip = "/usr/sbin/ifconfig $ifdev:$key down";
my $exit_code = 0;
my $_tstart;
my $_running_interval = 0.1;
my ($command,              $orig_master_is_new_slave, $orig_master_host,$orig_master_ip,       $orig_master_port,         $orig_master_user,$orig_master_password, $orig_master_ssh_user,     $new_master_host,$new_master_ip,        $new_master_port,          $new_master_user,$new_master_password,  $new_master_ssh_user,
);
GetOptions('command=s'                => \$command,'orig_master_is_new_slave' => \$orig_master_is_new_slave,'orig_master_host=s'       => \$orig_master_host,'orig_master_ip=s'         => \$orig_master_ip,'orig_master_port=i'       => \$orig_master_port,'orig_master_user=s'       => \$orig_master_user,'orig_master_password=s'   => \$orig_master_password,'orig_master_ssh_user=s'   => \$orig_master_ssh_user,'new_master_host=s'        => \$new_master_host,'new_master_ip=s'          => \$new_master_ip,'new_master_port=i'        => \$new_master_port,'new_master_user=s'        => \$new_master_user,'new_master_password=s'    => \$new_master_password,'new_master_ssh_user=s'    => \$new_master_ssh_user,
);exit &main();sub current_time_us {my ( $sec, $microsec ) = gettimeofday();my $curdate = localtime($sec);return $curdate . " " . sprintf( "%06d", $microsec );
}sub sleep_until {my $elapsed = tv_interval($_tstart);if ( $_running_interval > $elapsed ) {sleep( $_running_interval - $elapsed );}
}sub get_threads_util {my $dbh                    = shift;my $my_connection_id       = shift;my $running_time_threshold = shift;my $type                   = shift;$running_time_threshold = 0 unless ($running_time_threshold);$type                   = 0 unless ($type);my @threads;my $sth = $dbh->prepare("SHOW PROCESSLIST");$sth->execute();while ( my $ref = $sth->fetchrow_hashref() ) {my $id         = $ref->{Id};my $user       = $ref->{User};my $host       = $ref->{Host};my $command    = $ref->{Command};my $state      = $ref->{State};my $query_time = $ref->{Time};my $info       = $ref->{Info};$info =~ s/^\s*(.*?)\s*$/$1/ if defined($info);next if ( $my_connection_id == $id );next if ( defined($query_time) && $query_time < $running_time_threshold );next if ( defined($command)    && $command eq "Binlog Dump" );next if ( defined($user)       && $user eq "system user" );nextif ( defined($command)&& $command eq "Sleep"&& defined($query_time)&& $query_time >= 1 );if ( $type >= 1 ) {next if ( defined($command) && $command eq "Sleep" );next if ( defined($command) && $command eq "Connect" );}if ( $type >= 2 ) {next if ( defined($info) && $info =~ m/^select/i );next if ( defined($info) && $info =~ m/^show/i );}push @threads, $ref;}return @threads;
}sub main {if ( $command eq "stop" ) {## Gracefully killing connections on the current master# 1. Set read_only= 1 on the new master# 2. DROP USER so that no app user can establish new connections# 3. Set read_only= 1 on the current master# 4. Kill current queries# * Any database access failure will result in script die.my $exit_code = 1;eval {## Setting read_only=1 on the new master (to avoid accident)my $new_master_handler = new MHA::DBHelper();# args: hostname, port, user, password, raise_error(die_on_error)_or_not$new_master_handler->connect( $new_master_ip, $new_master_port,$new_master_user, $new_master_password, 1 );print current_time_us() . " Set read_only on the new master.. ";$new_master_handler->enable_read_only();if ( $new_master_handler->is_read_only() ) {print "ok.\n";}else {die "Failed!\n";}$new_master_handler->disconnect();# Connecting to the orig master, die if any database error happensmy $orig_master_handler = new MHA::DBHelper();$orig_master_handler->connect( $orig_master_ip, $orig_master_port,$orig_master_user, $orig_master_password, 1 );## Drop application user so that nobody can connect. Disabling per-session binlog beforehand$orig_master_handler->disable_log_bin_local();print current_time_us() . " Drpping app user on the orig master..\n";FIXME_xxx_drop_app_user($orig_master_handler);## Waiting for N * 100 milliseconds so that current connections can exitmy $time_until_read_only = 15;$_tstart = [gettimeofday];my @threads = get_threads_util( $orig_master_handler->{dbh},$orig_master_handler->{connection_id} );while ( $time_until_read_only > 0 && $#threads >= 0 ) {if ( $time_until_read_only % 5 == 0 ) {printf
"%s Waiting all running %d threads are disconnected.. (max %d milliseconds)\n",current_time_us(), $#threads + 1, $time_until_read_only * 100;if ( $#threads < 5 ) {print Data::Dumper->new( [$_] )->Indent(0)->Terse(1)->Dump . "\n"foreach (@threads);}}sleep_until();$_tstart = [gettimeofday];$time_until_read_only--;@threads = get_threads_util( $orig_master_handler->{dbh},$orig_master_handler->{connection_id} );}## Setting read_only=1 on the current master so that nobody(except SUPER) can writeprint current_time_us() . " Set read_only=1 on the orig master.. ";$orig_master_handler->enable_read_only();if ( $orig_master_handler->is_read_only() ) {print "ok.\n";}else {die "Failed!\n";}## Waiting for M * 100 milliseconds so that current update queries can completemy $time_until_kill_threads = 5;@threads = get_threads_util( $orig_master_handler->{dbh},$orig_master_handler->{connection_id} );while ( $time_until_kill_threads > 0 && $#threads >= 0 ) {if ( $time_until_kill_threads % 5 == 0 ) {printf
"%s Waiting all running %d queries are disconnected.. (max %d milliseconds)\n",current_time_us(), $#threads + 1, $time_until_kill_threads * 100;if ( $#threads < 5 ) {print Data::Dumper->new( [$_] )->Indent(0)->Terse(1)->Dump . "\n"foreach (@threads);}}sleep_until();$_tstart = [gettimeofday];$time_until_kill_threads--;@threads = get_threads_util( $orig_master_handler->{dbh},$orig_master_handler->{connection_id} );}## Terminating all threadsprint current_time_us() . " Killing all application threads..\n";$orig_master_handler->kill_threads(@threads) if ( $#threads >= 0 );print current_time_us() . " done.\n";$orig_master_handler->enable_log_bin_local();$orig_master_handler->disconnect();## After finishing the script, MHA executes FLUSH TABLES WITH READ LOCK$exit_code = 0;};if ($@) {warn "Got Error: $@\n";exit $exit_code;}exit $exit_code;}elsif ( $command eq "start" ) {## Activating master ip on the new master# 1. Create app user with write privileges# 2. Moving backup script if needed# 3. Register new master's ip to the catalog database# We don't return error even though activating updatable accounts/ip failed so that we don't interrupt slaves' recovery.
# If exit code is 0 or 10, MHA does not abortmy $exit_code = 10;eval {my $new_master_handler = new MHA::DBHelper();# args: hostname, port, user, password, raise_error_or_not$new_master_handler->connect( $new_master_ip, $new_master_port,$new_master_user, $new_master_password, 1 );## Set read_only=0 on the new master$new_master_handler->disable_log_bin_local();print current_time_us() . " Set read_only=0 on the new master.\n";$new_master_handler->disable_read_only();## Creating an app user on the new masterprint current_time_us() . " Creating app user on the new master..\n";FIXME_xxx_create_app_user($new_master_handler);$new_master_handler->enable_log_bin_local();$new_master_handler->disconnect();## Update master ip on the catalog database, etc$exit_code = 0;};if ($@) {warn "Got Error: $@\n";exit $exit_code;}exit $exit_code;}elsif ( $command eq "status" ) {# do nothingexit 0;}else {&usage();exit 1;}
}sub usage {print
"Usage: master_ip_online_change --command=start|stop|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";die;
}
# master_ip_online_change_script 指的是手动执行mysql master switchover时执行的切换脚本
# 一般用法: masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=192.168.8.57 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000# 创建 MHA 工作目录并复制配置文件,使用app1.cnf配置文件来管理 mysql 节点服务器,配置文件一般放在/etc/目录下
[root@mha-manager mha4mysql-manager-0.57]# mkdir /etc/masterha
[root@mha-manager mha4mysql-manager-0.57]# cp samples/conf/app1.cnf /etc/masterha/
# 删除原有内容,直接复制并修改节点服务器的IP地址
[root@mha-manager mha4mysql-manager-0.57]# vim /etc/masterha/app1.cnf
[server default]
manager_log=/var/log/masterha/app1/manager.log    #manager日志
manager_workdir=/var/log/masterha/app1.log      #manager工作目录
master_binlog_dir=/var/lib/mysql/            #master保存binlog的位置,这里的路径要与master里配置的binlog的路径一致,以便MHA能找到
master_ip_failover_script=/usr/local/bin/master_ip_failover            #设置自动failover时候的切换脚本,也就是上面的那个脚本
master_ip_online_change_script=/usr/local/bin/master_ip_online_change  #设置手动在线切换的脚本
user=mha                                #设置监控用户名
password=linux123.COM                   #设置mysql中用于监控mha用户的那个密码
ping_interval=1                         #设置监控主库,发送ping包的时间间隔1秒,默认是3秒,尝试三次没有回应的时候自动进行failover
remote_workdir=/tmp/        #设置远端mysql在发生切换时binlog的保存位置
repl_user=copy                          #设置mysql中用于主从复制的用户名
repl_password=linux123.COM              #设置mysql中用于主从复制的用户的密码
report_script=/usr/local/bin/send_report     #设置发生切换后发送的报警的脚本
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.126.93 -s 192.168.126.94      #指定检查的从服务器IP地址
shutdown_script=""                      #设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机防止发生脑裂,这里没有使用)
ssh_user=root                           #设置ssh的登录用户名[server1]
hostname=rs1
port=3306[server2]
hostname=rs2
port=3306
candidate_master=1
#设置为候选master,设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中最新的slavecheck_repl_delay=0
#默认情况下如果一个slave落后master 超过100M的relay logs的话,MHA将不会选择该slave作为一个新的master, 因为对于这个slave的恢复需要花费很长时间;通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将
会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master[server3]
hostname=nfs
port=3306# 在主库rs服务器上手动开启vip
[root@rs1 mha4mysql-node-0.57]# ifconfig ens32:1 192.168.126.200/24# 在 mha-manager 节点上测试 ssh 无密码认证,如果正常最后会输出 successfully。
[root@mha-manager mha4mysql-manager-0.57]# masterha_check_ssh -conf=/etc/masterha/app1.cnf
Sat Sep 25 15:47:10 2021 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sat Sep 25 15:47:10 2021 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Sat Sep 25 15:47:10 2021 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Sat Sep 25 15:47:10 2021 - [info] Starting SSH connection tests..
Sat Sep 25 15:47:12 2021 - [debug]
Sat Sep 25 15:47:10 2021 - [debug]  Connecting via SSH from root@192.168.126.92(192.168.126.92:22) to root@192.168.126.93(192.168.126.93:22)..
Sat Sep 25 15:47:11 2021 - [debug]   ok.
Sat Sep 25 15:47:11 2021 - [debug]  Connecting via SSH from root@192.168.126.92(192.168.126.92:22) to root@192.168.126.94(192.168.126.94:22)..
Sat Sep 25 15:47:11 2021 - [debug]   ok.
Sat Sep 25 15:47:13 2021 - [debug]
Sat Sep 25 15:47:11 2021 - [debug]  Connecting via SSH from root@192.168.126.93(192.168.126.93:22) to root@192.168.126.92(192.168.126.92:22)..
Sat Sep 25 15:47:11 2021 - [debug]   ok.
Sat Sep 25 15:47:11 2021 - [debug]  Connecting via SSH from root@192.168.126.93(192.168.126.93:22) to root@192.168.126.94(192.168.126.94:22)..
Sat Sep 25 15:47:12 2021 - [debug]   ok.
Sat Sep 25 15:47:13 2021 - [debug]
Sat Sep 25 15:47:11 2021 - [debug]  Connecting via SSH from root@192.168.126.94(192.168.126.94:22) to root@192.168.126.92(192.168.126.92:22)..
Sat Sep 25 15:47:12 2021 - [debug]   ok.
Sat Sep 25 15:47:12 2021 - [debug]  Connecting via SSH from root@192.168.126.94(192.168.126.94:22) to root@192.168.126.93(192.168.126.93:22)..
Sat Sep 25 15:47:12 2021 - [debug]   ok.
Sat Sep 25 15:47:13 2021 - [info] All SSH connection tests passed successfully.
# 如果上面出现Can't locate MHA/SSHCheck.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at bin/masterha_check_ssh line 25.
# BEGIN failed--compilation aborted at bin/masterha_check_ssh line 25.问题,则解决方法为:
#[root@mha-manager mha4mysql-manager-0.57]# find / -name SSHCheck.pm
#/usr/local/mha-manager/mha4mysql-manager-0.57/lib/MHA/SSHCheck.pm
#/usr/local/mha-manager/mha4mysql-manager-0.57/blib/lib/MHA/SSHCheck.pm
#[root@mha-manager mha4mysql-manager-0.57]# export PERL5LIB=$PERL5LIB:/usr/local/mha-manager#/mha4mysql-manager-0.57/lib/
#[root@mha-manager mha4mysql-manager-0.57]# export PERL5LIB=$PERL5LIB:/usr/local/mha-manager#/mha4mysql-manager-0.57/blib/lib/
# 或者写入/etc/profile文件中# 在 manager 节点上测试 mysql 主从连接情况,最后出现 MySQL Replication Health is OK 字样说明正常。
[root@mha-manager mha4mysql-manager-0.57]# masterha_check_repl -conf=/etc/masterha/app1.cnf
Sat Sep 25 16:06:34 2021 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sat Sep 25 16:06:34 2021 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Sat Sep 25 16:06:34 2021 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Sat Sep 25 16:06:34 2021 - [info] MHA::MasterMonitor version 0.57.
Sat Sep 25 16:06:35 2021 - [info] GTID failover mode = 0
Sat Sep 25 16:06:35 2021 - [info] Dead Servers:
Sat Sep 25 16:06:35 2021 - [info] Alive Servers:
Sat Sep 25 16:06:35 2021 - [info]   rs1(192.168.126.92:3306)
Sat Sep 25 16:06:35 2021 - [info]   rs2(192.168.126.93:3306)
Sat Sep 25 16:06:35 2021 - [info]   nfs(192.168.126.94:3306)
Sat Sep 25 16:06:35 2021 - [info] Alive Slaves:
Sat Sep 25 16:06:35 2021 - [info]   rs2(192.168.126.93:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sat Sep 25 16:06:35 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sat Sep 25 16:06:35 2021 - [info]     Primary candidate for the new Master (candidate_master is set)
Sat Sep 25 16:06:35 2021 - [info]   nfs(192.168.126.94:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sat Sep 25 16:06:35 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sat Sep 25 16:06:35 2021 - [info] Current Alive Master: rs1(192.168.126.92:3306)
Sat Sep 25 16:06:35 2021 - [info] Checking slave configurations..
Sat Sep 25 16:06:35 2021 - [info]  read_only=1 is not set on slave rs2(192.168.126.93:3306).
Sat Sep 25 16:06:35 2021 - [warning]  relay_log_purge=0 is not set on slave rs2(192.168.126.93:3306).
Sat Sep 25 16:06:35 2021 - [info]  read_only=1 is not set on slave nfs(192.168.126.94:3306).
Sat Sep 25 16:06:35 2021 - [warning]  relay_log_purge=0 is not set on slave nfs(192.168.126.94:3306).
Sat Sep 25 16:06:35 2021 - [info] Checking replication filtering settings..
Sat Sep 25 16:06:35 2021 - [info]  binlog_do_db= , binlog_ignore_db= information_schema,mysql,performance_schema,sys
Sat Sep 25 16:06:35 2021 - [info]  Replication filtering check ok.
Sat Sep 25 16:06:35 2021 - [info] GTID (with auto-pos) is not supported
Sat Sep 25 16:06:35 2021 - [info] Starting SSH connection tests..
Sat Sep 25 16:06:38 2021 - [info] All SSH connection tests passed successfully.
Sat Sep 25 16:06:38 2021 - [info] Checking MHA Node version..
Sat Sep 25 16:06:38 2021 - [info]  Version check ok.
Sat Sep 25 16:06:38 2021 - [info] Checking SSH publickey authentication settings on the current master..
Sat Sep 25 16:06:38 2021 - [info] HealthCheck: SSH to rs1 is reachable.
Sat Sep 25 16:06:39 2021 - [info] Master MHA Node version is 0.57.
Sat Sep 25 16:06:39 2021 - [info] Checking recovery script configurations on rs1(192.168.126.92:3306)..
Sat Sep 25 16:06:39 2021 - [info]   Executing command: save_binary_logs --command=test --start_pos=4 --binlog_dir=/var/lib/mysql/ --output_file=/tmp/save_binary_logs_test --manager_version=0.57 --start_file=mysql1-bin.000002
Sat Sep 25 16:06:39 2021 - [info]   Connecting to root@192.168.126.92(rs1:22).. Creating /tmp if not exists..    ok.Checking output directory is accessible or not..ok.Binlog found at /var/lib/mysql/, up to mysql1-bin.000002
Sat Sep 25 16:06:39 2021 - [info] Binlog setting check done.
Sat Sep 25 16:06:39 2021 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers..
Sat Sep 25 16:06:39 2021 - [info]   Executing command : apply_diff_relay_logs --command=test --slave_user='mha' --slave_host=rs2 --slave_ip=192.168.126.93 --slave_port=3306 --workdir=/tmp --target_version=8.0.16 --manager_version=0.57 --relay_dir=/var/lib/mysql --current_relay_log=relay2-log.000006  --slave_pass=xxx
Sat Sep 25 16:06:39 2021 - [info]   Connecting to root@192.168.126.93(rs2:22).. Checking slave recovery environment settings..Relay log found at /var/lib/mysql, up to relay2-log.000006Temporary relay log file is /var/lib/mysql/relay2-log.000006Testing mysql connection and privileges..mysql: [Warning] Using a password on the command line interface can be insecure.done.Testing mysqlbinlog output.. done.Cleaning up test file(s).. done.
Sat Sep 25 16:06:39 2021 - [info]   Executing command : apply_diff_relay_logs --command=test --slave_user='mha' --slave_host=nfs --slave_ip=192.168.126.94 --slave_port=3306 --workdir=/tmp --target_version=8.0.16 --manager_version=0.57 --relay_dir=/var/lib/mysql --current_relay_log=relay3-log.000006  --slave_pass=xxx
Sat Sep 25 16:06:39 2021 - [info]   Connecting to root@192.168.126.94(nfs:22).. Checking slave recovery environment settings..Relay log found at /var/lib/mysql, up to relay3-log.000006Temporary relay log file is /var/lib/mysql/relay3-log.000006Testing mysql connection and privileges..mysql: [Warning] Using a password on the command line interface can be insecure.done.Testing mysqlbinlog output.. done.Cleaning up test file(s).. done.
Sat Sep 25 16:06:40 2021 - [info] Slaves settings check done.
Sat Sep 25 16:06:40 2021 - [info]
rs1(192.168.126.92:3306) (current master)+--rs2(192.168.126.93:3306)+--nfs(192.168.126.94:3306)Sat Sep 25 16:06:40 2021 - [info] Checking replication health on rs2..
Sat Sep 25 16:06:40 2021 - [info]  ok.
Sat Sep 25 16:06:40 2021 - [info] Checking replication health on nfs..
Sat Sep 25 16:06:40 2021 - [info]  ok.
Sat Sep 25 16:06:40 2021 - [info] Checking master_ip_failover_script status:
Sat Sep 25 16:06:40 2021 - [info]   /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=rs1 --orig_master_ip=192.168.126.92 --orig_master_port=3306 IN SCRIPT TEST====/sbin/ifconfig ens32:1 down==/sbin/ifconfig ens32:1 192.168.126.200===Checking the Status of the script.. OK
Sat Sep 25 16:06:40 2021 - [info]  OK.
Sat Sep 25 16:06:40 2021 - [warning] shutdown_script is not defined.
Sat Sep 25 16:06:40 2021 - [info] Got exit code 0 (Not master dead).MySQL Replication Health is OK.   # 在 mha-manager 节点上启动 MHA
[root@mha-manager masterha]# nohup masterha_manager --conf=/etc/masterha/app1.cnf > /etc/masterha/mha.log  < /dev/null 2>&1 &
[1] 16524# --remove_dead_master_conf  该参数代表当发生主从切换后,老的主库的 ip 将会从配置文件中移除。
# --ignore_last_failover:在缺省情况下,如果 MHA 检测到连续发生宕机,且两次宕机间隔不足 8 小时的话,则不会进行 Failover, 之所以这样限制是为了避免 ping-pong 效应。该参数代表忽略上次 MHA 触发切换产生的文件,默认情况下,MHA 发生切换后会在日志记目录,也就是上面设置的日志app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为–ignore_last_failover。
# 关闭 manager 服务: bin/masterha_stop --conf=/etc/masterha/app1.cnf# 查看 MHA 状态,可以看到当前的 master 是 rs1 节点。
[root@mha-manager masterha]# masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:16524) is running(0:PING_OK), master:rs1
# 查看 MHA 日志,也以看到当前的 master 是 rs1(192.168.168.92)
[root@mha-manager masterha]# cat /etc/masterha/mha.log | grep "current master"
Sun Sep 26 13:04:53 2021 - [info] Checking SSH publickey authentication settings on the current master..
rs1(192.168.126.92:3306) (current master)# 查看 rs1 的 VIP 地址 192.168.126.200 是否存在,这个 VIP 地址不会因为 manager 节点停止 MHA 服务而消失。
[root@rs1 mha4mysql-node-0.57]# ip a | grep 192.168.126.200inet 192.168.126.200/24 brd 192.168.126.255 scope global secondary ens32:1

故障模拟

# 在 mha-manager 节点上监控观察日志记录
[root@mha-manager mha4mysql-manager-0.57]# tailf /etc/masterha/mha.log# 在 rs1 节点停止mysql服务
[root@rs1 ~]# systemctl stop mysqld[root@mha-manager mha4mysql-manager-0.57]# tailf /etc/masterha/mha.log# 查看日志信息
[root@mha-manager mha4mysql-manager-0.57]# tailf /etc/masterha/mha.logIN SCRIPT TEST====/usr/sbin/ifconfig ens32:1 down==/usr/sbin/ifconfig ens32:1 192.168.126.200/24===Checking the Status of the script.. OK
Sun Sep 26 13:04:54 2021 - [info]  OK.
Sun Sep 26 13:04:54 2021 - [warning] shutdown_script is not defined.
Sun Sep 26 13:04:54 2021 - [info] Set master ping interval 1 seconds.
Sun Sep 26 13:04:54 2021 - [info] Set secondary check script: /usr/local/bin/masterha_secondary_check -s 192.168.126.93 -s 192.168.126.94
Sun Sep 26 13:04:54 2021 - [info] Starting ping health check on rs1(192.168.126.92:3306)..
Sun Sep 26 13:04:54 2021 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..Sun Sep 26 13:06:14 2021 - [warning] Got error on MySQL select ping: 2006 (MySQL server has gone away)
Sun Sep 26 13:06:14 2021 - [info] Executing SSH check script: save_binary_logs --command=test --start_pos=4 --binlog_dir=/var/lib/mysql/ --output_file=/tmp/save_binary_logs_test --manager_version=0.57 --binlog_prefix=mysql1-bin
Sun Sep 26 13:06:14 2021 - [info] Executing secondary network check script: /usr/local/bin/masterha_secondary_check -s 192.168.126.93 -s 192.168.126.94  --user=root  --master_host=rs1  --master_ip=192.168.126.92  --master_port=3306 --master_user=mha --master_password=linux123.COM --ping_type=SELECT
Sun Sep 26 13:06:15 2021 - [info] HealthCheck: SSH to rs1 is reachable.
Monitoring server 192.168.126.93 is reachable, Master is not reachable from 192.168.126.93. OK.
Monitoring server 192.168.126.94 is reachable, Master is not reachable from 192.168.126.94. OK.
Sun Sep 26 13:06:15 2021 - [info] Master is not reachable from all other monitoring servers. Failover should start.
Sun Sep 26 13:06:15 2021 - [warning] Got error on MySQL connect: 2003 (Can't connect to MySQL server on '192.168.126.92' (111))
Sun Sep 26 13:06:15 2021 - [warning] Connection failed 2 time(s)..
Sun Sep 26 13:06:16 2021 - [warning] Got error on MySQL connect: 2003 (Can't connect to MySQL server on '192.168.126.92' (111))
Sun Sep 26 13:06:16 2021 - [warning] Connection failed 3 time(s)..
Sun Sep 26 13:06:17 2021 - [warning] Got error on MySQL connect: 2003 (Can't connect to MySQL server on '192.168.126.92' (111))
Sun Sep 26 13:06:17 2021 - [warning] Connection failed 4 time(s)..
Sun Sep 26 13:06:17 2021 - [warning] Master is not reachable from health checker!
Sun Sep 26 13:06:17 2021 - [warning] Master rs1(192.168.126.92:3306) is not reachable!
Sun Sep 26 13:06:17 2021 - [warning] SSH is reachable.
Sun Sep 26 13:06:17 2021 - [info] Connecting to a master server failed. Reading configuration file /etc/masterha_default.cnf and /etc/masterha/app1.cnf again, and trying to connect to all servers to check server status..
Sun Sep 26 13:06:17 2021 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sun Sep 26 13:06:17 2021 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Sun Sep 26 13:06:17 2021 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Sun Sep 26 13:06:18 2021 - [info] GTID failover mode = 0
Sun Sep 26 13:06:18 2021 - [info] Dead Servers:
Sun Sep 26 13:06:18 2021 - [info]   rs1(192.168.126.92:3306)
Sun Sep 26 13:06:18 2021 - [info] Alive Servers:
Sun Sep 26 13:06:18 2021 - [info]   rs2(192.168.126.93:3306)
Sun Sep 26 13:06:18 2021 - [info]   nfs(192.168.126.94:3306)
Sun Sep 26 13:06:18 2021 - [info] Alive Slaves:
Sun Sep 26 13:06:18 2021 - [info]   rs2(192.168.126.93:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:18 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:18 2021 - [info]     Primary candidate for the new Master (candidate_master is set)
Sun Sep 26 13:06:18 2021 - [info]   nfs(192.168.126.94:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:18 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:18 2021 - [info] Checking slave configurations..
Sun Sep 26 13:06:18 2021 - [info]  read_only=1 is not set on slave rs2(192.168.126.93:3306).
Sun Sep 26 13:06:18 2021 - [warning]  relay_log_purge=0 is not set on slave rs2(192.168.126.93:3306).
Sun Sep 26 13:06:18 2021 - [info]  read_only=1 is not set on slave nfs(192.168.126.94:3306).
Sun Sep 26 13:06:18 2021 - [warning]  relay_log_purge=0 is not set on slave nfs(192.168.126.94:3306).
Sun Sep 26 13:06:18 2021 - [info] Checking replication filtering settings..
Sun Sep 26 13:06:18 2021 - [info]  Replication filtering check ok.
Sun Sep 26 13:06:18 2021 - [info] Master is down!
Sun Sep 26 13:06:18 2021 - [info] Terminating monitoring script.
Sun Sep 26 13:06:18 2021 - [info] Got exit code 20 (Master dead).
Sun Sep 26 13:06:18 2021 - [info] MHA::MasterFailover version 0.57.
Sun Sep 26 13:06:18 2021 - [info] Starting master failover.
Sun Sep 26 13:06:18 2021 - [info]
Sun Sep 26 13:06:18 2021 - [info] * Phase 1: Configuration Check Phase..
Sun Sep 26 13:06:18 2021 - [info]
Sun Sep 26 13:06:19 2021 - [info] GTID failover mode = 0
Sun Sep 26 13:06:19 2021 - [info] Dead Servers:
Sun Sep 26 13:06:19 2021 - [info]   rs1(192.168.126.92:3306)
Sun Sep 26 13:06:19 2021 - [info] Checking master reachability via MySQL(double check)...
Sun Sep 26 13:06:19 2021 - [info]  ok.
Sun Sep 26 13:06:19 2021 - [info] Alive Servers:
Sun Sep 26 13:06:19 2021 - [info]   rs2(192.168.126.93:3306)
Sun Sep 26 13:06:19 2021 - [info]   nfs(192.168.126.94:3306)
Sun Sep 26 13:06:19 2021 - [info] Alive Slaves:
Sun Sep 26 13:06:19 2021 - [info]   rs2(192.168.126.93:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:19 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:19 2021 - [info]     Primary candidate for the new Master (candidate_master is set)
Sun Sep 26 13:06:19 2021 - [info]   nfs(192.168.126.94:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:19 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:19 2021 - [info] Starting Non-GTID based failover.
Sun Sep 26 13:06:19 2021 - [info]
Sun Sep 26 13:06:19 2021 - [info] ** Phase 1: Configuration Check Phase completed.
Sun Sep 26 13:06:19 2021 - [info]
Sun Sep 26 13:06:19 2021 - [info] * Phase 2: Dead Master Shutdown Phase..
Sun Sep 26 13:06:19 2021 - [info]
Sun Sep 26 13:06:19 2021 - [info] Forcing shutdown so that applications never connect to the current master..
Sun Sep 26 13:06:19 2021 - [info] Executing master IP deactivation script:
Sun Sep 26 13:06:19 2021 - [info]   /usr/local/bin/master_ip_failover --orig_master_host=rs1 --orig_master_ip=192.168.126.92 --orig_master_port=3306 --command=stopssh --ssh_user=root  IN SCRIPT TEST====/usr/sbin/ifconfig ens32:1 down==/usr/sbin/ifconfig ens32:1 192.168.126.200/24===Disabling the VIP on old master: rs1
Sun Sep 26 13:06:20 2021 - [info]  done.
Sun Sep 26 13:06:20 2021 - [warning] shutdown_script is not set. Skipping explicit shutting down of the dead master.
Sun Sep 26 13:06:20 2021 - [info] * Phase 2: Dead Master Shutdown Phase completed.
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 3: Master Recovery Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 3.1: Getting Latest Slaves Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] The latest binary log file/position on all slaves is mysql1-bin.000008:155
Sun Sep 26 13:06:20 2021 - [info] Latest slaves (Slaves that received relay log files to the latest):
Sun Sep 26 13:06:20 2021 - [info]   rs2(192.168.126.93:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:20 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:20 2021 - [info]     Primary candidate for the new Master (candidate_master is set)
Sun Sep 26 13:06:20 2021 - [info]   nfs(192.168.126.94:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:20 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:20 2021 - [info] The oldest binary log file/position on all slaves is mysql1-bin.000008:155
Sun Sep 26 13:06:20 2021 - [info] Oldest slaves:
Sun Sep 26 13:06:20 2021 - [info]   rs2(192.168.126.93:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:20 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:20 2021 - [info]     Primary candidate for the new Master (candidate_master is set)
Sun Sep 26 13:06:20 2021 - [info]   nfs(192.168.126.94:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:20 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 3.2: Saving Dead Master's Binlog Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] Fetching dead master's binary logs..
Sun Sep 26 13:06:20 2021 - [info] Executing command on the dead master rs1(192.168.126.92:3306): save_binary_logs --command=save --start_file=mysql1-bin.000008  --start_pos=155 --binlog_dir=/var/lib/mysql/ --output_file=/tmp/saved_master_binlog_from_rs1_3306_20210926130618.binlog --handle_raw_binlog=1 --disable_log_bin=0 --manager_version=0.57Creating /tmp if not exists..    ok.Concat binary/relay logs from mysql1-bin.000008 pos 155 to mysql1-bin.000008 EOF into /tmp/saved_master_binlog_from_rs1_3306_20210926130618.binlog ..Binlog Checksum enabledDumping binlog format description event, from position 0 to 155.. ok.No need to dump effective binlog data from /var/lib/mysql//mysql1-bin.000008 (pos starts 155, filesize 155). Skipping.Binlog Checksum enabled/tmp/saved_master_binlog_from_rs1_3306_20210926130618.binlog has no effective data events.
Event not exists.
Sun Sep 26 13:06:20 2021 - [info] Additional events were not found from the orig master. No need to save.
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 3.3: Determining New Master Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] Finding the latest slave that has all relay logs for recovering other slaves..
Sun Sep 26 13:06:20 2021 - [info] All slaves received relay logs to the same position. No need to resync each other.
Sun Sep 26 13:06:20 2021 - [info] Searching new master from slaves..
Sun Sep 26 13:06:20 2021 - [info]  Candidate masters from the configuration file:
Sun Sep 26 13:06:20 2021 - [info]   rs2(192.168.126.93:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:06:20 2021 - [info]     Replicating from rs1(192.168.126.92:3306)
Sun Sep 26 13:06:20 2021 - [info]     Primary candidate for the new Master (candidate_master is set)
Sun Sep 26 13:06:20 2021 - [info]  Non-candidate masters:
Sun Sep 26 13:06:20 2021 - [info]  Searching from candidate_master slaves which have received the latest relay log events..
Sun Sep 26 13:06:20 2021 - [info] New master is rs2(192.168.126.93:3306)
Sun Sep 26 13:06:20 2021 - [info] Starting master failover..
Sun Sep 26 13:06:20 2021 - [info]
From:
rs1(192.168.126.92:3306) (current master)+--rs2(192.168.126.93:3306)+--nfs(192.168.126.94:3306)To:
rs2(192.168.126.93:3306) (new master)+--nfs(192.168.126.94:3306)
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 3.3: New Master Diff Log Generation Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info]  This server has all relay logs. No need to generate diff files from the latest slave.
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 3.4: Master Log Apply Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] *NOTICE: If any error happens from this phase, manual recovery is needed.
Sun Sep 26 13:06:20 2021 - [info] Starting recovery on rs2(192.168.126.93:3306)..
Sun Sep 26 13:06:20 2021 - [info]  This server has all relay logs. Waiting all logs to be applied..
Sun Sep 26 13:06:20 2021 - [info]   done.
Sun Sep 26 13:06:20 2021 - [info]  All relay logs were successfully applied.
Sun Sep 26 13:06:20 2021 - [info] Getting new master's binlog name and position..
Sun Sep 26 13:06:20 2021 - [info]  mysql2-bin.000004:155
Sun Sep 26 13:06:20 2021 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='rs2 or 192.168.126.93', MASTER_PORT=3306, MASTER_LOG_FILE='mysql2-bin.000004', MASTER_LOG_POS=155, MASTER_USER='copy', MASTER_PASSWORD='xxx';
Sun Sep 26 13:06:20 2021 - [info] Executing master IP activate script:
Sun Sep 26 13:06:20 2021 - [info]   /usr/local/bin/master_ip_failover --command=start --ssh_user=root --orig_master_host=rs1 --orig_master_ip=192.168.126.92 --orig_master_port=3306 --new_master_host=rs2 --new_master_ip=192.168.126.93 --new_master_port=3306 --new_master_user='mha'   --new_master_password=xxx
Unknown option: new_master_user
Unknown option: new_master_passwordIN SCRIPT TEST====/usr/sbin/ifconfig ens32:1 down==/usr/sbin/ifconfig ens32:1 192.168.126.200/24===Enabling the VIP - 192.168.126.200/24 on the new master - rs2
Sun Sep 26 13:06:20 2021 - [info]  OK.
Sun Sep 26 13:06:20 2021 - [info] ** Finished master recovery successfully.
Sun Sep 26 13:06:20 2021 - [info] * Phase 3: Master Recovery Phase completed.
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 4: Slaves Recovery Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] * Phase 4.1: Starting Parallel Slave Diff Log Generation Phase..
Sun Sep 26 13:06:20 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info] -- Slave diff file generation on host nfs(192.168.126.94:3306) started, pid: 16751. Check tmp log /etc/masterha//nfs_3306_20210926130618.log if it takes time..
Sun Sep 26 13:06:21 2021 - [info]
Sun Sep 26 13:06:21 2021 - [info] Log messages from nfs ...
Sun Sep 26 13:06:21 2021 - [info]
Sun Sep 26 13:06:20 2021 - [info]  This server has all relay logs. No need to generate diff files from the latest slave.
Sun Sep 26 13:06:21 2021 - [info] End of log messages from nfs.
Sun Sep 26 13:06:21 2021 - [info] -- nfs(192.168.126.94:3306) has the latest relay log events.
Sun Sep 26 13:06:21 2021 - [info] Generating relay diff files from the latest slave succeeded.
Sun Sep 26 13:06:21 2021 - [info]
Sun Sep 26 13:06:21 2021 - [info] * Phase 4.2: Starting Parallel Slave Log Apply Phase..
Sun Sep 26 13:06:21 2021 - [info]
Sun Sep 26 13:06:21 2021 - [info] -- Slave recovery on host nfs(192.168.126.94:3306) started, pid: 16754. Check tmp log /etc/masterha//nfs_3306_20210926130618.log if it takes time..
Sun Sep 26 13:06:22 2021 - [info]
Sun Sep 26 13:06:22 2021 - [info] Log messages from nfs ...
Sun Sep 26 13:06:22 2021 - [info]
Sun Sep 26 13:06:21 2021 - [info] Starting recovery on nfs(192.168.126.94:3306)..
Sun Sep 26 13:06:21 2021 - [info]  This server has all relay logs. Waiting all logs to be applied..
Sun Sep 26 13:06:21 2021 - [info]   done.
Sun Sep 26 13:06:21 2021 - [info]  All relay logs were successfully applied.
Sun Sep 26 13:06:21 2021 - [info]  Resetting slave nfs(192.168.126.94:3306) and starting replication from the new master rs2(192.168.126.93:3306)..
Sun Sep 26 13:06:21 2021 - [info]  Executed CHANGE MASTER.
Sun Sep 26 13:06:22 2021 - [info]  Slave started.
Sun Sep 26 13:06:22 2021 - [info] End of log messages from nfs.
Sun Sep 26 13:06:22 2021 - [info] -- Slave recovery on host nfs(192.168.126.94:3306) succeeded.
Sun Sep 26 13:06:22 2021 - [info] All new slave servers recovered successfully.
Sun Sep 26 13:06:22 2021 - [info]
Sun Sep 26 13:06:22 2021 - [info] * Phase 5: New master cleanup phase..
Sun Sep 26 13:06:22 2021 - [info]
Sun Sep 26 13:06:22 2021 - [info] Resetting slave info on the new master..
Sun Sep 26 13:06:22 2021 - [info]  rs2: Resetting slave info succeeded.
Sun Sep 26 13:06:22 2021 - [info] Master failover to rs2(192.168.126.93:3306) completed successfully.
Sun Sep 26 13:06:22 2021 - [info] ----- Failover Report -----app1: MySQL Master failover rs1(192.168.126.92:3306) to rs2(192.168.126.93:3306) succeededMaster rs1(192.168.126.92:3306) is down!Check MHA Manager logs at mha-manager:/etc/masterha/mha.log for details.Started automated(non-interactive) failover.
Invalidated master IP address on rs1(192.168.126.92:3306)
The latest slave rs2(192.168.126.93:3306) has all relay logs for recovery.
Selected rs2(192.168.126.93:3306) as a new master.
rs2(192.168.126.93:3306): OK: Applying all logs succeeded.
rs2(192.168.126.93:3306): OK: Activated master IP address.
nfs(192.168.126.94:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
nfs(192.168.126.94:3306): OK: Applying all logs succeeded. Slave started, replicating from rs2(192.168.126.93:3306)
rs2(192.168.126.93:3306): Resetting slave info succeeded.
Master failover to rs2(192.168.126.93:3306) completed successfully. # 主切换为rs2# 同时查看rs1的VIP消失
[root@rs1 ~]# ip a | grep 192.168.126.200# 查看新的主rs2是否接管vip
[root@rs2 ~]# ip a | grep 192.168.126.200inet 192.168.126.200/24 brd 192.168.126.255 scope global secondary ens32:1
# 验证rs2是否为主库
[root@rs2 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 37
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show master status;
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB                                | Executed_Gtid_Set |
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
| mysql2-bin.000004 |      155 |              | information_schema,mysql,performance_schema,sys |                   |
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
1 row in set (0.00 sec)mysql> show slave status;
Empty set (0.00 sec)# 注意:正常自动切换一次后,MHA 进程会退出。
# 切换过程中需要关注的几个问题:
# 1.切换过程会自动把数据库只读read_only关闭
# 2.切换之后需要删除手工删除/etc/masterha/app1.failover.complete,才能进行第二次测试
# 3.一旦发生切换管理进程将会退出,无法进行再次测试,需将故障数据库加入到MHA环境中来故障切换备选主库的算法(根据app1.cnf配置文件中的设置):
1、一般判断从库的是从(position/GTID)判断优劣,数据有差异,最接近于master的slave,成为备选主。
2、数据一致的情况下,按照配置文件顺序,选择备选主库。
3、设定有权重(candidate_master=1),按照权重强制指定备选主。默认情况下如果一个slave落后master 100M的relay logs的话,即使有权重,也会失效。如果check_repl_delay=0的话,即使落后很多日志,也强制选择其为备选主。4、二级从数据库服务器需要在my.cnf数据可配置文件中将log_slave_updates打开
5、手工切换需要先定义好master_ip_online_change_script脚本,不然只会切换mysql,Ip地址不会绑定上去,可以根据模板来配置该脚本
6、通过设置no_master=1可以让某一个节点永远不成为新的主节点# 故障修复
# 启动rs1主机的数据库
[root@rs1 ~]# systemctl start mysqld# 在现主库服务器 rs2 查看二进制文件和同步点
[root@rs2 ~]# mysql -uroot -p'mysql123.COM' -e "show master status;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB                                | Executed_Gtid_Set |
+-------------------+----------+--------------+-------------------------------------------------+-------------------+
| mysql2-bin.000004 |      155 |              | information_schema,mysql,performance_schema,sys |                   |
+-------------------+----------+--------------+-------------------------------------------------+-------------------+# 配置原主库服务器 rs1为新主库rs2的从库
[root@rs1 ~]# mysql -uroot -p'mysql123.COM'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.16 MySQL Community Server - GPLCopyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> change master to-> master_host='rs2',-> master_user='copy',-> master_password='linux123.COM',-> master_log_file='mysql2-bin.000004',-> master_log_pos=155;
Query OK, 0 rows affected, 2 warnings (0.01 sec)mysql> start slave;
Query OK, 0 rows affected (0.00 sec)mysql> show slave status\G;
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: rs2Master_User: copyMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql2-bin.000004Read_Master_Log_Pos: 155Relay_Log_File: relay1-log.000002Relay_Log_Pos: 323Relay_Master_Log_File: mysql2-bin.000004Slave_IO_Running: YesSlave_SQL_Running: Yes       # 成功Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 155Relay_Log_Space: 526Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2Master_UUID: 9bc02a48-1d3a-11ec-a4b6-000c292bea5aMaster_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: Master_public_key_path: Get_master_public_key: 0Network_Namespace:
1 row in set (0.00 sec)# 删除mha-manager节点的mha工作目录下的文件
[root@mha-manager masterha]# ls
app1.cnf  app1.failover.complete  mha.log
[root@mha-manager masterha]# rm -rf app1.failover.complete  mha.log# 修改配置文件app1.cnf
[root@mha-manager masterha]# vim app1.cnf
master_ip_online_change_script=/usr/local/bin/master_ip_online_change
ping_interval=1
remote_workdir=/tmp
repl_user=copy
repl_password=linux123.COM
report_script=/usr/local/bin/send_report
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.126.92 -s 192.168.126.94
shutdown_script=""
ssh_user=root
user=mha
password=linux123.COM[server1]
hostname=rs1
port=3306
candidate_master=1
check_repl_delay=0[server2]
hostname=rs2
port=3306[server3]
hostname=nfs
port=3306# 主从检测
[root@mha-manager mha4mysql-manager-0.57]# masterha_check_repl -conf=/etc/masterha/app1.cnf
Sun Sep 26 13:30:39 2021 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sun Sep 26 13:30:39 2021 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Sun Sep 26 13:30:39 2021 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Sun Sep 26 13:30:39 2021 - [info] MHA::MasterMonitor version 0.57.
Sun Sep 26 13:30:40 2021 - [info] GTID failover mode = 0
Sun Sep 26 13:30:40 2021 - [info] Dead Servers:
Sun Sep 26 13:30:40 2021 - [info] Alive Servers:
Sun Sep 26 13:30:40 2021 - [info]   rs1(192.168.126.92:3306)
Sun Sep 26 13:30:40 2021 - [info]   rs2(192.168.126.93:3306)
Sun Sep 26 13:30:40 2021 - [info]   nfs(192.168.126.94:3306)
Sun Sep 26 13:30:40 2021 - [info] Alive Slaves:
Sun Sep 26 13:30:40 2021 - [info]   rs1(192.168.126.92:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:30:40 2021 - [info]     Replicating from rs2(192.168.126.93:3306)
Sun Sep 26 13:30:40 2021 - [info]     Primary candidate for the new Master (candidate_master is set)
Sun Sep 26 13:30:40 2021 - [info]   nfs(192.168.126.94:3306)  Version=8.0.16 (oldest major version between slaves) log-bin:enabled
Sun Sep 26 13:30:40 2021 - [info]     Replicating from rs2(192.168.126.93:3306)
Sun Sep 26 13:30:40 2021 - [info] Current Alive Master: rs2(192.168.126.93:3306)
Sun Sep 26 13:30:40 2021 - [info] Checking slave configurations..
Sun Sep 26 13:30:40 2021 - [info]  read_only=1 is not set on slave rs1(192.168.126.92:3306).
Sun Sep 26 13:30:40 2021 - [warning]  relay_log_purge=0 is not set on slave rs1(192.168.126.92:3306).
Sun Sep 26 13:30:40 2021 - [info]  read_only=1 is not set on slave nfs(192.168.126.94:3306).
Sun Sep 26 13:30:40 2021 - [warning]  relay_log_purge=0 is not set on slave nfs(192.168.126.94:3306).
Sun Sep 26 13:30:40 2021 - [info] Checking replication filtering settings..
Sun Sep 26 13:30:40 2021 - [info]  binlog_do_db= , binlog_ignore_db= information_schema,mysql,performance_schema,sys
Sun Sep 26 13:30:40 2021 - [info]  Replication filtering check ok.
Sun Sep 26 13:30:40 2021 - [info] GTID (with auto-pos) is not supported
Sun Sep 26 13:30:40 2021 - [info] Starting SSH connection tests..
Sun Sep 26 13:30:42 2021 - [info] All SSH connection tests passed successfully.
Sun Sep 26 13:30:42 2021 - [info] Checking MHA Node version..
Sun Sep 26 13:30:43 2021 - [info]  Version check ok.
Sun Sep 26 13:30:43 2021 - [info] Checking SSH publickey authentication settings on the current master..
Sun Sep 26 13:30:43 2021 - [info] HealthCheck: SSH to rs2 is reachable.
Sun Sep 26 13:30:43 2021 - [info] Master MHA Node version is 0.57.
Sun Sep 26 13:30:43 2021 - [info] Checking recovery script configurations on rs2(192.168.126.93:3306)..
Sun Sep 26 13:30:43 2021 - [info]   Executing command: save_binary_logs --command=test --start_pos=4 --binlog_dir=/var/lib/mysql/ --output_file=/tmp/save_binary_logs_test --manager_version=0.57 --start_file=mysql2-bin.000004
Sun Sep 26 13:30:43 2021 - [info]   Connecting to root@192.168.126.93(rs2:22).. Creating /tmp if not exists..    ok.Checking output directory is accessible or not..ok.Binlog found at /var/lib/mysql/, up to mysql2-bin.000004
Sun Sep 26 13:30:44 2021 - [info] Binlog setting check done.
Sun Sep 26 13:30:44 2021 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers..
Sun Sep 26 13:30:44 2021 - [info]   Executing command : apply_diff_relay_logs --command=test --slave_user='mha' --slave_host=rs1 --slave_ip=192.168.126.92 --slave_port=3306 --workdir=/tmp --target_version=8.0.16 --manager_version=0.57 --relay_dir=/var/lib/mysql --current_relay_log=relay1-log.000002  --slave_pass=xxx
Sun Sep 26 13:30:44 2021 - [info]   Connecting to root@192.168.126.92(rs1:22).. Checking slave recovery environment settings..Relay log found at /var/lib/mysql, up to relay1-log.000002Temporary relay log file is /var/lib/mysql/relay1-log.000002Testing mysql connection and privileges..mysql: [Warning] Using a password on the command line interface can be insecure.done.Testing mysqlbinlog output.. done.Cleaning up test file(s).. done.
Sun Sep 26 13:30:44 2021 - [info]   Executing command : apply_diff_relay_logs --command=test --slave_user='mha' --slave_host=nfs --slave_ip=192.168.126.94 --slave_port=3306 --workdir=/tmp --target_version=8.0.16 --manager_version=0.57 --relay_dir=/var/lib/mysql --current_relay_log=relay3-log.000002  --slave_pass=xxx
Sun Sep 26 13:30:44 2021 - [info]   Connecting to root@192.168.126.94(nfs:22).. Checking slave recovery environment settings..Relay log found at /var/lib/mysql, up to relay3-log.000002Temporary relay log file is /var/lib/mysql/relay3-log.000002Testing mysql connection and privileges..mysql: [Warning] Using a password on the command line interface can be insecure.done.Testing mysqlbinlog output.. done.Cleaning up test file(s).. done.
Sun Sep 26 13:30:44 2021 - [info] Slaves settings check done.
Sun Sep 26 13:30:44 2021 - [info]
rs2(192.168.126.93:3306) (current master)+--rs1(192.168.126.92:3306)+--nfs(192.168.126.94:3306)Sun Sep 26 13:30:44 2021 - [info] Checking replication health on rs1..
Sun Sep 26 13:30:44 2021 - [info]  ok.
Sun Sep 26 13:30:44 2021 - [info] Checking replication health on nfs..
Sun Sep 26 13:30:44 2021 - [info]  ok.
Sun Sep 26 13:30:44 2021 - [info] Checking master_ip_failover_script status:
Sun Sep 26 13:30:44 2021 - [info]   /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=rs2 --orig_master_ip=192.168.126.93 --orig_master_port=3306 IN SCRIPT TEST====/usr/sbin/ifconfig ens32:1 down==/usr/sbin/ifconfig ens32:1 192.168.126.200/24===Checking the Status of the script.. OK
Sun Sep 26 13:30:44 2021 - [info]  OK.
Sun Sep 26 13:30:44 2021 - [warning] shutdown_script is not defined.
Sun Sep 26 13:30:44 2021 - [info] Got exit code 0 (Not master dead).MySQL Replication Health is OK.# 启动 MHA
[root@mha-manager mha4mysql-manager-0.57]# nohup masterha_manager --conf=/etc/masterha/app1.cnf > /etc/masterha/mha.log  < /dev/null 2>&1 &
[1] 18046
[root@mha-manager mha4mysql-manager-0.57]#
[root@mha-manager mha4mysql-manager-0.57]# masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:18046) is running(0:PING_OK), master:rs2

redis配置

redis一主一从三哨兵+keepalived

主机名 IP 角色 备注
rs1 192.168.126.92 nginx服务器1、mysql服务器 、redis主+keepalived、redis哨兵 1提供WEB静态资源及对动态资源请求转发至后端tomcat服务器、mysql主(mysql主节点,负责写数据)
rs2 192.168.126.93 nginx服务器2 、mysql服务器、redis从+keepalived、redis哨兵2 提供WEB静态资源及对动态资源请求转发至后端tomcat服务器、mysql从1(mysql从节点,负责读数据,备选master)
nfs 192.168.126.94 数据共享服务器 、mysql服务器、redis哨兵3 提供网页共享静态WEB资源、mysql从2(mysql从节点,负责读数据)

安装redis

rs1、rs2、nfs节点均按如下步骤进行安装

说明:nfs不作为redis从,但要作为哨兵(所以还是得安装redis)

[root@rs1 ~]# wget http://download.redis.io/releases/redis-4.0.0.tar.gz
[root@rs1 ~]# ls
redis-4.0.0.tar.gz
[root@rs1 ~]# mkdir -p /usr/local/redis
[root@rs1 ~]# tar -xf redis-4.0.0.tar.gz -C /usr/local/redis
# 下载编译时所需依赖包
[root@rs1 ~]# yum -y install gcc gcc-c++
[root@rs1 ~]# cd /usr/local/redis/redis-4.0.0/
[root@rs1 redis-4.0.0]# ls
00-RELEASENOTES  CONTRIBUTING  deps     Makefile   README.md   runtest          runtest-sentinel  src    utils
BUGS             COPYING       INSTALL  MANIFESTO  redis.conf  runtest-cluster  sentinel.conf     tests
[root@rs1 redis-4.0.0]# make MALLOC=libc
[root@rs1 redis-4.0.0]# make install

配置一主一从

rs1作为redis主:

[root@rs1 ~]# mkdir /usr/local/redis/redis-4.0.0/data
[root@rs1 ~]# vim /usr/local/redis/redis-4.0.0/redis.conf
port 6379
daemonize no
dir /usr/local/redis/redis-4.0.0/data
protected-mode no

rs2作为redis从:

[root@rs2 ~]# mkdir /usr/local/redis/redis-4.0.0/data
[root@rs2 ~]# vim /usr/local/redis/redis-4.0.0/redis.conf
port 6379
daemonize no
protected-mode no
dir /usr/local/redis/redis-4.0.0/data
slaveof 192.168.126.92 6379

同时启动主从:

# 启动redis主rs1
[root@rs1 ~]# redis-server /usr/local/redis/redis-4.0.0/redis.conf
5613:C 26 Sep 16:26:39.897 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5613:C 26 Sep 16:26:39.897 # Redis version=4.0.0, bits=64, commit=00000000, modified=0, pid=5613, just started
5613:C 26 Sep 16:26:39.897 # Configuration loaded
5613:M 26 Sep 16:26:39.898 * Increased maximum number of open files to 10032 (it was originally set to 1024)._._                                                  _.-``__ ''-._                                             _.-``    `.  `_.  ''-._           Redis 4.0.0 (00000000/0) 64 bit.-`` .-```.  ```\/    _.,_ ''-._                                   (    '      ,       .-`  | `,    )     Running in standalone mode|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379|    `-._   `._    /     _.-'    |     PID: 5613`-._    `-._  `-./  _.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |           http://redis.io        `-._    `-._`-.__.-'_.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |                                  `-._    `-._`-.__.-'_.-'    _.-'                                   `-._    `-.__.-'    _.-'                                       `-._        _.-'                                           `-.__.-'                                               5613:M 26 Sep 16:26:39.899 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
5613:M 26 Sep 16:26:39.899 # Server initialized
5613:M 26 Sep 16:26:39.899 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
5613:M 26 Sep 16:26:39.900 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
5613:M 26 Sep 16:26:39.900 * Ready to accept connections
5613:M 26 Sep 16:26:55.259 * Slave 192.168.126.93:6379 asks for synchronization
5613:M 26 Sep 16:26:55.259 * Full resync requested by slave 192.168.126.93:6379
5613:M 26 Sep 16:26:55.259 * Starting BGSAVE for SYNC with target: disk
5613:M 26 Sep 16:26:55.260 * Background saving started by pid 5617
5617:C 26 Sep 16:26:55.260 * DB saved on disk
5617:C 26 Sep 16:26:55.261 * RDB: 0 MB of memory used by copy-on-write
5613:M 26 Sep 16:26:55.284 * Background saving terminated with success
5613:M 26 Sep 16:26:55.284 * Synchronization with slave 192.168.126.93:6379 succeeded   # 主从同步成功# 启动redis从rs2
[root@rs2 ~]# redis-server /usr/local/redis/redis-4.0.0/redis.conf
62918:C 26 Sep 16:26:55.253 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
62918:C 26 Sep 16:26:55.253 # Redis version=4.0.0, bits=64, commit=00000000, modified=0, pid=62918, just started
62918:C 26 Sep 16:26:55.253 # Configuration loaded
62918:S 26 Sep 16:26:55.254 * Increased maximum number of open files to 10032 (it was originally set to 1024)._._                                                  _.-``__ ''-._                                             _.-``    `.  `_.  ''-._           Redis 4.0.0 (00000000/0) 64 bit.-`` .-```.  ```\/    _.,_ ''-._                                   (    '      ,       .-`  | `,    )     Running in standalone mode|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379|    `-._   `._    /     _.-'    |     PID: 62918`-._    `-._  `-./  _.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |           http://redis.io        `-._    `-._`-.__.-'_.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |                                  `-._    `-._`-.__.-'_.-'    _.-'                                   `-._    `-.__.-'    _.-'                                       `-._        _.-'                                           `-.__.-'                                               62918:S 26 Sep 16:26:55.256 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
62918:S 26 Sep 16:26:55.256 # Server initialized
62918:S 26 Sep 16:26:55.256 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
62918:S 26 Sep 16:26:55.256 * Ready to accept connections
62918:S 26 Sep 16:26:55.257 * Connecting to MASTER 192.168.126.92:6379
62918:S 26 Sep 16:26:55.257 * MASTER <-> SLAVE sync started
62918:S 26 Sep 16:26:55.258 * Non blocking connect for SYNC fired the event.
62918:S 26 Sep 16:26:55.258 * Master replied to PING, replication can continue...
62918:S 26 Sep 16:26:55.259 * Partial resynchronization not possible (no cached master)
62918:S 26 Sep 16:26:55.259 * Full resync from master: 80a249e16ade10c26fa40b9efceccaca10468d7c:0
62918:S 26 Sep 16:26:55.284 * MASTER <-> SLAVE sync: receiving 175 bytes from master
62918:S 26 Sep 16:26:55.284 * MASTER <-> SLAVE sync: Flushing old data
62918:S 26 Sep 16:26:55.284 * MASTER <-> SLAVE sync: Loading DB in memory
62918:S 26 Sep 16:26:55.284 * MASTER <-> SLAVE sync: Finished with success  # 主从同步成功

测试主从同步数据:

# 主
[root@rs1 ~]# redis-cli
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.126.93,port=6379,state=online,offset=382,lag=0
master_replid:80a249e16ade10c26fa40b9efceccaca10468d7c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:382
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:382# 从
[root@rs2 ~]# redis-cli
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.126.92
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:396
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:80a249e16ade10c26fa40b9efceccaca10468d7c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:396
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:396# 主从正常

配置哨兵

[root@rs1 ~]# vim /usr/local/redis/redis-4.0.0/sentinel.conf
port 26379
dir /usr/local/redis/redis-4.0.0/data
sentinel monitor mymaster 192.168.126.92 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
protected-mode no[root@rs2 ~]# vim /usr/local/redis/redis-4.0.0/sentinel.conf
port 26379
dir /usr/local/redis/redis-4.0.0/data
sentinel monitor mymaster 192.168.126.92 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
protected-mode no[root@nfs ~]# vim /usr/local/redis/redis-4.0.0/sentinel.conf
port 26379
dir /usr/local/redis/redis-4.0.0/data
sentinel monitor mymaster 192.168.126.92 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
protected-mode no

启动哨兵

# rs1哨兵:
[root@rs1 ~]# redis-sentinel /usr/local/redis/redis-4.0.0/sentinel.conf
5648:X 26 Sep 16:39:07.008 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5648:X 26 Sep 16:39:07.008 # Redis version=4.0.0, bits=64, commit=00000000, modified=0, pid=5648, just started
5648:X 26 Sep 16:39:07.008 # Configuration loaded
5648:X 26 Sep 16:39:07.009 * Increased maximum number of open files to 10032 (it was originally set to 1024)._._                                                  _.-``__ ''-._                                             _.-``    `.  `_.  ''-._           Redis 4.0.0 (00000000/0) 64 bit.-`` .-```.  ```\/    _.,_ ''-._                                   (    '      ,       .-`  | `,    )     Running in sentinel mode|`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379|    `-._   `._    /     _.-'    |     PID: 5648`-._    `-._  `-./  _.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |           http://redis.io        `-._    `-._`-.__.-'_.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |                                  `-._    `-._`-.__.-'_.-'    _.-'                                   `-._    `-.__.-'    _.-'                                       `-._        _.-'                                           `-.__.-'                                               5648:X 26 Sep 16:39:07.010 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
5648:X 26 Sep 16:39:07.011 # Sentinel ID is b52bd0f340f84ee933fb0314143105bdaa91f608
5648:X 26 Sep 16:39:07.011 # +monitor master mymaster 192.168.126.92 6379 quorum 2
5648:X 26 Sep 16:39:07.011 * +slave slave 192.168.126.93:6379 192.168.126.93 6379 @ mymaster 192.168.126.92 6379
5648:X 26 Sep 16:39:07.616 * +sentinel sentinel 68cd3bb1de8d21777f81a838050541dec642577a 192.168.126.93 26379 @ mymaster 192.168.126.92 6379
5648:X 26 Sep 16:39:26.224 * +sentinel sentinel f8598202868d2cf721df04f4f5da4c1bb70ec09f 192.168.126.94 26379 @ mymaster 192.168.126.92 6379
[root@rs1 ~]# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.126.92:6379,slaves=1,sentinels=3# rs2哨兵:
[root@rs2 ~]# redis-sentinel /usr/local/redis/redis-4.0.0/sentinel.conf
65211:X 26 Sep 16:39:03.526 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
65211:X 26 Sep 16:39:03.526 # Redis version=4.0.0, bits=64, commit=00000000, modified=0, pid=65211, just started
65211:X 26 Sep 16:39:03.526 # Configuration loaded
65211:X 26 Sep 16:39:03.527 * Increased maximum number of open files to 10032 (it was originally set to 1024)._._                                                  _.-``__ ''-._                                             _.-``    `.  `_.  ''-._           Redis 4.0.0 (00000000/0) 64 bit.-`` .-```.  ```\/    _.,_ ''-._                                   (    '      ,       .-`  | `,    )     Running in sentinel mode|`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379|    `-._   `._    /     _.-'    |     PID: 65211`-._    `-._  `-./  _.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |           http://redis.io        `-._    `-._`-.__.-'_.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |                                  `-._    `-._`-.__.-'_.-'    _.-'                                   `-._    `-.__.-'    _.-'                                       `-._        _.-'                                           `-.__.-'                                               65211:X 26 Sep 16:39:03.528 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
65211:X 26 Sep 16:39:03.529 # Sentinel ID is 68cd3bb1de8d21777f81a838050541dec642577a
65211:X 26 Sep 16:39:03.529 # +monitor master mymaster 192.168.126.92 6379 quorum 2
65211:X 26 Sep 16:39:03.530 * +slave slave 192.168.126.93:6379 192.168.126.93 6379 @ mymaster 192.168.126.92 6379
65211:X 26 Sep 16:39:09.078 * +sentinel sentinel b52bd0f340f84ee933fb0314143105bdaa91f608 192.168.126.92 26379 @ mymaster 192.168.126.92 6379
65211:X 26 Sep 16:39:26.224 * +sentinel sentinel f8598202868d2cf721df04f4f5da4c1bb70ec09f 192.168.126.94 26379 @ mymaster 192.168.126.92 6379
[root@rs2 ~]# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.126.92:6379,slaves=1,sentinels=3# nfs哨兵
[root@nfs ~]# redis-sentinel /usr/local/redis/redis-4.0.0/sentinel.conf
4893:X 26 Sep 16:39:24.153 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
4893:X 26 Sep 16:39:24.153 # Redis version=4.0.0, bits=64, commit=00000000, modified=0, pid=4893, just started
4893:X 26 Sep 16:39:24.153 # Configuration loaded
4893:X 26 Sep 16:39:24.154 * Increased maximum number of open files to 10032 (it was originally set to 1024)._._                                                  _.-``__ ''-._                                             _.-``    `.  `_.  ''-._           Redis 4.0.0 (00000000/0) 64 bit.-`` .-```.  ```\/    _.,_ ''-._                                   (    '      ,       .-`  | `,    )     Running in sentinel mode|`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379|    `-._   `._    /     _.-'    |     PID: 4893`-._    `-._  `-./  _.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |           http://redis.io        `-._    `-._`-.__.-'_.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |                                  `-._    `-._`-.__.-'_.-'    _.-'                                   `-._    `-.__.-'    _.-'                                       `-._        _.-'                                           `-.__.-'                                               4893:X 26 Sep 16:39:24.156 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4893:X 26 Sep 16:39:24.157 # Sentinel ID is f8598202868d2cf721df04f4f5da4c1bb70ec09f
4893:X 26 Sep 16:39:24.157 # +monitor master mymaster 192.168.126.92 6379 quorum 2
4893:X 26 Sep 16:39:24.160 * +slave slave 192.168.126.93:6379 192.168.126.93 6379 @ mymaster 192.168.126.92 6379
4893:X 26 Sep 16:39:25.402 * +sentinel sentinel b52bd0f340f84ee933fb0314143105bdaa91f608 192.168.126.92 26379 @ mymaster 192.168.126.92 6379
4893:X 26 Sep 16:39:26.051 * +sentinel sentinel 68cd3bb1de8d21777f81a838050541dec642577a 192.168.126.93 26379 @ mymaster 192.168.126.92 6379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.126.92:6379,slaves=1,sentinels=3

验证redis故障自动主从切换

# 此时停掉rs1主的redis服务(模拟master节点redis故障)
# 因为redis在前台启动,直接 ctrl + c 即可停止# 查看三个哨兵的主从选举和切换日志输出信息
# rs1哨兵
5648:X 26 Sep 16:47:48.678 # +sdown master mymaster 192.168.126.92 6379
5648:X 26 Sep 16:47:48.778 # +new-epoch 1
5648:X 26 Sep 16:47:48.779 # +vote-for-leader 68cd3bb1de8d21777f81a838050541dec642577a 1
5648:X 26 Sep 16:47:49.392 # +config-update-from sentinel 68cd3bb1de8d21777f81a838050541dec642577a 192.168.126.93 26379 @ mymaster 192.168.126.92 6379
5648:X 26 Sep 16:47:49.392 # +switch-master mymaster 192.168.126.92 6379 192.168.126.93 6379
5648:X 26 Sep 16:47:49.392 * +slave slave 192.168.126.92:6379 192.168.126.92 6379 @ mymaster 192.168.126.93 6379
5648:X 26 Sep 16:48:19.396 # +sdown slave 192.168.126.92:6379 192.168.126.92 6379 @ mymaster 192.168.126.93 6379# rs2哨兵
65211:X 26 Sep 16:47:48.722 # +sdown master mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:48.774 # +odown master mymaster 192.168.126.92 6379 #quorum 3/2
65211:X 26 Sep 16:47:48.774 # +new-epoch 1
65211:X 26 Sep 16:47:48.774 # +try-failover master mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:48.776 # +vote-for-leader 68cd3bb1de8d21777f81a838050541dec642577a 1
65211:X 26 Sep 16:47:48.779 # f8598202868d2cf721df04f4f5da4c1bb70ec09f voted for 68cd3bb1de8d21777f81a838050541dec642577a 1
65211:X 26 Sep 16:47:48.779 # b52bd0f340f84ee933fb0314143105bdaa91f608 voted for 68cd3bb1de8d21777f81a838050541dec642577a 1
65211:X 26 Sep 16:47:48.848 # +elected-leader master mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:48.848 # +failover-state-select-slave master mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:48.925 # +selected-slave slave 192.168.126.93:6379 192.168.126.93 6379 @ mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:48.925 * +failover-state-send-slaveof-noone slave 192.168.126.93:6379 192.168.126.93 6379 @ mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:48.981 * +failover-state-wait-promotion slave 192.168.126.93:6379 192.168.126.93 6379 @ mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:49.290 # +promoted-slave slave 192.168.126.93:6379 192.168.126.93 6379 @ mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:49.290 # +failover-state-reconf-slaves master mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:49.390 # +failover-end master mymaster 192.168.126.92 6379
65211:X 26 Sep 16:47:49.390 # +switch-master mymaster 192.168.126.92 6379 192.168.126.93 6379
65211:X 26 Sep 16:47:49.390 * +slave slave 192.168.126.92:6379 192.168.126.92 6379 @ mymaster 192.168.126.93 6379
65211:X 26 Sep 16:48:19.402 # +sdown slave 192.168.126.92:6379 192.168.126.92 6379 @ mymaster 192.168.126.93 6379# rs3哨兵
4893:X 26 Sep 16:47:48.697 # +sdown master mymaster 192.168.126.92 6379
4893:X 26 Sep 16:47:48.779 # +new-epoch 1
4893:X 26 Sep 16:47:48.780 # +vote-for-leader 68cd3bb1de8d21777f81a838050541dec642577a 1
4893:X 26 Sep 16:47:48.789 # +odown master mymaster 192.168.126.92 6379 #quorum 2/2
4893:X 26 Sep 16:47:48.789 # Next failover delay: I will not start a failover before Sun Sep 26 16:53:49 2021
4893:X 26 Sep 16:47:49.393 # +config-update-from sentinel 68cd3bb1de8d21777f81a838050541dec642577a 192.168.126.93 26379 @ mymaster 192.168.126.92 6379
4893:X 26 Sep 16:47:49.393 # +switch-master mymaster 192.168.126.92 6379 192.168.126.93 6379
4893:X 26 Sep 16:47:49.393 * +slave slave 192.168.126.92:6379 192.168.126.92 6379 @ mymaster 192.168.126.93 6379
4893:X 26 Sep 16:48:19.473 # +sdown slave 192.168.126.92:6379 192.168.126.92 6379 @ mymaster 192.168.126.93 6379
# 三个哨兵输出信息基本相同,发现rs1的redis无法连接最后选举192.168.126.93即rs2为主# 查看rs2的redis是否为主
[root@rs2 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:master     # 主
connected_slaves:0
master_replid:8e7da4b9c5b36e33f14996827b69b581eac8033f
master_replid2:80a249e16ade10c26fa40b9efceccaca10468d7c
master_repl_offset:162366
second_repl_offset:102856
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:162366
[root@rs2 ~]# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.126.93:6379,slaves=1,sentinels=3  # 是自己# 此时手动启动rs1的redis服务,便会将其自动加入到以rs2为主的从,并同步主的数据
[root@rs1 ~]# redis-server /usr/local/redis/redis-4.0.0/redis.conf# 查看任意哨兵的信息
65211:X 26 Sep 16:54:41.927 * +convert-to-slave slave 192.168.126.92:6379 192.168.126.92 6379 @ mymaster 192.168.126.93 6379    # 意思是作为rs2的主# 查看任一redis日志信息
62918:M 26 Sep 16:54:42.671 * Slave 192.168.126.92:6379 asks for synchronization
62918:M 26 Sep 16:54:42.672 * Partial resynchronization request from 192.168.126.92:6379 accepted. Sending 188964 bytes of backlog starting from offset 1.  # 将主rs2的数据同步到现在作为从的rs1上# 查看rs1的状态
[root@rs1 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave      # 从
master_host:192.168.126.93
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:226968
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:8e7da4b9c5b36e33f14996827b69b581eac8033f
master_replid2:80a249e16ade10c26fa40b9efceccaca10468d7c
master_repl_offset:0
second_repl_offset:1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0[root@rs1 ~]# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.126.93:6379,slaves=1,sentinels=3# 一主一从三哨兵模式就搭建成功了
# 停止rs2上的redis服务,待rs1成为主后,再启动rs2上的redis,恢复成rs1为主,rs2为从

keepalived安装及配置

[root@rs1 ~]# yum install keepalived -y
[root@rs1 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id LVS_DEVEL
}vrrp_script check_redis {script "/etc/keepalived/check_redis.sh"   #要执行的脚本interval 1      # 执行脚本间隔时间
}vrrp_instance VI_1 {state MASTERinterface ens32virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.126.250}track_script {check_redis}
}
[root@rs1 ~]# vim /etc/keepalived/check_redis.sh
#!/bin/bash
ALIVE=`/usr/local/bin/redis-cli  PING`
if [ "$ALIVE" == "PONG" ]; thenecho $ALIVEexit 0
elseecho $ALIVEexit 1
fi
[root@rs1 ~]# systemctl start keepalived[root@rs2 ~]# yum install keepalived -y
[root@rs2 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id LVS_DEVEL
}vrrp_script check_redis {script "/etc/keepalived/check_redis.sh"interval 1
}vrrp_instance VI_1 {state BACKUPinterface ens32virtual_router_id 51priority 99advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.126.250}track_script {check_redis}
}[root@rs2 ~]# vim /etc/keepalived/check_redis.sh
#!/bin/bash
ALIVE=`/usr/local/bin/redis-cli  PING`
if [ "$ALIVE" == "PONG" ]; thenecho $ALIVEexit 0
elseecho $ALIVEexit 1
fi
[root@rs2 ~]# systemctl start keepalived# 查看rs1上的VIP是否已生成
[root@rs1 ~]# ip a | grep 192.168.126.250inet 192.168.126.250/32 scope global ens32# 使用一台装有redis的主机测试能否使用上面的VIP进行连接
[root@test ~]# ifconfig ens32 | awk 'NR==2 {print $2}'
192.168.126.120
[root@test ~]# redis-cli -h 192.168.126.250
192.168.126.250:6379> keys *
1) "name"
192.168.126.250:6379> get name
"zhangsan"
192.168.126.250:6379> exit

session会话共享配置

两台tomcat服务器的session配置

jar包获取:https://search.maven.org/

[root@ds-master ~]# ls
commons-pool2-2.2.jar    jedis-2.5.2.jar    tomcat-redis-session-manager-2.0.0.jar
[root@ds-master ~]# cp commons-pool2-2.2.jar jedis-2.5.2.jar tomcat-redis-session-manager-2.0.0.jar /usr/local/tomcat/apache-tomcat-8.0.36/lib/
[root@ds-master ~]# vim /usr/local/tomcat/apache-tomcat-8.0.36/conf/context.xml
<?xml version='1.0' encoding='utf-8'?><WatchedResource>WEB-INF/web.xml</WatchedResource><WatchedResource>${catalina.base}/conf/web.xml</WatchedResource><Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /><Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"host="192.168.126.250"   # redis的vipport="6379"         # redis端口database="0"          # redis数据库maxInactiveInterval="60"/>    # 会话缓存到redis有效时长/>
</Context># 启动
[root@ds-master ~]# /usr/local/tomcat/apache-tomcat-8.0.36/bin/startup.sh

另一台tomcat同上配置

测试

# 上面的session已写入redis服务器中
[root@test ~]# redis-cli -h 192.168.126.250
192.168.126.250:6379> keys *
1) "29C6A13CD627A5E9890BA2498C40A0D2"
2) "name"

两台php服务器的session配置

# 下载php-redis扩展插件包
[root@ds-master ~]# wget https://pecl.php.net/get/redis-4.3.0.tgz
[root@ds-master ~]# ls
redis-4.3.0.tgz
[root@ds-master ~]# mkdir /usr/local/php-redis
[root@ds-master ~]# tar -xf redis-4.3.0.tgz -C /usr/local/php-redis
# 下载编译安装所需依赖
[root@ds-master ~]# yum install php-devel gcc gcc-c++ -y
[root@ds-master ~]# cd /usr/local/php-redis/redis-4.3.0/
# 安装php-redis。使用phpize(由php软件包提供,如果没有请安装php)工具生成configure文件,编译并编译安装(安装完成模块在/usr/lib64/php/modules目录下)
[root@ds-master redis-4.3.0]# phpize
Configuring for:
PHP Api Version:         20100412
Zend Module Api No:      20100525
Zend Extension Api No:   220100525[root@ds-master redis-4.3.0]# ./configure
[root@ds-master redis-4.3.0]# make && make install
[root@ds-master redis-4.3.0]# ls /usr/lib64/php/modules/
curl.so  fileinfo.so  gd.so  json.so  mbstring.so  mysqli.so  mysql.so  pdo_mysql.so  pdo.so  pdo_sqlite.so  phar.so  redis.so  sqlite3.so  zip.so# 修改php-fpm和PHP的配置信息,使其支持redis模块,并指定session到redis服务的地址
[root@ds-master redis-4.3.0]# vim /etc/php.ini
session.save_handler = redis    # 默认有,需更改
extension_dir="/usr/lib64/php/modules/"       # 默认没有,需添加
extension=redis.so          # 默认有,被注释,直接添加
session.save_path = "tcp://192.168.126.250:6379"  # 默认有,被注释,直接添加
session.auto_start = 1    # 默认有需更改[root@ds-master redis-4.3.0]# vim /etc/php-fpm.d/www.conf
# 文件最后两行进行修改
php_value[session.save_handler] = redis
php_value[session.save_path] = tcp://192.168.126.250:6379# 重启php
[root@ds-master redis-4.3.0]# systemctl restart php-fpm

另一台php服务器同上面步骤

测试

[root@test ~]# redis-cli -h 192.168.126.250
192.168.126.250:6379> keys *
1) "name"
2) "PHPREDIS_SESSION:u4al5f23a2hvhav1ipi3j7fpk7"

记一次网站架构的搭建相关推荐

  1. 搭建“双11”大型网站架构必须掌握的 5 个核心知识

    2019独角兽企业重金招聘Python工程师标准>>> 每年电商双11大促对背后技术人都是一次大考,阿里数据库团队表示.经过9年的发展,双11单日交易额从2009年的0.5亿一路攀升 ...

  2. ASP.NET Core搭建多层网站架构【11-WebApi统一处理返回值、异常】

    ASP.NET Core搭建多层网站架构[11-WebApi统一处理返回值.异常] 参考文章: (1)ASP.NET Core搭建多层网站架构[11-WebApi统一处理返回值.异常] (2)http ...

  3. 亿级流量网站架构核心技术 跟开涛学搭建高可用高并发系统

    亿级流量网站架构核心技术 跟开涛学搭建高可用高并发系统 1.高并发原则 1.1 无状态 1.2 拆分 1.3 服务化 1.4 消息队列 1.5 数据异构 1.6 缓存银弹 1.7 并发化 2 高可用原 ...

  4. 高性能网站架构之缓存篇—Redis集群搭建

    看过 高性能网站架构之缓存篇--Redis安装配置和高性能网站架构之缓存篇--Redis使用配置端口转发 这两篇文章的,相信你已经对redis有一定的了解,并能够安装上,进行简单的使用了,但是在咱们的 ...

  5. 亿级流量网站架构核心技术 跟开涛学搭建高可用高并发系统.

    有过互联网开发经验的人员或许有这样的感受: 搭建一个设计精良.功能丰富的网站并不是一件特别困难的事情,但是搭建一个能够支持巨大流量并且运行自如的网站就不是一件轻松的事情了. 因为,随着用户规模的增长, ...

  6. 读书笔记:《亿级流量网站架构核心技术 -- 跟开涛学搭建高可用高并发系统》

    from <亿级流量网站架构核心技术 – 跟开涛学搭建高可用高并发系统> 概述 一个好的设计要做到,解决现有的需求和问题,把控实现和进度风险,预测和规划未来,不要过度设计,从迭代中演进和完 ...

  7. linux下yum搭建lamp,linux下Yum搭建lamp网站架构

    在上节课我用了源代码和免安装软件的两种方式搭建了LAMP架构的网站,今天我们对上一节做个简单的总结: 源代码安装软件是我们Linux下常用的安装方法共分四个步骤: 在上一节我们的数据库就是免安装的.直 ...

  8. 我的网站之一(搭建网站架构)

    前言 自己在博客园也游历了一年左右,对博客园中博友们发的博文每天也是多多少少也看了不少,自己也从中获益不少.因为自己现在是在做.net网站的,所以对网站也是多多宜善.也看到许多大神们自己的开源网站.开 ...

  9. 大型网站架构演变和知识体系

    存爱好,作为收藏,原地址:http://www.blogjava.net/BlueDavy/archive/2008/09/03/226749.html ,同时向原创致敬 之前也有一些介绍大型网站架构 ...

最新文章

  1. SQL2005合理的索引设计
  2. C++ Boost库初步使用 - 使用CFree
  3. warning:This application is modifying the autolayout engine from a background thread
  4. selector的使用
  5. 计算机文件系统小结,文件系统总结
  6. 编程没点为什么,生活就是十万个为什么
  7. 如何同时将多张图片进行批量无损压缩、调整尺寸及调整大小
  8. h3c交换机限制端口访问_勒索病毒,华为/H3C三层交换机/路由器用ACL访问控制实现端口禁用...
  9. BugTracker配置
  10. Vim中文本全部选中
  11. 基于DAMO-YOLO的RepGFPN多尺度特征融合的YOLOv5、YOLOv7、Faster RCNN、FCOS、CenterNet等目标检测器改进
  12. AST反混淆实战:猿人学爬虫比赛第二题详细题解
  13. Unity打开电脑本地文件夹选择图片替换
  14. Emmet语法的使用
  15. python-numpy-pandas
  16. 什么是SEO搜索引擎优化?如何实现?
  17. 使用晨曦记账本,认识记账的重要性
  18. 【诺贝尔物理奖量子纠缠】启发:命由我作,福由我求
  19. PG 利用FDW的水平分片
  20. 解决windows系统powershell命令行无法使用代理的问题

热门文章

  1. 利用计算机协助诈骗,侵犯公民个人信息罪与诈骗罪的竞合吗?
  2. 网页开发可以使用多种编程语言。以下是一些常用的编程语言及其优缺点
  3. 去除、添加 Windows7 桌面的 IE 图标
  4. 关于opencv中 THRESH_TRUNC 参数的疑惑
  5. 杭州内推 | 阿里巴巴CRO线招聘语音方向高级算法工程师
  6. IP地址虚拟网络与虚拟机网络配置
  7. 稀疏Softmax(Sparse Softmax)
  8. python svr回归_python机器学习库scikit-learn:SVR的基本应用
  9. 融云 及时通讯云服务平台
  10. Web jsp开发学习——网上直播聊天室的简单开发