1.架构图

2.原理
2.1什么是nginx
Nginx是一个高性能的 HTTP 服务器 和 反向代理服务器,同时也支持 IMAP/POP3/SMTP 等协议
作用:
1.WEB服务器(静态资源服务)
提供静态文件(如 HTML、CSS、JavaScript、图片等)
2. 反向代理(Reverse Proxy)
将来自客户端的请求转发给后端的应用服务器,并对外隐藏真实服务器的地址
3.负载均衡(Load Balancing)
将流量分发到多个后端服务器,
算法:轮询(round-robin)、加权轮询、IP 哈希、最少连接等
4.缓存(Caching)
可缓存后端响应内容,减少后端压力,加快响应速度
5.SSL/TLS 终止(HTTPS 支持)
可处理 HTTPS 请求,卸载 SSL 加密/解密任务
5.访问控制与安全
可限制 IP 访问、设置速率限制(防 DDOS)、隐藏版本号等,提升服务器安全性
总结:Nginx 是一个轻量、高性能、高并发的 Web 服务器和反向代理工具,常用于静态资源服务、负载均衡、API 网关、HTTPS 终端等场景
2.2什么是orchestator
Orchestrator 是由 GitHub 开源的一款 MySQL 高可用管理与复制拓扑编排工具,专为自动化处理主从复制、故障检测、主库故障自动切换(Failover) 等场景而设计
核心功能:
1.自动发现复制拓扑
2.主库故障检测(Failure Detection)
3.自动主从切换(Automated Failover)
3.钩子(Hooks)与可扩展性
4.Web UI 可视化
3.基础环境和版本信息
10台虚拟机,1G内存,1CPU,20GB,操作系统:Centos7.3。
mysql8.0.44 (数据库)
orchestator3.2.6 (主从切换工具)
nginx1.28.0(入站口,反向代理)
keeplaived2.3.4(高可用)
httpd2.4.62(WEB服务)
php8.3.8(环境)
phpredis6.0.2(用来连接redis)
redis7.4.0(缓存数据)
nfs(版本比较旧,请大家自行升级)
4.mysql主部署流程
1.把 MySQL 官方提供的“仓库配置文件包”装进系统,具体文件放在yum源下
yum install https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
2.把 MySQL 2023 年新的公钥下载到本地标准目录,文件名叫 RPM-GPG-KEY-mysql-2023
curl -sS https://repo.mysql.com/RPM-GPG-KEY-mysql-2023 -o /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2023
3.以后遇到用这把钥匙签名的包,我认为它合法
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2023
4.把 repo 文件里原来指向的旧钥匙(2022 或 2021 版)统一改成 2023 版,这样 yum 校验时就能对上号,不再出现 “GPG key 已安装但不适用” 的错误
sed -i 's|RPM-GPG-KEY-mysql.*|RPM-GPG-KEY-mysql-2023"|g' /etc/yum.repos.d/mysql-community.repo
安装mysql8.0.44
###查找mysql软件包#####
rpm -qa | grep -i mysql
yum -y install mysql-community-server
###缺少工具###
yum -y install net-tools
以上内容均以从相同
5.修改主库配置文件/etc/my.conf,添加一下内容到mysqld模块下
[mysqld]
server_id=100 #给这台 MySQL 一个全局唯一编号(主从不能重复)
log_bin=/var/lib/mysql/mysql-bin (打开二进制日志,并放在指定路径,文件名前缀 mysql-bin)
binlog_format=ROW (日志按“行”记录(更精确、更安全,推荐))
gtid_mode=ON (启用 GTID(全局事务标识),方便主从切换、避免位点错)
enforce_gtid_consistency=ON 禁止任何会破坏 GTID 一致性的语句(如 CREATE TABLE … SELECT)
binlog_expire_logs_seconds=604800 # 7天自动清理
sync_binlog=1 每次事务提交都立即把 binlog 刷盘,崩溃时最多丢 1 个事务(最安全)
######加入以上内容,必须重启mysqld,不然配置无效
##列出所有已安装的 systemd 单元(服务),把名字里带 "mysql" 的筛出来
systemctl list-unit-files | grep -i mysql
5.5,获取数据库的临时密码(数据库8.0会临时给一个数据库密码)
awk '/temporary password/ {print $NF}' /var/log/mysqld.log
6.创建专用复制账号
(1)登录数据库
mysql -uroot -p
进入之后,必须重置密码:
alter user 'root'@'localhost' identified by '123456@Yz';
(2)创建专用账号
CREATE USER 'repl'@'192.168.20.137' IDENTIFIED WITH mysql_native_password BY 'Repl@2025Strong'; 创建用户、指定从库ip地址及用户密码
GRANT REPLICATION SLAVE ON *.* TO 'yz'@'192.168.20.144'; 用于建立和维护主从复制关系。
(3)orc_client_user:Orchestrator 的 “拓扑监控用户”,管 MySQL 主从集群的监控和切换
-- 1. 先创建 orc_client_user 用户(允许 134 服务器登录,密码 Orch@123 与配置一致)
CREATE USER IF NOT EXISTS 'orc_client_user'@'192.168.20.134' IDENTIFIED BY 'Orch@123';
2. 再授予监控所需权限(SELECT + PROCESS + REPLICATION CLIENT)
GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO'orc_client_user'@'192.168.20.134';
刷新
FLUSH PRIVILEGES;
#查看File和Position值
#show master status;
##安装keepalived配置文件
1.下载源码包
wget https://www.keepalived.org/software/keepalived-2.3.4.tar.gz
2.# 解压 tar 包到 /usr/local
tar -zxvf keepalived-2.3.4.tar.gz -C /usr/local/
3.重命名为 keepalived(简化路径,后续操作更方便)
mv /usr/local/keepalived-2.3.4 /usr/local/keepalived
4. 使用 configure 脚本指定安装路径、依赖库路径等
./configure \
--prefix=/usr/local/keepalived \ 安装路径
--sysconfdir=/etc/keepalived \ #配置文件目录
--with-openssl=/usr \ #openssl安装路径
--with-popt=/usr \ #popt安装路径
--with-libnl3=/usr #libnl3的安装目录
报错:没有C环境
第一种方式,安装gcc*
第二种方式:安装gcc-11.2.0
(1)安装一次性依赖包
yum groupinstall "Development Tools"
yum install gmp-devel mpfr-devel libmpc-devel
(2)下载源码包
wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.gz
(3)解压安装包,并进入解压目录
tar -xf gcc-11.2.0.tar.gz && cd gcc-11.2.0
(4)新建隔离目录
mkdir build && cd build
(5)配置编译
./configure \--prefix=/usr/local/gcc-11.2.0 \ #指定目录
--enable-languages=c,c++ \
--disable-multilib \
--enable-checking=release
(6)编译和安装
make
make install
(7)把新 GCC 放进环境变量
echo 'export PATH=/usr/local/gcc-11.2.0/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/gcc-11.2.0/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/ .bashrc
验证:
gcc --version # 应显示 11.2.0
g++ --version
5.编译与安装
make -j $(nproc) # 多线程编译($(nproc) 自动获取 CPU 核心数,加速编译)
make install # 安装到指定目录
6.配置环境变量
echo 'export PATH=/usr/local/keepalived/sbin:$PATH' >> /etc/profile
source /etc/profile # 生效环境变量
验证:
执行 keepalived -v,若输出版本信息(Keepalived v2.3.4)
7.配置keepalived
keepalived配置文件
# /etc/keepalived/keepalived.conf
# ----------- 全局段 -----------
global_defs {
router_id 1
script_user root
enable_script_security
}
# ----------- VRRP 脚本:探活 MySQL -----------
vrrp_script chk_mysql {
script "/etc/keepalived/check_mysql.sh" (如果这个脚本发现到数据库主宕机,优先级减50)
interval 2
weight -50 # 脚本失败则本机 priority -30
}
# ----------- VRRP 实例 -----------
vrrp_instance VI_1 {
state BACKUP # 两台都写 BACKUP,靠 priority 决定主从
interface ens33 # 实际网卡名
virtual_router_id 1 # 同一组 VRRP 必须相同
priority 150 # 另一台写 90
advert_int 3
authentication {
auth_type PASS
auth_pass 1111 # 同一组密码必须一致
}
virtual_ipaddress {
192.168.20.100/32 dev ens33 label ens33:1 # 要漂移的 VIP
}
track_script {
chk_mysql # 引用上面定义的探活脚本
}
# 当主库恢复时,不自动抢回 VIP(避免频繁切换,可选)
notify_down "/etc/keepalived/mysql_down.sh"
}
8.在/etc/keepalived/目录下创建脚本文件
(1)vi check_mysql_sh加入以下内容
#!/bin/bash
# 检测 MySQL 是否能正常连接
MYSQL_USER="orc_server_user"
MYSQL_PASS="123456"
MYSQL_PORT="3306"
# 执行 MySQL 连接测试
mysql -u$MYSQL_USER -p$MYSQL_PASS -P$MYSQL_PORT -e "SELECT 1" > /dev/null 2>&1
if [ $? -eq 0 ]; then
# MySQL 正常,返回 0(Keepalived 认为健康)
exit 0
else
# MySQL 异常,返回 1(Keepalived 认为故障)
exit 1
fi
(2)记录日志
#!/bin/bash
# /etc/keepalived/mysql_down.sh
LOG_FILE="/var/log/keepalived_mysql_down.log"
LOCAL_IP=$(hostname -I | awk '{print $1}')
DATE=$(date "+%Y-%m-%d %H:%M:%S")
# 记录宕机日志
echo "[$DATE] 警告:本地 MySQL 主库(IP: $LOCAL_IP)宕机,VIP 192.168.20.100 即将漂移" >> $LOG_FILE
# 可选:发送邮件/短信告警(示例:发送邮件,需安装 mailx)
# echo "MySQL 主库 $LOCAL_IP 宕机,VIP 已漂移" | mailx -s "【MySQL 主库宕机告警】" admin@example.com
exit 0
(3)赋予脚本文件可执行权限
chmod +x /etc/keepalived/mysql_down.sh
chmod +x /etc/keepalived/check_mysql.sh
9.需加入主恢复之后,抢占VIP
5.mysql从(slave)部署流程
1.修改从库配置文件/etc/my.conf,添加一下内容到mysqld模块下
[mysqld]
server_id=101 #从库唯一编号,必须和主库不同
report_host = 192.168.20.131 #所有从库都应设置 report_host
否则 Orchestrator、MHA、Prometheus 等工具都无法正确发现拓扑
relay_log=/var/lib/mysql/relay-bin #指定中继日志文件名前缀(可自定义路径
gtid_mode=ON #开启 GTID 复制
enforce_gtid_consistency=ON #保证语句不会破坏 GTID 一致性
read_only=ON # 只读模式,普通用户无法写数据,防止误操作(但 root 和 SUPER 权限仍可写)slave_parallel_type=LOGICAL_CLOCK #按“逻辑时钟”并行回放事务(GTID 复制推荐
slave_parallel_workers=8 # 核数多可再提高
relay_log_purge=ON #中继日志应用完后自动删除,节省磁盘
######加入以上内容,必须重启mysqld,不然配置无效
2.获取数据库临时密码
awk '/temporary password/ {print $NF}' /var/log/mysqld.log
进入之后,必须重置密码:
alter user 'root'@'localhost' identified by '123456@Yz';
3.使用专用用户来连接主库
CHANGE MASTER TO
MASTER_HOST='192.168.1.100', #主库IP地址
MASTER_USER='repl', #专用用户
MASTER_PASSWORD='Repl@2025Strong', #密码
MASTER_AUTO_POSITION=1;
4.开启复制
start slave;
5.验证
SHOW SLAVE STATUS\G;
-- 确保以下两项为 Yes--
Slave_IO_Running: Yes--
Slave_SQL_Running: Yes--
Seconds_Behind_Master: 0 (无延迟)
6.##安装keepalived配置文件
1.下载源码包
wget https://www.keepalived.org/software/keepalived-2.3.4.tar.gz
2.# 解压 tar 包到 /usr/local
tar -zxvf keepalived-2.3.4.tar.gz -C /usr/local/
tar 参数命令和含义
z:表示使用 gzip 解压缩。
→ 因为 .tar.gz 文件是先用 tar 打包,再用 gzip 压缩的,所以需要用 -z 来解压 gzip 层。
-x:表示 extract(解包/解压)。
→ 和 -c(create,创建)相对,-x 是把归档文件中的内容提取出来。
-v:表示 verbose(详细模式)。
→ 解压时会列出被解压的文件名,便于用户查看进度和内容。
-f:表示 file(指定文件名)
3.重命名为 keepalived(简化路径,后续操作更方便)
mv /usr/local/keepalived-2.3.4 /usr/local/keepalived
4. 使用 configure 脚本指定安装路径、依赖库路径等
./configure \
--prefix=/usr/local/keepalived \ 安装路径
--sysconfdir=/etc/keepalived \ #配置文件目录
--with-openssl=/usr \ #openssl安装路径
--with-popt=/usr \ #popt安装路径
--with-libnl3=/usr #libnl3的安装目录
##如果缺少openssl请安装
报错内容:
configure: error:
!!! OpenSSL is not properly installed on your system. !!!
!!! Can not include OpenSSL headers files. !!!
解决方案:
yum install -y openssl-devel
##报错:没有C环境
第一种方式,安装gcc*
第二种方式:安装gcc-11.2.0
(1)安装一次性依赖包
yum groupinstall "Development Tools"
yum install gmp-devel mpfr-devel libmpc-devel
(2)下载源码包
wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.gz
(3)解压安装包,并进入解压目录
tar -xf gcc-11.2.0.tar.gz && cd gcc-11.2.0
(4)新建隔离目录
mkdir build && cd build
(5)配置编译
./configure \--prefix=/usr/local/gcc-11.2.0 \ #指定目录
--enable-languages=c,c++ \
--disable-multilib \
--enable-checking=release
(6)编译和安装
make
make install
(7)把新 GCC 放进环境变量
echo 'export PATH=/usr/local/gcc-11.2.0/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/gcc-11.2.0/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/ .bashrc
验证:
gcc --version # 应显示 11.2.0
g++ --version
(8)将keepalived命令加入systemd管理
vi /etc/systemd/system/keepalived.service
[Unit]
Description=Keepalived High Availability Daemon
Documentation=man:keepalived(8) man:keepalived.conf(5)
After=network.target network-online.target syslog.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/keepalived.pid
ExecStart=/usr/local/keepalived/sbin/keepalived -D -f /etc/keepalived/keepalived.conf #指定可执行文件和配置文件目录
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
5.编译与安装
make -j $(nproc) # 多线程编译($(nproc) 自动获取 CPU 核心数,加速编译)
make install # 安装到指定目录
6.配置环境变量
echo 'export PATH=/usr/local/keepalived/sbin:$PATH' >> /etc/profile
source /etc/profile # 生效环境变量
验证:
执行 keepalived -v,若输出版本信息(Keepalived v2.3.4)
7.配置keepalived
# /etc/keepalived/keepalived.conf
# ----------- 全局段 -----------
global_defs {
router_id 2
script_user root
enable_script_security
}
# ----------- VRRP 脚本:探活 MySQL -----------
vrrp_script chk_mysql {
script "/etc/keepalived/check_mysql.sh"
interval 2
weight -30 # 脚本失败则本机 priority -30
}
# ----------- VRRP 实例 -----------
vrrp_instance VI_1 {
state BACKUP # 两台都写 BACKUP,靠 priority 决定主从
interface ens33 # 实际网卡名
virtual_router_id 1 # 同一组 VRRP 必须相同
priority 120 # 另一台写 90
advert_int 3
authentication {
auth_type PASS
auth_pass 1111 # 同一组密码必须一致
}
virtual_ipaddress {
192.168.20.100/32 dev ens33 label ens33:2 # 要漂移的 VIP
}
track_script {
chk_mysql # 引用上面定义的探活脚本
}
# 允许从库成为主库后抢占 VIP(故障转移后保持 VIP 在新主库)
preempt_delay 30 # 延迟 30 秒抢占(避免网络抖动
notify_master "/etc/keepalived/mysql_master.sh"
}
8.在/etc/keepalived/目录下创建脚本文件
(1)vi check_mysql_sh加入以下内容
#!/bin/bash
# 检测 MySQL 是否能正常连接
MYSQL_USER="orc_server_user" ##确保这个用户可以在本机正常登录
MYSQL_PASS="123456"
MYSQL_PORT="3306"
# 执行 MySQL 连接测试
mysql -u$MYSQL_USER -p$MYSQL_PASS -P$MYSQL_PORT -e "SELECT 1" > /dev/null 2>&1
if [ $? -eq 0 ]; then
# MySQL 正常,返回 0(Keepalived 认为健康)
exit 0
else
# MySQL 异常,返回 1(Keepalived 认为故障)
exit 1
fi
(2)记录日志
#!/bin/bash
# /etc/keepalived/mysql_down.sh
LOG_FILE="/var/log/keepalived_mysql_down.log"
LOCAL_IP=$(hostname -I | awk '{print $1}')
DATE=$(date "+%Y-%m-%d %H:%M:%S")
# 记录宕机日志
echo "[$DATE] 警告:本地 MySQL 主库(IP: $LOCAL_IP)宕机,VIP 192.168.20.100 即将漂移" >> $LOG_FILE
# 可选:发送邮件/短信告警(示例:发送邮件,需安装 mailx)
# echo "MySQL 主库 $LOCAL_IP 宕机,VIP 已漂移" | mailx -s "【MySQL 主库宕机告警】" admin@example.com
exit 0
(3)赋予脚本文件可执行权限
chmod +x /etc/keepalived/mysql_down.sh
chmod +x /etc/keepalived/check_mysql.sh
6.单机部署orchetrator主从切换
防火墙setenforce必须
部署mysql8.0(用做元数据)
1.把 MySQL 官方提供的“仓库配置文件包”装进系统,具体文件放在yum源下
yum install https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
2.把 MySQL 2023 年新的公钥下载到本地标准目录,文件名叫 RPM-GPG-KEY-mysql-2023
curl -sS https://repo.mysql.com/RPM-GPG-KEY-mysql-2023 -o /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2023
3.以后遇到用这把钥匙签名的包,我认为它合法
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2023
4.把 repo 文件里原来指向的旧钥匙(2022 或 2021 版)统一改成 2023 版,这样 yum 校验时就能对上号,不再出现 “GPG key 已安装但不适用” 的错误
sed -i 's|RPM-GPG-KEY-mysql.*|RPM-GPG-KEY-mysql-2023"|g' /etc/yum.repos.d/mysql-community.repo
yum -y install mysql
5.进入数据库,创建元数据用户,并赋予本机登录权限,Orchestrator 的 “数据管理员”,管自己的运行数据存储
mysql -uroot -p
(1)
(2)授权 192.168.20.% 网段(Orchestrator 节点远程连接主从库)
GRANT ALL PRIVILEGES ON `orchestrator`.* TO 'orc_server_user'@'192.168.20.%' IDENTIFIED BY 'Orch@123';--
(3) 授权 localhost 本地连接(元数据库节点本地维护时使用)
GRANT ALL PRIVILEGES ON `orchestrator`.* TO 'orc_server_user'@'localhost' IDENTIFIED BY 'Orch@123';
####如果mysql报错###请确定是否安装过其它版本
解决方法:(全新目录 + 彻底授权)
1.停止所有进程
systemctl stop mysqld.service
ps -ef | grep mysqld | grep -v grep | awk '{print $2}' | xargs kill -9 2>/dev/null
2.新建全新的数据目录(远离默认目录
# 1. 创建新目录(选 /data 分区,通常无挂载限制)mkdir -p /data/mysql8
mkdir -p /data/mysql8-files # 对应 secure-file-priv 目录# 2. 给新目录授权(彻底放开,确保 mysql 用户完全控制)chown -R mysql:mysql /data/mysql8
chown -R mysql:mysql /data/mysql8-files
chmod -R 770 /data/mysql8 # 测试环境宽松权限,避免权限不足chmod -R 770 /data/mysql8-files
# 3. 确认权限(必须是 mysql:mysql,权限 770)ls -ld /data/mysql8
ls -ld /data/mysql8-files
4.修改 MySQL 配置文件(指向新目录)
vim /etc/my.cnf
[mysqld]port=3307 # 确保端口不冲突(3306 被旧从库占用)datadir=/data/mysql8 # 新数据目录socket=/data/mysql8/mysql.sock socket 文件log-error=/var/log/mysqld.log # 日志路径不变pid-file=/var/run/mysqld/mysqld.pid # PID 文件路径不变user=mysqldefault-storage-engine=InnoDBcharacter-set-server=utf8mb4collation-server=utf8mb4_unicode_cisecure-file-priv=/data/mysql8-files # 新的安全目录# 禁用符号链接(消除警告,可选)skip-symbolic-links=0
5.直接启动 MySQL 服务,让系统自动初始化(关键!)
systemctl start mysqld.service
6.查看启动日志,观察是否在生成系统表tail -f /var/log/mysqld.log | grep -iE "initialize|create table|mysql.db"
###换了mysql路径之后,临时密码的路径/var/log/mysqld.log不会变,所以需要在登录是加入-S指定目录文件
mysql -uroot -p'.*Npd?lD4suB' -S /data/mysql8/mysql.sock
在配置文件加入
[mysql]
socket=/data/mysql8/mysql.sock
orchestator安装部署
1.下载安装包
wget https://github.com/openark/orchestrator/releases/download/v3.2.6/orchestrator-3.2.6-linux-amd64.tar.gz
2.解压安装包到/usr/local/ (-C代表指定目录)
tar -zxvf orchestrator-3.2.6-linux-amd64.tar.gz -C /usr/local/
3.进入cd /usr/local/orchetrator/下面,原有的配置文件删除加入以下
{
{
"Debug": true,
"EnableSyslog": true, #启用日志
"SyslogFacility": "local0",
"ListenAddress": ":3000", #WEB监听端口
"EnableNodeElection": true,
"InstancePollSeconds": 3,
"AuditLogFile": "/var/log/orchestrator/orchestrator.log", #指定日志的写入路径
"AssumeNodeIsActive": true, #设置当前节点为活跃状态
"NodeAddress": "192.168.20.134", 当前 MySQL节点的通信地址
"MySQLTopologyUser": "orc_client_user", # 用于探测 MySQL 拓扑的「专用账号」和密码
"MySQLTopologyPassword": "Orch@123",
"MySQLTopologyCredentialsConfigFile": "",
"MySQLTopologySSLPrivateKeyFile": "",
"MySQLTopologySSLCertFile": "",
"MySQLTopologySSLCAFile": "",
"MySQLTopologySSLSkipVerify": true,
"MySQLTopologyUseMutualTLS": false,
"MySQLOrchestratorHost": "192.168.20.134", #「Orchestrator 元数据库地址」
"MySQLOrchestratorPort": 3307, #端口号
"MySQLOrchestratorDatabase": "Orchestrator", #Orchestrator 元数据存储的数据库名
"MySQLOrchestratorUser": "Orchestrator", #连接「Orchestrator 元数据库」的 MySQL 账号和密码
"MySQLOrchestratorPassword": "Orch@123",
"MySQLOrchestratorCredentialsConfigFile": "",
"MySQLOrchestratorSSLPrivateKeyFile": "",
"MySQLOrchestratorSSLCertFile": "",
"MySQLOrchestratorSSLCAFile": "",
"MySQLOrchestratorSSLSkipVerify": true,
"MySQLOrchestratorUseMutualTLS": false,
"MySQLConnectTimeoutSeconds": 1,
"DefaultInstancePort": 3306,
"DiscoverByShowSlaveHosts": true,
"InstancePollSeconds": 5,
"ClusterNameToAlias": {
"192.168.20.131:3306": "MySQL-server"},
"RejectHostnameResolvePattern": "",
"AllowTLS": false,
"DiscoveryIgnoreReplicaHostnameFilters": [
"a_host_i_want_to_ignore[.]example[.]com",
".*[.]ignore_all_hosts_from_this_domain[.]example[.]com",
"a_host_with_extra_port_i_want_to_ignore[.]example[.]com:3307"
],
"UnseenInstanceForgetHours": 240,
"SnapshotTopologiesIntervalHours": 0,
"InstanceBulkOperationsWaitTimeoutSeconds": 10,
"HostnameResolveMethod": "default",
"MySQLHostnameResolveMethod": "@@hostname",
"SkipBinlogServerUnresolveCheck": true,
"ExpiryHostnameResolvesMinutes": 60,
"RejectHostnameResolvePattern": "",
"ReasonableReplicationLagSeconds": 10,
"ProblemIgnoreHostnameFilters": [],
"VerifyReplicationFilters": false,
"ReasonableMaintenanceReplicationLagSeconds": 20,
"CandidateInstanceExpireMinutes": 60,
"AuditLogFile": "",
"AuditToSyslog": false,
"RemoveTextFromHostnameDisplay": ".mydomain.com:3306",
"ReadOnly": false,
"AuthenticationMethod": "",
"HTTPAuthUser": "",
"HTTPAuthPassword": "",
"AuthUserHeader": "",
"PowerAuthUsers": [
"*"
],
"ClusterNameToAlias": {
"127.0.0.1": "test suite"
},
"ReplicationLagQuery": "",
"DetectClusterAliasQuery": "SELECT SUBSTRING_INDEX(@@hostname, '.', 1)",
"DetectClusterDomainQuery": "",
"DetectInstanceAliasQuery": "",
"DetectPromotionRuleQuery": "",
"DataCenterPattern": "[.]([^.]+)[.][^.]+[.]mydomain[.]com",
"PhysicalEnvironmentPattern": "[.]([^.]+[.][^.]+)[.]mydomain[.]com",
"PromotionIgnoreHostnameFilters": [],
"DetectSemiSyncEnforcedQuery": "",
"ServeAgentsHttp": false,
"AgentsServerPort": ":3001",
"AgentsUseSSL": false,
"AgentsUseMutualTLS": false,
"AgentSSLSkipVerify": false,
"AgentSSLPrivateKeyFile": "",
"AgentSSLCertFile": "",
"AgentSSLCAFile": "",
"AgentSSLValidOUs": [],
"UseSSL": false,
"UseMutualTLS": false,
"SSLSkipVerify": false,
"SSLPrivateKeyFile": "",
"SSLCertFile": "",
"SSLCAFile": "",
"SSLValidOUs": [],
"URLPrefix": "",
"StatusEndpoint": "/api/status",
"StatusSimpleHealth": true,
"StatusOUVerify": false,
"AgentPollMinutes": 60,
"UnseenAgentForgetHours": 6,
"StaleSeedFailMinutes": 60,
"SeedAcceptableBytesDiff": 8192,
"PseudoGTIDPattern": "",
"PseudoGTIDPatternIsFixedSubstring": false,
"PseudoGTIDMonotonicHint": "asc:",
"DetectPseudoGTIDQuery": "",
"BinlogEventsChunkSize": 10000,
"SkipBinlogEventsContaining": [],
"ReduceReplicationAnalysisCount": true,
"FailureDetectionPeriodBlockMinutes": 60,
"FailMasterPromotionOnLagMinutes": 0,
"RecoveryPeriodBlockSeconds": 180,
"RecoveryIgnoreHostnameFilters": [],
"RecoverMasterClusterFilters": [
"*"
],
"RecoverIntermediateMasterClusterFilters": [
"*"
],
"OnFailureDetectionProcesses": [
"echo '>>> Detected {failureType} on {failureCluster}' >> /tmp/recovery.log"
],
"PreGracefulTakeoverProcesses": [
"echo 'Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
],
"PreFailoverProcesses": [
"echo '>>> Will recover from {failureType} on {failureCluster}' >> /tmp/recovery.log"
],
"PostFailoverProcesses": [
"echo '(for all types) Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostUnsuccessfulFailoverProcesses": [],
"PostMasterFailoverProcesses": [
"echo '>>> Promoted {successorHost}:{successorPort} as new master' >> /tmp/recovery.log", #故障转移日志记录
"/usr/local/orchestrator/keepalived-vip.sh {successorHost} {failedHost}" 执行 VIP 漂移脚本
],
"PostIntermediateMasterFailoverProcesses": [
"echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostGracefulTakeoverProcesses": [
"echo 'Planned takeover complete' >> /tmp/recovery.log"
],
"CoMasterRecoveryMustPromoteOtherCoMaster": true,
"DetachLostSlavesAfterMasterFailover": true,
"ApplyMySQLPromotionAfterMasterFailover": true,
"PreventCrossDataCenterMasterFailover": false,
"PreventCrossRegionMasterFailover": false,
"MasterFailoverDetachReplicaMasterHost": false,
"MasterFailoverLostInstancesDowntimeMinutes": 0,
"PostponeReplicaRecoveryOnLagMinutes": 0,
"OSCIgnoreHostnameFilters": [],
"GraphiteAddr": "",
"GraphitePath": "",
"GraphiteConvertHostnameDotsToUnderscores": true,
"ConsulAddress": "",
"ConsulAclToken": "",
"ConsulKVStoreProvider": "consul",
"AutoMasterFailover": true,
"AutoRecoverMaster": true,
"AutoRecoverIntermediateMaster": true,
"AutomaticMasterRecoveryMustPromoteOtherInstance": true,
"PromoteSlavePreferCountReplicas": true,
"PromoteSlavePreferLagMinutes": 0
}
5.将orchestator服务加入systemd管理
vi /etc/systemd/system/orchestrator.service 加入以下内容:
[Unit]
Description=Orchestrator MySQL Topology Manager
After=network.target mysql.service
[Service]
Type=simple
WorkingDirectory=/usr/local/orchestrator #orchestator文件目录
User=root #root用户
Group=root #root组
ExecStart=/usr/local/orchestrator/orchestrator --config=/usr/local/orchestrator/orchestrator.conf.json http #启动文件和配置文件目录
Restart=always
RestartSec=5
#可选可不选
StandardOutput=journal+console #写出日志
StandardError=journal+console
[Install]
WantedBy=multi-user.target
6.重新加载systemd管理,并启动orchestator
systemctl redaom-reload
systemctl restart orchestator
7.将日志文件输出到指定目录,
创建文件:/var/log/orchestrator/orchestrator.log
将syslog下的日志文件写入到自定义目录。
vi /etc/rsyslog.d/30-orchestrator.conf 加入以下内容
# Orchestrator 日志规则(local0 标识匹配)
local0.* /var/log/orchestrator/orchestrator.log
# 日志格式定义(时间、主机名、应用名)
$template OrchestratorLogFormat, "%timereported% %HOSTNAME% orchestrator: %msg%\n"
local0.* -/var/log/orchestrator/orchestrator.log;OrchestratorLogFormat
:programname, isequal, "orchestrator" /var/log/orchestrator/orchestrator.log
# 匹配 orchestrator: 前缀的日志(应用自定义格式)
:msg, contains, "orchestrator:" /var/log/orchestrator/orchestrator.log
# 禁止重复转发到系统日志
& ~
# 禁止日志重复转发到系统日志
local0.* ~
重新启动syslog
systemctl restart syslog
###
查看是否有日志出现:
vi /var/log/orchestrator/orchestrator.log
8.配置钩子脚本/usr/local/orchestrator/
vi keepalived-vip.sh
#!/bin/bash
# /usr/local/orchestrator/keepalived-vip.sh
# 接收 Orchestrator 传递的参数:$1 = 新主库IP(successorHost),$2 = 旧主库IP(failedHost)
# 配置参数(仅需修改 VIP 和网卡名,与 Keepalived 配置一致)
VIP="192.168.20.100" #虚拟VIP
INTERFACE="ens33" # 与 keepalived.conf 中的 interface 一致
LOG_FILE="/var/log/orchestrator-vip-switch.log" #日志目录
# 校验参数(避免脚本因无参数执行失败)
if [ $# -ne 2 ]; then
echo "$(date +'%Y-%m-%d %H:%M:%S') - 错误:参数不足!需要 新主库IP 和 旧主库IP" >> $LOG_FILE
exit 1
fi
# 接收 Orchestrator 传递的变量(动态获取,无需硬编码)
NEW_MASTER="$1" # 新主库IP(如 192.168.20.137)
OLD_MASTER="$2" # 旧主库IP(如 192.168.20.131)
# 1. 停止旧主库的 Keepalived(确保旧主库释放 VIP)
echo "$(date +'%Y-%m-%d %H:%M:%S') - 正在停止旧主库 $OLD_MASTER 的 Keepalived..." >> $LOG_FILE
ssh root@$OLD_MASTER "systemctl stop keepalived && systemctl disable keepalived" > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "$(date +'%Y-%m-%d %H:%M:%S') - 旧主库 $OLD_MASTER Keepalived 已停止" >> $LOG_FILE
else
echo "$(date +'%Y-%m-%d %H:%M:%S') - 警告:停止旧主库 $OLD_MASTER Keepalived 失败(可能已宕机)" >> $LOG_FILE
fi
# 2. 启动新主库的 Keepalived(确保新主库绑定 VIP)
echo "$(date +'%Y-%m-%d %H:%M:%S') - 正在启动新主库 $NEW_MASTER 的 Keepalived..." >> $LOG_FILE
ssh root@$NEW_MASTER "systemctl enable keepalived && systemctl start keepalived" > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "$(date +'%Y-%m-%d %H:%M:%S') - 新主库 $NEW_MASTER Keepalived 已启动,VIP $VIP 已漂移" >> $LOG_FILE
else
echo "$(date +'%Y-%m-%d %H:%M:%S') - 错误:启动新主库 $NEW_MASTER Keepalived 失败!" >> $LOG_FILE
exit 1
fi
# 3. 验证 VIP 是否绑定成功(可选,增强可靠性)
VIP_CHECK=$(ssh root@$NEW_MASTER "ip addr show $INTERFACE | grep $VIP" 2>/dev/null)
if [ -n "$VIP_CHECK" ]; then
echo "$(date +'%Y-%m-%d %H:%M:%S') - 验证成功:新主库 $NEW_MASTER 已绑定 VIP $VIP" >> $LOG_FILE
else
echo "$(date +'%Y-%m-%d %H:%M:%S') - 警告:新主库 $NEW_MASTER 未检测到 VIP $VIP,可能绑定失败" >> $LOG_FILE
fi
exit 0
需要做ssh免密,否则钩子脚本停止不到keepalived。
ssh-keygen
ssh-copy-id root@192.168.20.131
##手动添加集群模式
./orchestrator -c register -i 192.168.20.131:3306 (主)
./orchestrator -c register -i 192.168.20.137:3306 (从)
并验证是否加入集群:
./orchestrator -c topology -i 192.168.20.137:3306
正常状态
025-11-25 02:51:56 DEBUG instanceKey: 192.168.20.131:3306
2025-11-25 02:51:56 DEBUG instanceKey: 192.168.20.137:3306
192.168.20.131:3306 [0s,ok,8.0.44,rw,ROW,>>,GTID]
+ 192.168.20.137:3306 [0s,ok,8.0.44,ro,ROW,>>,GTID]
####查询数据库是读权限还是写
SHOW VARIABLES LIKE 'read_only';
ON 表示 MySQL 实例处于只读模式(即使你有写权限也写不了)
OFF 表示可读写
修改写权限为读
SET GLOBAL read_only = ON;
只要 Orchestrator 成功将从库提升为新主库,就会自动关闭只读模式,让其成为 “可写主库”
在主库上验证 SHOW SLAVE HOSTS
完整的主动联动过程
主库 MySQL 宕机
├─ 1. Keepalived 侧:检测故障
│ - 健康检测脚本(select 1)失败 → 返回 1,Keepalived 判定节点故障;
│ - 触发 mysql_down.sh → 记录日志、发邮件告警;
├─ 2. Orchestrator 侧:主动探测+执行切换
│ - 按周期探测主库 → 连接超时,判定主库故障;
│ - 自动提升从库为新主库(stop slave → reset master);
│ - 触发钩子脚本 keepalived-vip.sh(配置在 Orchestrator 的 PostFailoverProcesses 中);
├─ 3. 脚本联动:Orchestrator 通知 Keepalived 漂移 VIP
│ - keepalived-vip.sh 接收新/旧主库 IP 参数;
│ - 远程停止旧主库 Keepalived → 释放 VIP;
│ - 远程启动新主库 Keepalived → 绑定 VIP;
│ - 验证 VIP 绑定成功;
└─ 4. 业务恢复:
- VIP 192.168.20.100 已漂移到新主库;
- 业务通过 VIP 访问 → 连接新主库(可读写),切换完成。
7.配置ngin+keepalived2台同上(用来反向代理WEB网站)
关闭防火墙,setenforce
1.下载源码包
wget https://www.keepalived.org/software/keepalived-2.3.4.tar.gz
2.# 解压 tar 包到 /usr/local
tar -zxvf keepalived-2.3.4.tar.gz -C /usr/local/
3.重命名为 keepalived(简化路径,后续操作更方便)
mv /usr/local/keepalived-2.3.4 /usr/local/keepalived
4. 使用 configure 脚本指定安装路径、依赖库路径等
./configure \
--prefix=/usr/local/keepalived \ 安装路径
--sysconfdir=/etc/keepalived \ #配置文件目录
--with-openssl=/usr \ #openssl安装路径
--with-popt=/usr \ #popt安装路径
--with-libnl3=/usr #libnl3的安装目录
##如果以上命令输错,重新清理编译生成的文件###
make clean # 清理编译生成的 .o 目标文件、可执行文件等
make distclean # 额外清理 configure 生成的缓存文件(config.status、Makefile 等)
##如果缺少openssl请安装
yum install -y openssl-devel
##报错:没有C环境
第一种方式,安装gcc*
第二种方式:安装gcc-11.2.0
(1)安装一次性依赖包
yum groupinstall "Development Tools"
yum install gmp-devel mpfr-devel libmpc-devel
(2)下载源码包
wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.gz
(3)解压安装包,并进入解压目录
tar -xf gcc-11.2.0.tar.gz && cd gcc-11.2.0
(4)新建隔离目录
mkdir build && cd build
(5)配置编译
./configure \--prefix=/usr/local/gcc-11.2.0 \ #指定目录
--enable-languages=c,c++ \
--disable-multilib \
--enable-checking=release
(6)编译和安装
make
make install
(7)把新 GCC 放进环境变量
echo 'export PATH=/usr/local/gcc-11.2.0/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/gcc-11.2.0/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/ .bashrc
验证:
gcc --version # 应显示 11.2.0
g++ --version
5.将keepalived命令加入systemd管理
vi /etc/systemd/system/keepalived.service
[Unit]
Description=Keepalived High Availability Daemon
Documentation=man:keepalived(8) man:keepalived.conf(5)
After=network.target network-online.target syslog.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/keepalived.pid
ExecStart=/usr/local/keepalived/sbin/keepalived -D -f /etc/keepalived/keepalived.conf #指定可执行文件和配置文件目录
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
5.编译与安装
make -j $(nproc) # 多线程编译($(nproc) 自动获取 CPU 核心数,加速编译)
make install # 安装到指定目录
6.配置环境变量
echo 'export PATH=/usr/local/keepalived/sbin:$PATH' >> /etc/profile
source /etc/profile # 生效环境变量
验证:
执行 keepalived -v,若输出版本信息(Keepalived v2.3.4)
7.配置keepalived文件:
vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived (Master 节点)
global_defs {
router_id LVS_MASTER # 节点唯一标识(主从需不同,如 LVS_MASTER/LVS_BACKUP)
script_user root # 执行健康检查脚本的用户
enable_script_security # 启用脚本安全(2.3.x 推荐开启,避免权限问题)
}
# 健康检查脚本(检测本机核心服务是否正常,如 Nginx/Redis/业务进程)
vrrp_script check_service {
script "/etc/keepalived/check_service.sh" # 脚本路径(需手动创建)
interval 3 # 检查间隔(3秒)
weight -20 # 检查失败时,节点权重减20(触发切换)
fall 2 # 连续2次失败视为服务异常
rise 2 # 连续2次成功视为服务恢复
}
# VRRP 实例(核心配置,定义 VIP 和主从关系)
vrrp_instance VI_1 {
state MASTER # 节点角色(MASTER/BACKUP)
interface eth0 # 绑定的网卡(需改为你的实际网卡,如 ens33、eth1)
virtual_router_id 51 # 虚拟路由ID(主从必须一致,范围 0-255)
priority 100 # 优先级(MASTER > BACKUP,如 MASTER=100,BACKUP=90)
advert_int 1 # VRRP 通告间隔(1秒,主从同步心跳)
# 认证配置(主从必须一致,避免非法节点接入)
authentication {
auth_type PASS # 认证方式(PASS 简单密码认证,2.3.x 支持)
auth_pass 1111 # 认证密码(4位数字,主从需相同)
}
# 虚拟 IP(VIP,可配置多个,主从切换时自动漂移)
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip # VIP + 子网掩码 + 网卡标签
# 192.168.1.101/24 # 如需多个 VIP,换行添加
}
# 绑定健康检查脚本(触发故障切换的条件)
track_script {
check_service
}
# (可选)主从切换时执行的钩子脚本(如通知业务、日志记录)
notify_master "/etc/keepalived/notify.sh MASTER" # 成为主节点时执行
notify_backup "/etc/keepalived/notify.sh BACKUP" # 成为备节点时执行
notify_fault "/etc/keepalived/notify.sh FAULT" # 节点故障时执行
}
8.编译安装nginx1.28.0
1.# 安装基础编译工具、依赖库
yum install -y gcc gcc-c++ make zlib zlib-devel pcre pcre-devel openssl openssl-devel
#(可选)若需支持 IPv6、HTTP/2 等高级功能,补充安装
yum install -y libxslt-devel gd-devel geoip-devel
2.安装源码包
wget https://nginx.org/download/nginx-1.28.0.tar.gz
3.# 验证压缩包完整性(可选,防止下载损坏)# 先获取官方 MD5 校验值:
md5sum nginx-1.28.0.tar.gz
# 对比输出结果与官方 MD5,一致则正常# 解压源码包tar -zxvf nginx-1.28.0.tar.gz
4.# 进入解压后的源码目录
cd nginx-1.28.0
5.配置编译参数
./configure \--prefix=/usr/local/nginx \ # 安装目录(核心,后续所有文件都在这)
--conf-path=/etc/nginx/nginx.conf ##指定配置文件目录
--user=nginx \ #运行用户
--group=nginx \ # 运行组
--with-http_ssl_module \ # 启用 SSL 模块(支持 HTTPS)
--with-http_v2_module \ # 启用 HTTP/2 模块(提升访问速度)
--with-http_realip_module \ # 启用真实 IP 模块(后端服务获取客户端真实 IP)
--with-http_stub_status_module \ # 启用状态监控模块(查看 Nginx 运行状态)
--with-http_gzip_static_module \ # 启用 Gzip 静态压缩模块(优化静态资源传输)
--with-pcre \ # 启用 PCRE 正则支持(URL 重写必备)
--with-stream \ # 启用 Stream 模块(支持 TCP/UDP 代理,如数据库代理)
--without-http_autoindex_module \ # 禁用自动索引模块(避免目录遍历风险)
--without-http_ssi_module \ # 禁用 SSI 模块(非必需,减少资源占用)
--with-cc-opt="-O2 -fPIE -fstack-protector-strong" \ # 编译器优化(提升性能+安全)
--with-ld-opt="-Wl,-z,relro,-z,now"
6.编译和安装
make -j1
make install
7.将nginx加入systemd管理
vi /etc/systemd/system/nginx.service
[Unit]
Description=Nginx HTTP Server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
加载systemd管理,并启动nginx
systemctl daemon-reload
systemctl restart nginx
###如果报错请看日志#####
journalctl -u nginx -f --no-pager
##报错内容
nginx: [emerg] unknown log format "main" in /etc/nginx/nginx.conf:25
我遇到的:25行引用了main格式,但配置中没有定义这个日志格式
解决:在nginx配置文件中是有的,只是备注释掉了,打开注释即可
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
重新启动nginx
systemctl restart nginx
8.随后修改日志文件的目录,将nginx的日志写入到/var/log/nginx/
创建目录:
touch error.log #「异常错误信息」
touch access.log # 记录「正常访问行为」
###nginx正常启动,但是日志文件报错
11月 25 21:44:19 192.168.20.128 systemd[1]: Can't open PID file /usr/local/nginx/logs/nginx.pid (yet?) after start: No such file or directory
解决;在systemd管理里面加入
ExecStartPost=/bin/sleep 1 # 启动后延迟 1 秒,给 Nginx 生成 PID 文件的时间
加载systemd、关闭nginx所有进程并重启nginx解决
systemctl daemon-reload
systemctl stop nginx && pkill -9 nginx
systemctl restart nginx
####nginx配置方向代理#####
1.只留全局配置,其余全部删除
vi /etc/nginx/nginx.conf
user root;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /usr/local/nginx/logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
include /etc/nginx/proxy.conf;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
}
2.创建代理文件(这个文件只做代理),进入nginx目录
cd /etc/nginx/
创建文件
touch proxy.conf
3.加入以下配置文件
# upstream backend {
server 192.168.20.135:80;
server 192.168.20.132:80;
}
#虚拟主机配置(反向代理核心)
server {
listen 80;
server_name 192.168.20.200; # 你的 Nginx 服务器VIP
location / {
proxy_pass http://backend; # 反向代理转发
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect default;
}
}
8.部署WEB网站,两台配置同上
1.安装依赖包
yum install -y gcc gcc-c++ make pcre-devel openssl-devel expat-devel
# 安装 APR 核心库 + 开发包(必需)
yum install -y apr apr-devel apr-util apr-util-devel
2.下载源码包
wget https://dlcdn.apache.org/httpd/httpd-2.4.65.tar.gz
3.解压并接入解压目录
tar -zxvf httpd-2.4.62.tar.gz && cd httpd-2.4.62
4.配置编译参数
./configure \--prefix=/usr/local/httpd \
--enable-so \
--enable-ssl \
--enable-proxy \
--enable-proxy_http \
--with-mpm=prefork
5.编译安装
make -j1
make install
6.将httpd的配置文件复制一份到/etc/httpd/httpd.conf
(1)创建目录
mkdir -p /etc/httpd/
(2)复制到指定目录下
cp /usr/local/httpd/conf/httpd.conf /etc/httpd/
(3)创建日志文件以及httpd的家目录
mkdir -p /var/www/html/
mkdir -p /var/log/httpd/access_log
mkdir -p /var/log/httpd/error_log
7.使用grep查找httpd配置文件的家目录以及日志信息并修改指定目录
(1)查找日志文件
grep 'access_log' /etc/httpd/httpd.conf
grep 'error_log' /etc/httpd/httpd.conf
(2)默认家目录是/usr/local/httpd/htdocs/
grep '/var/www/html/' /etc/httpd/httpd.conf #已修改
DocumentRoot "/var/www/html/"
<Directory "/var/www/html/">
8.创建系统服务管理
[Unit]
Description=Apache HTTP Server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/httpd/bin/apachectl start -f /etc/httpd/httpd.conf #指定目录
ExecReload=/usr/local/httpd/bin/apachectl graceful -f /etc/httpd/httpd.conf
ExecStop=/usr/local/httpd/bin/apachectl stop
PIDFile=/usr/local/httpd/logs/httpd.pid
ExecStartPost=/bin/sleep 1
[Install]
WantedBy=multi-user.target
#查看日志
journalctl -u httpd -f --no-pager
加载systemd单元并重启httpd服务
systemctl daemob-reload
systemctl restart httpd
部署php php-mysqld组件
1.配置华为源,下载安装Remi源时缺少的依赖包epel-release
华为源:
[base]
name=base
baseurl=https://repo.huaweicloud.com/centos/7/os/x86_64/
enable=1
gpgcheck=0
[extras]
name=extrax
baseurl=https://repo.huaweicloud.com/centos/7/extras/x86_64/
enable=1
gpgcheck=0
[updates]
name=updates
baseurl=https://repo.huaweicloud.com/centos/7/updates/x86_64/
enable=1
gpgcheck=0
[queens]
name=queens
baseurl=https://repo.huaweicloud.com/centos/7/cloud/x86_64/openstack-queens/
enable=1
gpgcheck=0
[virt]
name=virt
baseurl=https://repo.huaweicloud.com/centos/7/virt/x86_64/kvm-common/
enable=1
gpgcheck=0
yum install -y epel-release
2.安装php8.3源
yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
2.启用Remi 源的 PHP 8.4 仓库
yum-config-manager --enable remi-php83
##如果没有这条命令,下载对应的工具包
yum install -y yum-utils
3.安装 PHP 及 MySQL 扩展(mysqlnd 原生驱动)
安装前先把本地源复制到~下面,因为安装php组件时他会先去寻本地源上有没有这个包
mv /etc/yum.repos.d/bdy.repo
在进行安装##
yum install -y php php-mysqlnd
4.# 验证安装
php -v # 应显示 PHP 8.3.x
PHP 8.3.8 (cli) (built: Jun 4 2024 14:53:17) (NTS gcc x86_64)
php -m | grep mysql # 应显示 mysqlnd、mysqli 等扩展
##客户端(WEB1和WEB2)安装phpredis扩展程序
1.下载phpredis扩展程序
wget https://github.com/phpredis/phpredis/archive/refs/tags/6.0.2.tar.gz
或
wget https://gitee.com/mirrors/phpredis/repository/archive/6.0.2.tar.gz -O phpredis-6.0.2.tar.gz
2.解压源码包并进入目录
tar xzf 6.0.2.tar.gz && cd phpredis-6.0.2/
3.用 phpize 初始化构建环境(关键步骤)
phpize
#如果失败需要安装环境php-devel,如果继续失败请确认版本是否符合
yum install -y php-devel (因为我之前已经安装过php8.0版本,源在yum里,需要注意,先把本地源移到其它位置,否则先到本地源里去下载php-devel(版本较低,))
4.配置编译目录及其它
./configure --with-php-config=/usr/bin/php-config --enable-redis
5.编译安装
make && make install
6.修改vim /etc/php.ini配置文件,添加redis.so模块,加到最后一行即可
extension=redis.so
7.重启Apache服务,写入phpinfo测试页面,通过浏览器访问,http://IP/aa.php
vi /var/www/html/aa.php 加入以下内容
<?php
phpinfo();
?>
测试:
查看是否有redis模块。
####客户端访问discuz论坛,发现httpd网站没有解析php模块,导致客户端不能正常访问discuz论坛网站
1.找到 PHP 模块文件的路径
find / -name "libphp*.so" (记住输出的路径)
比如:/usr/lib64/httpd/modules/libphp.so
2.在 Apache 配置文件中添加 PHP 解析配置
vi /etc/httpd/conf/httpd.conf (加到httpd配置文件的最后面)
(1) 加载 PHP 模块(路径替换为你找到的 libphp.so 位置)
LoadModule php_module /usr/lib64/httpd/modules/libphp.so
(2). 配置 .php 文件的解析规则:将 .php 后缀的文件交给 PHP 模块处理
AddHandler application/x-httpd-php .php
3.PHP动态网站的通用配置,缺一不可 —— 少了任何一条,都会导致论坛无法正常显示或功能异常
# 修正后的 Options 行(二选一)
DocumentRoot "/var/www/html/" (找到这个模块)
<Directory "/var/www/html/"> (需加到里面)
Options Indexes FollowSymLinks ExecCGI 启用 / 禁用当前目录的核心功能
# 或 Options +Indexes +FollowSymLinks +ExecCGI
AllowOverride All 允许当前目录及其子目录使用 .htaccess 文件覆盖当前配置
Require all granted 允许所有客户端访问当前目录(Apache 2.4+ 版本的权限指令
DirectoryIndex index.php index.html index.htm 指定用户访问目录时,Apache 优先查找的 “默认首页文件”
</Directory>
整体配置的核心用途
这组配置是 搭建动态网站(如 PHP 网站)的基础配置,典型场景:
允许访问目录、跟随软链接(适配网站目录结构);
允许执行 PHP/CGI 脚本(运行动态程序);
支持 .htaccess 自定义规则(比如 WordPress 的固定链接、伪静态);
优先加载动态首页(index.php),兼容静态首页(index.html)
9.部署redis+keepalived,实现数据缓存加高可用
1.# 安装 GCC 编译器、依赖库
yum install -y gcc gcc-c++ make jemalloc-devel openssl-devel tcl
2.创建redis存放目录,并进入目录
mkdir -p /opt/redis/ && cd /opt/redis/
3.# 下载官方源码包(官网直达,无篡改风险)
wget https://download.redis.io/releases/redis-7.4.0.tar.gz
4.# 解压源码包
tar -zxvf redis-7.4.0.tar.gz
5.# 进入源码目录
cd redis-7.4.0
6.# 编译(指定使用 jemalloc 内存分配器,优化性能)
make -j1
7.# 安装到指定目录(默认 /usr/local/redis,可自定义)
make PREFIX=/usr/local/redis install
8.创建日志目录以及配置文件命令
mkdir -p /var/log/redis/
mkdir -p /etc/redis/
将redis.conf配置文件和日志文件复制到这个目录
cp redis.conf /etc/redis/ #配置文件
cp redis.log /var/log/redis/ #日志文件
9.修改reids配置文件的日志目录及redis密码
logfile "/var/log/redis/redis.log"
requirepass 123456 # 默认被注释,示例密码 foobared
###重要###
grep "daemonize" /etc/redis/redis.conf
是否为yes,如果不是立即修改,因为后续redis启动时会报错说start operation timed out. Terminating.
10.将redis加入到systemd管理
[Unit]
Description=Redis 7.4 Server
After=network.target
[Service]
Type=forking
PIDFile=/var/run/redis_6379.pid
ExecStart=/opt/redis/redis-7.4.0/src/redis-server /etc/redis/redis.conf
ExecStop=/opt/redis/redis-7.4.0/src/redis-cli -a 123456 shutdown
Restart=always
User=root
Group=root
TimeoutStartSec=120
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
加载配置文件并启动服务
systemctl daemon-erload
systemctl restart redis
11.日志中两个告警,可解决可不解决
(1)TCP 半连接队列限制
73106:M 26 Nov 2025 20:22:08.725 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
解决:
1. 临时生效sysctl net.core.somaxconn=1024#
2. 永久生效echo "net.core.somaxconn = 1024" >> /etc/sysctl.conf
加载配置sysctl -p
(2)内存过量使用未开启
WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. 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.
解决:
1. 临时生效(无需重启)
sysctl vm.overcommit_memory=1
2. 永久生效(重启服务器后仍有效)
echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
加载配置sysctl -p
遇到的问题:
确认 Redis 的 daemonize 配置是 yes(后台启动)?
Type=forking 必须搭配 Redis 的 daemonize yes(默认是 yes),若不小心改成 daemonize no,Redis 会前台运行,不会 fork 子进程,也不会生成 PID 文件,systemd 会一直等 fork 行为,最终超时。
示例 1:bind 127.0.0.1 → 仅本机访问(默认配置,最安全);
示例 2:bind 192.168.20.138 → 仅内网 192.168.20.x 网段能访问;
示例 3:bind 0.0.0.0 或 bind * → 所有网络可访问(需密码 + 防火墙);
示例 4:bind 127.0.0.1 192.168.20.138 → 允许本机 + 内网访问(推荐内网部署)。
9.配置NFS共享存储目录
1.下载nfs-utils*
yum install -y nfs-utils*
systemctl restart rpcbind 启用进程
systemctl restart nfs 启动nfs
2.关闭防火墙
systemctl stop firewalld
setenforce 0
3.创建共享目录
mkdir -p /luntan/
4.进入共享目录
cd /luntan
5.使用git下载新版论坛包
git clone https://gitee.com/Discuz/DiscuzX.git
6.将移动upload/的全部东西到当前目录下面
mv upload/* . (根据实际情况目录)
7.赋予权限
chmod -R 757 /luntan config uc_*
8.编写配置文件
vi /etc/exports 加入
/luntan 192.168.10.0/24(rw,sync,no_root_squash,)
#检测文件内容
exportfs -t
9.启动进程及nfs
systemctl restart rpcbind
systemctl restart nfs
客户端WEB1和WEB2安装nfs,并进行挂载目录
1.安装nfs
yum -y install nfs-utils*
2.挂载目录
mount 192.168.20.130:/luntan /var/www/html/
10.如果访问论坛报错
| xml_parser_create() | 不支持 | 该函数需要 PHP 支持 XML 。请联系服务商,确定开启了此项功能 |
解决方案:
(1)查询是否只有这三个扩展
php -m | grep -E 'dom|xmlreader'
dom
random
xmlreader
(2)如果没有
1.安装epel源
yum install -y epel-release yum-utils
2.可以从 Remi 仓库下载、安装 PHP 8.3 版本的相关软件包
yum-config-manager --enable remi-php83
3.PHP 8.0 后 php-xml 扩展已拆分,需安装 php-dom 和 php-xmlreader
yum install -y php-dom php-xmlreader
11.总结
本文详细介绍了基于LAMP架构的高可用网站集群部署方案,采用2025年最新版本组件在CentOS7系统上实现。系统架构包含Nginx作为反向代理和负载均衡入口,Apache作为Web服务,MySQL主从集群配合Orchestrator实现自动故障切换,Redis提供缓存服务,NFS实现共享存储。部署过程中重点解决了版本兼容性、服务解析配置、模块加载等技术难点,并通过Keepalived实现各组件的高可用。文章提供了完整的安装配置流程和故障排查方法,最终构建了一个支持主节点故障自动切换、业务不中断的高性能网站集群。测试结果表明,当主节点故障时,系统能够自动完成VIP漂移和主从切换,确保服务持续可用。
170万+

被折叠的 条评论
为什么被折叠?



