MySQL数据库企业集群项目实战(阶段三)
作者 |
刘畅 |
时间 |
2020-10-25 |
目录
1 架构拓扑图
1.1 方案一
1.2 方案二
mycat可以实现对只读从库的负载均衡功能。
1.3 方案三
使用MySQL代理中间件的目的是为了减少数据库分片集群开发。
2 环境规划
主机名 |
IP地址 |
服务 |
用途 |
软件版本 |
Web |
eth1: 172.16.1.10 |
LNMP |
wordpress PHP网站测试 |
wordpress: nginx-1.19.1 PHP: php-7.2.19 |
MyCAT-Master |
eth1: 172.16.1.211 VIP: 172.16.1.200 |
MyCAT+Keepalived |
MyCAT主服务器 |
MyCAT: Mycat-server-1.6.7.4 |
MyCAT-Backup |
eth1: 172.16.1.212 |
MyCAT+Keepalived |
MyCAT备服务器 |
MyCAT: Mycat-server-1.6.7.4 |
LVS-Master01 |
eth1: 172.16.1.213 VIP: 172.16.1.201 |
LVS+Keepalived |
四层负载均衡01 |
|
LVS-Master02 |
eth1: 172.16.1.214 VIP: 172.16.1.202 |
LVS+Keepalived |
四层负载均衡02 |
|
MySQL-Master |
eth1: 172.16.1.215 VIP: 172.16.1.203 |
MySQL Master + Keepalived |
业务写,主服务器 |
MySQL: 5.7.31 密码: mysql5.7@2020 |
MySQL-Backup |
eth1: 172.16.1.216 |
MySQL Slave + MySQL Keepalived |
备服务器 |
MySQL: 5.7.31 密码: mysql5.7@2020 |
MySQL-Slave01 |
eth1: 172.16.1.217 |
MySQL Slave |
业务读,读服务器 |
MySQL: 5.7.31 密码: mysql5.7@2020 |
MySQL-Slave02 |
eth1: 172.16.1.218 |
MySQL Slave |
业务读,读服务器 |
MySQL: 5.7.31 密码: mysql5.7@2020 |
环境说明:
关闭selinux和iptables,服务器已优化。
3 集群部署
这个项目重点不是学习MyCAT,也许对于你们公司业务,这种架构不是最优的。
要学习的是架构思路和其中解决方案,比如读写分离怎么实现的、怎么做双机热备、多从怎么提供服务,怎么解决单点故障、怎么能提高并发性能等问题。
当然,如果生产环境用的就是MyCAT,那么你可以省略LVS负载均衡和MySQL主备+Keepalived,使用自身的。
从后向前部署。
3.1 MySQL一主多从
1 解压二进制MySQL包
在172.16.1.215、172.16.1.216、172.16.1.217、172.16.1.218节点上进行操作。
(1) 安装依赖包
MySQL依赖libaio库,如果没有安装,则数据目录初始化和服务器启动将失败。
# yum install libaio -y
(2) 解压数据库
# tar -xzf mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz
# mv mysql-5.7.31-linux-glibc2.12-x86_64/ /usr/local/mysql/
(3) 创建mysql用户
# groupadd -g 1600 mysql
# useradd -g mysql -u 1600 -M -s /sbin/nologin mysql
# id mysql
uid=1600(mysql) gid=1600(mysql) 组=1600(mysql)
(4) 创建存放数据库文件的目录并赋予mysql安装目录的属主和属组都是mysql
# mkdir -p /usr/local/mysql/data/
# chown -R mysql.mysql /usr/local/mysql/
(5) 创建配置文件
# cat /etc/my.cnf
[client]
port = 3306
default-character-set = utf8
socket = /usr/local/mysql/data/mysql.sock
[mysql]
no-auto-rehash
[mysqld]
user = mysql
port = 3306
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
socket = /usr/local/mysql/data/mysql.sock
bind-address = 0.0.0.0
pid-file = /usr/local/mysql/data/mysqld.pid
character-set-server = utf8
collation-server = utf8_general_ci
log-error = /usr/local/mysql/data/mysqld.log
slow_query_log = ON
long_query_time = 2
slow_query_log_file = /usr/local/mysql/data/mysql-slow.log
max_connections = 10240
open_files_limit = 65535
innodb_buffer_pool_size = 1G
innodb_flush_log_at_trx_commit = 2
innodb_log_file_size = 256M
transaction_isolation = READ-COMMITTE
default-storage-engine = innodb
innodb_file_per_table = on
symbolic-links = 0
explicit_defaults_for_timestamp = 1
skip-name-resolve
lower_case_table_names = 1
[mysqldump]
quick
max_allowed_packet = 32M
# 注意:172.16.1.215、172.16.1.216、172.16.1.217、172.16.1.218节点的server-id分别设置为1、2、3、4。
(6) 初始mysql数据库
# /usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
Type=forking
PIDFile=/usr/local/mysql/data/mysqld.pid
TimeoutSec=0
PermissionsStartOnly=true
# ExecStartPre=/usr/local/mysql/bin/mysqld_pre_systemd
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --daemonize --pid-file=/usr/local/mysql/data/mysqld.pid $MYSQLD_OPTS
EnvironmentFile=-/etc/sysconfig/mysql
LimitNOFILE = 65535
Restart=on-failure
RestartPreventExitStatus=1
PrivateTmp=false
# systemctl daemon-reload
(9) 将mysql执行命令加入到环境变量中
# cat >> /etc/profile << EOF
export PATH=/usr/local/mysql/bin/:$PATH
EOF
# source /etc/profile
(10) 启动数据库
# systemctl start mysqld.service
# systemctl enable mysqld.service
# netstat -tunlp | grep mysqld
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN mysqld
(11) 修改mysql root用户密码
# grep 'temporary password' /usr/local/mysql/data/mysqld.log
2020-10-25T07:35:34.271950Z 1 [Note] A temporary password is generated for root@localhost: S_.q!udm,0Q?
# mysql -uroot -p'S_.q!udm,0Q?'
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'mysql5.7@2020';
mysql> flush privileges;
2 MySQL-Master
在172.16.1.215节点上操作
(1) 修改/etc/my.cnf
# vim /etc/my.cnf
[mysqld]
server-id = 1
log-bin = /usr/local/mysql/data/mysql-bin
binlog_cache_size = 4M
binlog_format = mixed
max_binlog_cache_size = 8M
max_binlog_size = 512M
expire_logs_days = 14
gtid_mode = ON
enforce_gtid_consistency = ON
(2) 重启mysql数据库
(3) 创建复制账户
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.16.1.%' IDENTIFIED BY 'repl@2020';
mysql> flush privileges;
(4) 查看gtid
mysql> show global variables like "%gtid%";
3 MySQL-Backup
在172.16.1.216节点上操作
# vim /etc/my.cnf
[mysqld]
server-id = 2
slave-skip-errors=1007,1022,1050,1062,1169
relay-log=/usr/local/mysql/data/relay-log
max_relay_log_size=512M
relay-log-purge=ON
gtid_mode = ON
enforce_gtid_consistency = ON
log-bin = mysql-bin
log_slave_updates = ON
slave-parallel-type = LOGICAL_CLOCK
slave-parallel-workers = 8
master-info-repository = TABLE
relay-log-info-repository = TABLE
(2) 重启mysql数据库
# systemctl restart mysqld
(3) 配置复制连接
mysql> CHANGE MASTER TO
MASTER_HOST='172.16.1.215',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='repl@2020',
MASTER_AUTO_POSITION=1;
(4) 启动复制线程
mysql> start slave;
(5) 查看复制状态
mysql> show slave statusG;
mysql> show processlist;
4 Keepalived高可用软件介绍
(1) 内核版本要求:linux内核2.4.19+
(2) Keepalived是一个可以快速构建高可用服务的解决方案。设计之初是针对LVS负载均衡提供高可用的,它集成对LVS集群管理,包括健康检查、故障剔除等功能。
Keepalived使用VRRP协议实现主备模式,当主服务器发生故障,备服务器接管。
(3) 工作原理:
VRRP实例中分为MASTER和BACKUP状态,组成一个热备组,MASTER状态及优先级高的服务器绑定一个虚拟IP(VIP),这个VIP对外提供服务。
热备组内服务器周期性发送VRRP通告信息,一方面BACKUP服务器确定MASTER是否存活,另一方面进行MASTER选举。如果MASTER宕机,BACKUP切换到MASTER状态,接管VIP,对外提供服务;当MASTER恢复后会自动加入热备组切换到MASTER状态,接管VIP,对外提供服务。
(4) VRRP(VIrtual Route Redundancy Protocol):虚拟路由冗余协议,解决局域网中配置静态网关出现单点失效现象的路由协议。
(5) 什么情况下使用高可用
1) 不允许暂停服务。
2) 单台Nginx Web服务器
3) 网站流量入口,比如反向代理、负载均衡
# HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
5 MySQL+Keepalived主备
(1) 安装keepalived
在172.16.1.215、172.16.1.216节点上进行操作
# yum install keepalived -y
在172.16.1.215节点上进行操作
1) 备份原始keepalived配置文件
# mv /etc/keepalived/keepalived.conf{,.bak}
2) keepalived.conf配置文件
# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id MYSQL_HA
}
# 自定义资源监控脚本,监控mysql服务
vrrp_script check_mysql {
script "/etc/keepalived/check_mysql.sh"
# 每2秒执行一次脚本
interval 2
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state BACKUP
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 51
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 150
# 检查的时间间隔,默认1s
advert_int 1
################################################################################################
# 设置为不抢占
# 通常如果master服务死掉后backup会变成master,但是当master服务又好了的时候master此时会抢占VIP,
# 这样就会发生两次切换对业务繁忙的网站来说是不好的。所以我们要在配置文件加入nopreempt非抢占,
# 但是这个参数只能用于state为backup,故我们在用HA的时候最好master和backup的state都设置成backup
# 让其通过priority(优先级)来竞争。
################################################################################################
nopreempt
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.203/24 dev eth1 label eth1:1
}
# 调用定义的vrrp_script脚本去监控资源,定义在实例之内,脚本可被多个实例调用
track_script {
check_mysql
}
}
3) mysql状态监测脚本
# cat /etc/keepalived/check_mysql.sh
#!/bin/bash
source /etc/profile
IP_LIST="172.16.1.215"
IP_PORT="3306"
for IP in $IP_LIST; do
FAIL_COUNT=0
for ((i=1; i<=3; i++)); do
echo quit | timeout --signal=9 3 telnet $IP $IP_PORT 2>&1 | grep "Connected to $IP" &>/dev/null
if [ $? -eq 0 ]; then
break
else
# echo "$URL retry $FAIL_COUNT"
let FAIL_COUNT++
fi
done
if [ $FAIL_COUNT -eq 3 ]; then
/usr/bin/kill -9 $(cat /var/run/keepalived.pid)
fi
done
# chmod +x /etc/keepalived/check_mysql.sh
# systemctl start keepalived
(3) 从服务器配置
在172.16.1.216节点上进行操作
1) 备份原始keepalived配置文件
# mv /etc/keepalived/keepalived.conf{,.bak}
2) keepalived.conf配置文件
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id MYSQL_HA
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state BACKUP
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 51
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 100
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.203/24 dev eth1 label eth1:1
}
# 节点变为master时执行发送邮件的脚本
notify_master /etc/keepalived/send_mail.sh
}
3) 当主宕机,vip飘到备份服务器时,发送邮件的脚本
# cat /etc/keepalived/send_mail.sh
#!/bin/bash
source /etc/profile
# 配置邮件服务器
# yum install mailx -y
# vim /etc/mail.rc
# set from=hyjy2504164765@163.com smtp=smtp.163.com
# set smtp-auth-user=hyjy2504164765@163.com smtp-auth-password=linux123
# set smtp-auth=login
# 测试,163邮箱服务器需要开启 pop3 smtp 服务,并客户端授权密码
# echo "this is test mail." | mail -s "monitor test" 2504164765@qq.com
function check_mysql() {
IP_LIST="172.16.1.216"
IP_PORT="3306"
for IP in $IP_LIST; do
FAIL_COUNT=0
for ((i=1; i<=3; i++)); do
echo quit | timeout --signal=9 3 telnet $IP $IP_PORT 2>&1 | grep "Connected to $IP" &>/dev/null
if [ $? -eq 0 ]; then
echo "mysql-backup mysql status is running"
break
else
# echo "$URL retry $FAIL_COUNT"
let FAIL_COUNT++
fi
done
if [ $FAIL_COUNT -eq 3 ]; then
echo "mysql-backup mysql status is down"
fi
done
}
to="2504164765@qq.com"
subject="MYSQL keepalived up on backup"
body="mysql-master服务器宕机!!! mysql-backup变为master!!! `check_mysql`"
FILE=/tmp/mail.tmp
echo "$body" > $FILE
dos2unix -k $FILE &>/dev/null
# 解决正文变成附件.bin
mail -s "$subject" "$to" < $FILE
# chmod +x /etc/keepalived/send_mail.sh
4) 启动keepalived
# systemctl start keepalived
1) 主备两边的STATE参数都设置为BACKUP,因为nopreempt(不抢占)只支持在BACKUP模式下,只有主服务器设置nopreempt,当主服务器挂了,备份服务器接管vip资源,主修复好启动后,不抢占备的vip资源,除非备挂了。
2) 当主服务器挂了(mysqld和keepalived都停止),备服务器接管资源后
A、备当做主服务器使用,待relaylog回放完成后,执行reset slave;命令清空slave复制信息。
使用xtrabackup方式对库进行备份。
B、原主服务器当作备服务器使用,清空data数据目录,修改/etc/my.cnf,开启relaylog日志和
relaylog回放到binlog的参数,还原xtrabackup库备份,启动数据库执行reset master; reset slave;清空主从复制信息,再配置主从同步,启动keepalived即可。
3) 为了防止主备不一致,主备服务器上的keepalived软件不设置开机自启动(下面实验
中keepalived也设置开机不自启动)。
6 MySQL-Slave01
在172.16.1.217节点上操作
(1) 修改/etc/my.cnf
# vim /etc/my.cnf
[mysqld]
server-id = 3
slave-skip-errors=1007,1022,1050,1062,1169
relay-log=/usr/local/mysql/data/relay-log
max_relay_log_size=512M
relay-log-purge=ON
read-only
gtid_mode = ON
enforce_gtid_consistency = ON
slave-parallel-type = LOGICAL_CLOCK
slave-parallel-workers = 8
master-info-repository = TABLE
relay-log-info-repository = TABLE
(2) 重启mysql数据库
# systemctl restart mysqld
(3) 配置复制连接
mysql> CHANGE MASTER TO
MASTER_HOST='172.16.1.203',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='repl@2020',
MASTER_AUTO_POSITION=1;
# 注意:连接虚拟IP。
(4) 启动复制线程
mysql> start slave;
(5) 查看复制状态
mysql> show slave statusG;
mysql> show processlist;
7 MySQL-Slave02
在172.16.1.218节点上操作
(1) 修改/etc/my.cnf
# vim /etc/my.cnf
[mysqld]
server-id = 4
slave-skip-errors=1007,1022,1050,1062,1169
relay-log=/usr/local/mysql/data/relay-log
max_relay_log_size=512M
relay-log-purge=ON
read-only
gtid_mode = ON
enforce_gtid_consistency = ON
slave-parallel-type = LOGICAL_CLOCK
slave-parallel-workers = 8
master-info-repository = TABLE
relay-log-info-repository = TABLE
(2) 重启mysql数据库
# systemctl restart mysqld
(3) 配置复制连接
mysql> CHANGE MASTER TO
MASTER_HOST='172.168.1.203',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='repl@2020',
MASTER_AUTO_POSITION=1;
# 注意:连接虚拟IP。
(4) 启动复制线程
mysql> start slave;
(5) 查看复制状态
mysql> show slave statusG;
mysql> show processlist;
8 测试
(1) 查看172.16.1.215 mysql主库上的vip
(2) 关闭172.16.1.215 mysql主库
[root@mysql-master ~]# systemctl stop mysqld
(3) 172.16.1.215 mysql主库上的keepalived服务被kill掉
(4) vip转移到172.16.1.216 mysql备库上
(5) 报警邮箱接收到报警
(6) 查看172.16.1.127从库状态
可以发现从库的Master_UUID: aa7489a2-1694-11eb-9b82-000c299c9831(这是主库的uuid)变为Master_UUID: 7b59201e-1696-11eb-ab21-000c29b9ac88(这是备库的uuid)。
9 小结
(1) 程序必须有数据库重连机制。
(2) 每个服务器设置唯一ID。否则主备切换会报错:Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids;
(3) log_slave_updates = ON # 最好加上,binlog记录从主回放的SQL,备替换主后,可能会有好处。
(4) 主服务器故障,切换备服务器,此时从服务器会延迟几秒故障后新增加的数据。因为备服务器在与主服务器连接不上时,会过秒重试连接,一旦连接上会自动跟上复制。
(5) 主备切换需要3秒左右。
(6) 双主架构建议
3.2 从服务器LVS四层负载均衡
采用LVS DR模式
1 安装ipvsadm、keepalived
在172.16.1.213、172.16.1.214节点上操作
# yum install keepalived ipvsadm -y
说明:
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。ipvsadm是在负载调度器上使用的LVS群集管理工具,通过调用ip_vs模块来添加、删除服务器节点,以及查看群集的运行状态。
2 LVS-Master01
(1) 备份keepalive原始配置文件
# mv /etc/keepalived/keepalived.conf{,.bak}
(2) 修改keepalived.conf配置文件
# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id LVS_RR
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state MASTER
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 52
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 150
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.201/24 dev eth1 label eth1:1
}
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_2 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state BACKUP
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 53
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 100
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.202/24 dev eth1 label eth1:2
}
# 节点变为master时执行发送邮件的脚本
notify_master /etc/keepalived/send_mail.sh
}
#########################################################
# 虚拟服务器virtual_server定义块,该部分是用来管理LVS的,
# 是实现keepalived和LVS相结合的模块,real_server是该模块
# 的子模块,可设置多个。
#########################################################
# VIP地址,要和vrrp_instance模块中的virtual_ipaddress地址一致
virtual_server 172.16.1.201 3306 {
# 健康检查时间间隔
delay_loop 6
# lvs调度算法rr、wrr、lc、wlc、lblc、sh、dh
lb_algo rr
# 负载均衡转发规则NAT|DR|RUN
lb_kind DR
# 使用的协议
protocol TCP
# RS的真实IP地址
real_server 172.16.1.217 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
# RS的真实IP地址
real_server 172.16.1.218 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
}
# VIP地址,要和vrrp_instance模块中的virtual_ipaddress地址一致
virtual_server 172.16.1.202 3306 {
# 健康检查时间间隔
delay_loop 6
# lvs调度算法rr、wrr、lc、wlc、lblc、sh、dh
lb_algo rr
# 负载均衡转发规则NAT|DR|RUN
lb_kind DR
# 使用的协议
protocol TCP
# RS的真实IP地址
real_server 172.16.1.217 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
# RS的真实IP地址
real_server 172.16.1.218 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
}
# cat /etc/keepalived/send_mail.sh
#!/bin/bash
source /etc/profile
# 配置邮件服务器
# yum install mailx -y
# vim /etc/mail.rc
# set from=hyjy2504164765@163.com smtp=smtp.163.com
# set smtp-auth-user=hyjy2504164765@163.com smtp-auth-password=linux123
# set smtp-auth=login
# 测试,163邮箱服务器需要开启 pop3 smtp 服务,并客户端授权密码
# echo "this is test mail." | mail -s "monitor test" 2504164765@qq.com
to="2504164765@qq.com"
subject="lvs keepalived up on backup"
body="lvs-master02服务器宕机!!! lvs-master01变为master!!!"
FILE=/tmp/mail.tmp
echo "$body" > $FILE
dos2unix -k $FILE &>/dev/null
# 解决正文变成附件.bin
mail -s "$subject" "$to" < $FILE
# chmod +x /etc/keepalived/send_mail.sh
# systemctl start keepalived.service
3 LVS-Master02
在172.16.1.214节点上操作
(1) 备份keepalive原始配置文件
# mv /etc/keepalived/keepalived.conf{,.bak}
(2) 修改keepalived.conf配置文件
# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id LVS_RR
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state BACKUP
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 52
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 100
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.201/24 dev eth1 label eth1:1
}
# 节点变为master时执行发送邮件的脚本
notify_master /etc/keepalived/send_mail.sh
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_2 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state MASTER
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 53
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 150
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.202/24 dev eth1 label eth1:2
}
}
#########################################################
# 虚拟服务器virtual_server定义块,该部分是用来管理LVS的,
# 是实现keepalived和LVS相结合的模块,real_server是该模块
# 的子模块,可设置多个。
#########################################################
# VIP地址,要和vrrp_instance模块中的virtual_ipaddress地址一致
virtual_server 172.16.1.201 3306 {
# 健康检查时间间隔
delay_loop 6
# lvs调度算法rr、wrr、lc、wlc、lblc、sh、dh
lb_algo rr
# 负载均衡转发规则NAT|DR|RUN
lb_kind DR
# 使用的协议
protocol TCP
# RS的真实IP地址
real_server 172.16.1.217 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
# RS的真实IP地址
real_server 172.16.1.218 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
}
# VIP地址,要和vrrp_instance模块中的virtual_ipaddress地址一致
virtual_server 172.16.1.202 3306 {
# 健康检查时间间隔
delay_loop 6
# lvs调度算法rr、wrr、lc、wlc、lblc、sh、dh
lb_algo rr
# 负载均衡转发规则NAT|DR|RUN
lb_kind DR
# 使用的协议
protocol TCP
# RS的真实IP地址
real_server 172.16.1.217 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
# RS的真实IP地址
real_server 172.16.1.218 3306 {
# 四层健康检查
TCP_CHECK {
connect_port 3306 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
}
(3) 创建邮件发送脚本
# cat /etc/keepalived/send_mail.sh
#!/bin/bash
source /etc/profile
# 配置邮件服务器
# yum install mailx -y
# vim /etc/mail.rc
# set from=hyjy2504164765@163.com smtp=smtp.163.com
# set smtp-auth-user=hyjy2504164765@163.com smtp-auth-password=linux123
# set smtp-auth=login
# 测试,163邮箱服务器需要开启 pop3 smtp 服务,并客户端授权密码
# echo "this is test mail." | mail -s "monitor test" 2504164765@qq.com
to="2504164765@qq.com"
subject="lvs keepalived up on backup"
body="lvs-master01服务器宕机!!! lvs-master02变为master!!!"
FILE=/tmp/mail.tmp
echo "$body" > $FILE
dos2unix -k $FILE &>/dev/null
# 解决正文变成附件.bin
mail -s "$subject" "$to" < $FILE
# chmod +x /etc/keepalived/send_mail.sh
(4) 开启keepalived服务
# systemctl start keepalived.service
4 MySQL-Slave
后端MySQL所有从服务器绑定VIP,在172.16.1.217、218节点上操作
(1) 配置脚本
# cat /root/lvs-dr-real.sh
#!/bin/bash
source /etc/profile
VIP1=172.16.1.201
VIP2=172.16.1.202
NIC1="lo:0"
NIC2="lo:1"
case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $NIC1 $VIP1 netmask 255.255.255.255 broadcast $VIP1 up
ifconfig $NIC2 $VIP2 netmask 255.255.255.255 broadcast $VIP2 up
route add -host $VIP1 dev $NIC1
route add -host $VIP2 dev $NIC2
;;
stop)
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $NIC1 down
ifconfig $NIC2 down
;;
status)
if ifconfig $NIC1 |grep $VIP1 &> /dev/null; then
echo "$NIC1 is configured."
else
echo "$NIC1 not configured."
fi
if ifconfig $NIC2 |grep $VIP2 &> /dev/null; then
echo "$NIC2 is configured."
else
echo "$NIC2 not configured."
fi
;;
*)
echo "Usage: $0 {start|stop|status}"
exit 1
esac
(2) 启动脚本
# chmod +x /root/lvs-dr-real.sh
# /root/lvs-dr-real.sh start
(3) 查看本地环回网卡多了两个vip地址
(4) 将脚本加入到开机自启动
# chmod +x /etc/rc.d/rc.local
# echo "/root/lvs-dr-real.sh start" >> /etc/rc.local
5 测试
(1) 查看172.16.1.213、214节点的vip地址
1) 172.16.1.213
2) 172.16.1.214
(2) 为了方便测试,在172.16.1.215主库上创建可以远程连接mysql的root用户,备库和从库会复制主库的操作,创建该root用户。
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'172.16.1.%' IDENTIFIED BY 'mysql5.7@2020' WITH GRANT OPTION;
mysql> flush privileges;
(3) 在172.16.1.10节点上操作
1) 安装mysql客户端
# yum install mysql -y
2) 执行如下命令连接172.16.1.201、202 vip地址连接从mysql
# mysql -h172.16.1.201 -P3306 -uroot -pmysql5.7@2020
# mysql -h172.16.1.201 -P3306 -uroot -pmysql5.7@2020
# mysql -h172.16.1.201 -P3306 -uroot -pmysql5.7@2020
# mysql -h172.16.1.202 -P3306 -uroot -pmysql5.7@2020
# mysql -h172.16.1.202 -P3306 -uroot -pmysql5.7@2020
# mysql -h172.16.1.202 -P3306 -uroot -pmysql5.7@2020
(4) 查看lvs信息
1) 在172.16.1.213节点上查看lvs信息
# ipvsadm -Ln
(5) 故障测试
1) 关闭172.16.1.213节点的keepalived服务
[root@lvs-master01 ~]# systemctl stop keepalived.service
2) 查看172.16.1.214节点的vip地址
3) 接收到报警邮件
(6) 说明
1) 为防止keepalived资源竞争问题,keepalived服务设置开机不自启动。
2) lvs-master01和lvs-master02是互为主备的作用,其中一台机器挂了,另一台机器就会接管对方的vip地址。
3.3 MyCAT中间件数据库读写分离
1 数据库读写分离方案
数据库读写分离对于大型系统或者访问量很高的互联网应用来说,是必不可少的一个重要功能。
从数据库的角度,对于大多数应用来说,从集中到分布,最基本的一个需求不是数据库存储的瓶颈,而是在于计算的瓶颈,即SQL查询的瓶颈。
我们知道,正常情况下,Insert语句毫秒级写入完成,而系统中的大多数Select语句则要几秒到几分钟才能有结果,很多复杂的SQL消耗很多的服务器CPU及磁盘IO。很可能在高峰期导致数据库服务器爆表,系统陷入瘫痪,严重情况下可能导致数据库崩溃。因此,我们应该尽量避免数据库单点和处理性能。
对于MySQL来说,读写分离基于主从模式,一个写节点后面跟多个读节点,读节点的数量取决于系统的数据库压力。
对于数据库实时性不是特别严格的应用,只需要通过廉价的PC服务器来扩展Slave的数量,将读压力分散到多台从的服务器上,来解决读性能瓶颈,毕竟大多数数据库应用系统中的读压力要比写压力大很多。
数据库代理中间件完全对客户端透明。
项目名称 |
负责公司 |
网址 |
说明 |
状态 |
MySQL-Proxy |
官方 |
|
内测项目 |
停止更新 |
Amoeba |
|
|
|
停止更新 |
MyCAT |
社区 |
http://mycat.org.cn/ |
基于Cobar |
活跃 |
Cobar |
阿里巴巴 |
https://github.com/alibaba/cobar |
基于Amoeba |
停止更新 |
Atlas |
奇虎360 |
https://github.com/Qihoo360/Atlas |
基于MySQL-Proxy |
停止更新 |
开源项目很多,坚持下来的少之又少(可能资金断,也可能短期看不懂红利),MyCAT前仆后继。
# mycat稳定版下载地址
http://dl.mycat.org.cn/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
# mycat参考手册
http://www.mycat.org.cn/document/mycat-definitive-guide.pdf
2 MyCAT数据库读写分离配置
(1) 在172.16.1.215主库上创建两个数据库用于实验
[root@mysql-master ~]# mysql -uroot -pmysql5.7@2020
mysql> create database wp character set utf8 collate utf8_bin;
# 说明:该库用于后面lnmp环境,wordpress系统的库。
mysql> create database liuchang character set utf8 collate utf8_bin;
# 说明:测试库
(2)
生产案例:简单的读写分离类型(只是读写分离支持)
MyCAT简单的一类Proxy。只要在schema.xml中的元素上增加dataNode=“defaultDN”属性,并配置此dataNode对应的真实物理数据库的database,然后dataHost开启读写分离功能即可。
在172.16.1.211、212节点上进行操作
(3) 安装jdk(mycat依赖于java环境)
# tar -xzf jdk-8u45-linux-x64.tar.gz
# mv jdk1.8.0_45/ /usr/local/jdk
# cat >> /etc/profile << EOF
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar
export PATH=$JAVA_HOME/bin:$PATH
EOF
# source /etc/profile
# java -version
(4) 安装Mycat-server
# tar -xzf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
# mv mycat/ /usr/local/mycat/
(5) 配置Mycat-server
# cd /usr/local/mycat/conf
1) vim /usr/local/mycat/conf/server.xml
说明:
上面添加了一个客户端访问账户,可读写。这个是客户端访问mycat的账户名和密码。
schemas要与schema.xml里的schema name配置一致,多个schema用逗号分隔。账户名和密码与schema.xml里配置的无关。
2) vim /usr/local/mycat/conf/schema.xml
多个数据库写多个schema。
3) 大致流程
server.xml(user)->schema.xml(schema name)->schema.xml(dataNode)->schema.xml(dataHost)
server.xml
# 保存了几乎所有的系统配置信息。
# 主要配置文件之一,管理MyCAT的逻辑库、表、分片规则、DataNode以及DataSource。
schema
# 标签用于定义MyCAT实例中的逻辑库,可以有多个逻辑库,每个逻辑库都有自己相关的
# 配置。可以使用schema标签划分这些不同的逻辑库。
dataNode
# 该属性用于绑定逻辑库到某个具体的database上。
dataHost
# 标签定义具体的数据库实例、读写分离配置和心跳语句。
1) 指定mycat java命令路径
# vim /usr/local/mycat/conf/wrapper.conf
wrapper.java.command=/usr/local/jdk/bin/java
2) mycat.service
# cat /usr/lib/systemd/system/mycat.service
[Unit]
Description=MyCAT Server
[Service]
Type=forking
ExecStart=/usr/local/mycat/bin/mycat start
ExecStop=/usr/local/mycat/bin/mycat stop
ExecReload=/usr/local/mycat/bin/mycat restart
Restart=on-failure
[Install]
WantedBy=multi-user.target
3) 启动mycat并加入开机自启动
# systemctl daemon-reload
# systemctl start mycat.service
# systemctl enable mycat.service
4) 查看mycat的端口
# netstat -tunlp | grep ".*66"
mycat有两个端口,一个是8066数据端口,一个是9066管理端口。
3 管理命令与监控
(1) 在172.16.1.10节点上连接172.16.1.211节点上的mycat
(2) 在172.16.1.10节点上连接172.16.1.212节点上的mycat
(3) 查看帮助
参考文档:http://www.jianshu.com/p/cb7ec06dae05
4 MyCAT+Keepalived主备
在172.16.1.211节点上操作
# yum install keepalived -y
1) keepalived.conf配置文件
# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id MYCAT_HA
}
# 自定义资源监控脚本,监控mysql服务
vrrp_script check_mycat {
script "/etc/keepalived/check_mycat.sh"
# 每2秒执行一次脚本
interval 2
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state MASTER
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 54
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 150
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.200/24 dev eth1 label eth1:1
}
# 调用定义的vrrp_script脚本去监控资源,定义在实例之内,脚本可被多个实例调用
track_script {
check_mycat
}
}
2) mycat服务8066数据端口状态监测脚本
# cat /etc/keepalived/check_mycat.sh
#!/bin/bash
source /etc/profile
IP_LIST="172.16.1.211"
IP_PORT="8066"
for IP in $IP_LIST; do
FAIL_COUNT=0
for ((i=1; i<=3; i++)); do
echo quit | timeout --signal=9 3 telnet $IP $IP_PORT 2>&1 | grep "Connected to $IP" &>/dev/null
if [ $? -eq 0 ]; then
break
else
# echo "$URL retry $FAIL_COUNT"
let FAIL_COUNT++
fi
done
if [ $FAIL_COUNT -eq 3 ]; then
/usr/bin/kill -9 $(cat /var/run/keepalived.pid)
fi
done
# chmod +x /etc/keepalived/check_mycat.sh
3) 启动keepalived
# systemctl start keepalived.service
(2) 从服务器
在172.16.1.212节点上操作
# yum install keepalived -y
1) keepalived.conf配置文件
# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id MYCAT_HA
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state BACKUP
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 54
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 100
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.200/24 dev eth1 label eth1:1
}
# 节点变为master时执行发送邮件的脚本
notify_master /etc/keepalived/send_mail.sh
}
2) 创建邮件发送脚本
# cat /etc/keepalived/send_mail.sh
#!/bin/bash
source /etc/profile
# 配置邮件服务器
# yum install mailx -y
# vim /etc/mail.rc
# set from=hyjy2504164765@163.com smtp=smtp.163.com
# set smtp-auth-user=hyjy2504164765@163.com smtp-auth-password=linux123
# set smtp-auth=login
# 测试,163邮箱服务器需要开启 pop3 smtp 服务,并客户端授权密码
# echo "this is test mail." | mail -s "monitor test" 2504164765@qq.com
function check_mycat() {
IP_LIST="172.16.1.212"
IP_PORT="8066"
for IP in $IP_LIST; do
FAIL_COUNT=0
for ((i=1; i<=3; i++)); do
echo quit | timeout --signal=9 3 telnet $IP $IP_PORT 2>&1 | grep "Connected to $IP" &>/dev/null
if [ $? -eq 0 ]; then
echo "MyCAT-Backup MyCAT Data Port 8066 status is running"
break
else
# echo "$URL retry $FAIL_COUNT"
let FAIL_COUNT++
fi
done
if [ $FAIL_COUNT -eq 3 ]; then
echo "MyCAT-Backup MyCAT Data Port 8066 status is down"
fi
done
}
to="2504164765@qq.com"
subject="MyCAT keepalived up on backup"
body="MyCAT-Master服务器宕机!!! MyCAT-Backup变为master!!! `check_mycat`"
FILE=/tmp/mail.tmp
echo "$body" > $FILE
dos2unix -k $FILE &>/dev/null
# 解决正文变成附件.bin
mail -s "$subject" "$to" < $FILE
# chmod +x /etc/keepalived/send_mail.sh
3) 启动keepalived
# systemctl start keepalived.service
(3) 测试
1) 在172.16.1.10节点连接vip
2) 主节点停止mycat服务
[root@mycat-master ~]# systemctl stop mycat
3) 此时从节点出现了vip
4) 接收到报警邮件
5) 测试方法二
关闭从库SQL线程。然后登录mycat数据端口,插入一条数据,查询正常是没有(走的从库),登录主库查询是有的。
3.4 搭建LNMP网站测试
在172.16.1.10节点上操作
1 安装lnp环境
# 使用脚本部署,这里省略具体步骤
2 部署wordpress
# wordpress下载地址:https://cn.wordpress.org
# cd /usr/local/nginx/html/
# tar -xzf /tmp/wordpress-5.4.2.tar.gz
# chown -R nginx.nginx wordpress/
# systemctl restart nginx
3 安装站点
访问地址:http://172.16.1.10/wordpress/
(1) 连接数据库配置
(2) 配置站点基本信息
(3) 报错
(4) 报错原因解决办法
1) 先停止MySQL-Backup的keepalived,再停止MySQL-Master的keepalived,在所有数据
库的/etc/my.cnf文件中添加如下参数,重启mysqld服务。
[mysqld]
sql_mode=NO_ENGINE_SUBSTITUTION
2) 删除wp库,重建wp库。
3) 先启动MySQL-Master的keepalived,再启动MySQL-Backup的keepalived。
4) 删除/usr/local/nginx/html/wordpress项目,重新解压一份新的wordpress项目,重启
nginx服务。
5) 重新安装wordpress
(5) 安装成功
4 查看访问数据
(1) Mycat读写分布
(2) mysql只读从库lvs负载情况
5 架构启停说明
(1) 架构说明
整个架构所有的keepalived服务设置的都是开机不自启,先手动启动主节点的keepalived
服务,再手动启动从节点的keepalived服务,这样操作是为了避免vip漂移导致主备数据不
一致或脑裂的发生。
(2) 启动-从后往前
1) MySQL-Master
2) MySQL-Backup
3) MySQL-Slave01
4) MySQL-Slave02
5) LVS-Master01
6) LVS-Master02
7) MyCAT-Master
8) MyCAT-Backup
9) Web
(3) 停止-从前往后
1) Web
2) MyCAT-Backup
3) MyCAT-Master
4) LVS-Master02
5) LVS-Master01
6) MySQL-Slave02
7) MySQL-Slave01
8) MySQL-Backup
9) MySQL-Master