Rocky Linux 9.5 部署 Percona XtraDB Cluster (PXC) 集群

1. 环境需求与节点规划

1.1 节点规划(示例)

|--------|-----------------|-----------|--------|
| 节点 | IP 地址 | 主机名 | 角色 |
| Node1 | 192.168.106.178 | pxc-node1 | 主节点 |
| Node2 | 192.168.106.179 | pxc-node2 | 从节点 |
| Node3 | 192.168.106.180 | pxc-node3 | 从节点 |

1.2 系统环境配置(所有节点执行)

1.2.1 配置主机名和 Hosts 解析
bash 复制代码
# 按节点分别设置主机名
hostnamectl set-hostname pxc-node1  # 192.168.106.178
hostnamectl set-hostname pxc-node2  # 192.168.106.179
hostnamectl set-hostname pxc-node3  # 192.168.106.180

# 统一添加 hosts 解析
cat >> /etc/hosts << EOF
192.168.106.178 pxc-node1
192.168.106.179 pxc-node2
192.168.106.180 pxc-node3
EOF
1.2.2 关闭 SELinux 和防火墙
bash 复制代码
# 临时关闭 SELinux
setenforce 0

# 永久关闭 SELinux
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# 关闭防火墙(Rocky 9 默认使用 firewalld)
systemctl stop firewalld
systemctl disable firewalld

# 如果使用 nftables(可选检查)
systemctl disable --now nftables 2>/dev/null || true
1.2.3 配置系统内核参数
bash 复制代码
cat >> /etc/sysctl.conf << EOF
# PXC 优化参数
net.ipv4.tcp_syncookies = 1
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.core.netdev_max_backlog = 2000
net.ipv4.ip_local_port_range = 1024 65535

# 内存与脏页优化
vm.swappiness = 0
vm.dirty_ratio = 80
vm.dirty_background_ratio = 5
EOF

sysctl -p

# 禁用透明大页(THP)
cat > /etc/systemd/system/disable-thp.service << EOF
[Unit]
Description=Disable Transparent Huge Pages

[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo never > /sys/kernel/mm/transparent_hugepage/enabled"
ExecStart=/bin/sh -c "echo never > /sys/kernel/mm/transparent_hugepage/defrag"

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now disable-thp
1.2.4 配置资源限制
bash 复制代码
# 全局限制
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
* soft core unlimited
* hard core unlimited
EOF

# PXC 专用用户限制
cat > /etc/security/limits.d/99-pxc.conf << EOF
mysql soft nofile 65535
mysql hard nofile 65535
mysql soft nproc 65535
mysql hard nproc 65535
EOF

# 立即生效(需重新登录)
ulimit -n 65535
1.2.5 安装依赖软件包
bash 复制代码
# 启用 CRB 仓库(部分依赖在 EPEL 中)
dnf config-manager --set-enabled crb
dnf install -y epel-release

# 卸载冲突包
dnf remove -y mariadb* postfix 2>/dev/null || true

# 安装依赖(适配 Rocky 9 包名)
dnf install -y gcc gcc-c++ ncurses-devel cmake \
    libaio libaio-devel bind-utils wget curl \
    perl openssh-clients sysstat make libev \
    lrzsz perl-DBD-MySQL perl-IO-Socket-SSL \
    git scons check boost-devel asio-devel \
    readline-devel numactl-libs socat \
    openssl-devel zlib-devel pam-devel

# 安装 Red Hat 兼容层(部分工具需要)
dnf install -y redhat-lsb-core

2. 安装 Percona XtraDB Cluster

下载地址:Downloads - Percona

这里我将下载好的软件包上传到三个节点的/opt/pxc下,并解压:

2.1 安装依赖

bash 复制代码
dnf install -y epel-release
dnf config-manager --set-enabled crb

dnf install -y openssl-devel zlib-devel pam-devel \
               socat numactl-libs libev perl-DBD-MySQL \
               perl-IO-Socket-SSL rsync

2.2 安装 PXC & XtraBackup

bash 复制代码
cd /opt/pxc

dnf localinstall -y \
  Percona-XtraDB-Cluster-57-5.7.44-31.65.1.el9.x86_64.rpm \
  Percona-XtraDB-Cluster-server-57-5.7.44-31.65.1.el9.x86_64.rpm \
  Percona-XtraDB-Cluster-client-57-5.7.44-31.65.1.el9.x86_64.rpm \
  Percona-XtraDB-Cluster-shared-57-5.7.44-31.65.1.el9.x86_64.rpm \
  percona-xtrabackup-24-2.4.29-1.el9.x86_64.rpm

3. 配置 PXC 节点

3.1 节点1 配置文件 (/etc/my.cnf)

bash 复制代码
[mysqld]
server-id=1
wsrep_node_name=pxc-node1
wsrep_node_address=192.168.106.178
wsrep_cluster_address=gcomm://
# ===== 基础 =====
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

# ===== 网络 =====
bind-address=0.0.0.0
port=3306

# ===== InnoDB =====
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=2G
innodb_log_file_size=1G
innodb_file_per_table=1
innodb_flush_method=O_DIRECT

# ===== Binlog =====
binlog_format=ROW

# ===== PXC / Galera =====
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_name=pxc-cluster
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth=sstuser:s3cretPass
wsrep_slave_threads=4
pxc_strict_mode=ENFORCING

[sst]
streamfmt=xbstream

[client]
socket=/var/lib/mysql/mysql.sock

节点2和节点3的区别:

bash 复制代码
server-id=2
wsrep_node_name=pxc-node2
wsrep_node_address=192.168.106.179
wsrep_cluster_address=gcomm://192.168.106.178,192.168.106.179,192.168.106.180

server-id=3
wsrep_node_name=pxc-node3
wsrep_node_address=192.168.106.180
wsrep_cluster_address=gcomm://192.168.106.178,192.168.106.179,192.168.106.180

3.2 创建数据目录

bash 复制代码
mkdir -p /var/lib/mysql
chown mysql:mysql /var/lib/mysql
chmod 750 /var/lib/mysql

mkdir -p /var/run/mysqld
chown mysql:mysql /var/run/mysqld

4.第 1 节点引导启动(仅 node1)

bash 复制代码
systemctl start mysql@bootstrap.service
systemctl status mysql@bootstrap.service
tail -f /var/log/mysqld.log

使用mysql -uroot -p,若找不到临时密码按照以下步骤操作:

bash 复制代码
#停掉 bootstrap 节点
systemctl stop mysql@bootstrap.service

#以跳过权限表方式启动 MySQL
mysqld --defaults-file=/etc/my.cnf \
       --skip-grant-tables \
       --skip-networking \
       --user=mysql &

#确认已启动
ps -ef | grep mysqld | grep -v grep

#无密码登录
mysql -uroot


-- 重新加载权限表(5.7 必须)
FLUSH PRIVILEGES;

-- 重置 root@localhost 密码
ALTER USER 'root'@'localhost'
IDENTIFIED BY 'YourStrongRootPassword';

-- 创建 SST 用户(与 my.cnf 保持一致)
CREATE USER 'sstuser'@'localhost'
IDENTIFIED BY 's3cretPass';

GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT
ON *.* TO 'sstuser'@'localhost';

-- 可选:远程 root
CREATE USER 'root'@'%'
IDENTIFIED BY 'YourStrongRootPassword';

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'
WITH GRANT OPTION;

FLUSH PRIVILEGES;
EXIT;


# 停掉跳过权限表的 mysqld
mysqladmin -uroot -p'YourStrongRootPassword' shutdown

# 用 systemd 正常启动 bootstrap
systemctl start mysql@bootstrap.service


mysql -uroot -p'YourStrongRootPassword' -e "SELECT @@hostname;"

5.Node2 加入(Node3 同理)

1) SST 用户必须存在且认证方式可用(5.7 一般没问题)

bash 复制代码
mysql -uroot -p'YourStrongRootPassword' -e "
SELECT user,host,plugin FROM mysql.user WHERE user IN ('root','sstuser');
SHOW STATUS LIKE 'wsrep_cluster_size';
"

2) 安装SST 运行期依赖

bash 复制代码
dnf install -y socat rsync openssl

Node2:正常启动(⚠️ 不要用 bootstrap)

bash 复制代码
systemctl start mysql

3)在Node1上验证:

bash 复制代码
mysql -uroot -p'YourStrongRootPassword' -e "
SHOW STATUS LIKE 'wsrep_cluster_size';
SHOW STATUS LIKE 'wsrep_cluster_status';
SHOW STATUS LIKE 'wsrep_ready';
"
# wsrep_cluster_size = 2 就对了

Node3加入后wsrep_cluster_size = 3:

附:pxc-healthcheck.sh

bash 复制代码
#!/bin/bash
# PXC 集群健康检查脚本


# ============ 配置区 ============
MYSQL_USER="${MYSQL_USER:-root}"
MYSQL_PASS="${MYSQL_PASS:-YourStrongRootPassword}"
MYSQL_HOST="${MYSQL_HOST:-localhost}"
MYSQL_PORT="${MYSQL_PORT:-3306}"
MIN_CLUSTER_SIZE="${MIN_CLUSTER_SIZE:-2}"
# =================================

# ============ 函数定义 ============
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

check_mysql_connection() {
    if ! mysql -u"${MYSQL_USER}" -p"${MYSQL_PASS}" \
         -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" \
         -e "SELECT 1;" >/dev/null 2>&1; then
        log_message "ERROR: 无法连接到 MySQL 服务器"
        return 1
    fi
    return 0
}

get_wsrep_status() {
    mysql -u"${MYSQL_USER}" -p"${MYSQL_PASS}" \
          -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" \
          -e "SHOW STATUS LIKE 'wsrep_%';" 2>/dev/null
}

check_cluster_health() {
    local cluster_status cluster_size wsrep_ready
    local exit_code=0
    
    # 获取集群状态
    local status_output
    status_output=$(get_wsrep_status)
    
    # 提取关键指标
    cluster_status=$(echo "${status_output}" | awk '/wsrep_cluster_status/{print $2}')
    cluster_size=$(echo "${status_output}" | awk '/wsrep_cluster_size/{print $2}')
    wsrep_ready=$(echo "${status_output}" | awk '/wsrep_ready/{print $2}')
    
    # 输出详细信息
    log_message "=== PXC 集群健康检查结果 ==="
    log_message "节点: ${MYSQL_HOST}:${MYSQL_PORT}"
    log_message "集群状态: ${cluster_status:-N/A}"
    log_message "集群节点数: ${cluster_size:-0} (最小要求: ${MIN_CLUSTER_SIZE})"
    log_message "WSREP 就绪: ${wsrep_ready:-N/A}"
    
    # 检查各项指标
    if [[ "${cluster_status}" != "Primary" ]]; then
        log_message "CRITICAL: 集群状态异常 (非 Primary)"
        exit_code=2
    fi
    
    if [[ -z "${cluster_size}" ]] || (( cluster_size < MIN_CLUSTER_SIZE )); then
        log_message "CRITICAL: 集群节点数不足 (当前: ${cluster_size}, 要求: >=${MIN_CLUSTER_SIZE})"
        exit_code=2
    fi
    
    if [[ "${wsrep_ready}" != "ON" ]]; then
        log_message "CRITICAL: WSREP 未就绪"
        exit_code=2
    fi
    
    # 额外检查(可选)
    local local_state
    local_state=$(echo "${status_output}" | awk '/wsrep_local_state_comment/{print $2}')
    log_message "本地状态: ${local_state:-N/A}"
    
    if [[ "${local_state}" != "Synced" ]]; then
        log_message "WARNING: 本地节点未同步 (状态: ${local_state})"
        (( exit_code < 1 )) && exit_code=1
    fi
    
    return ${exit_code}
}
# =================================

# ============ 主流程 ============
main() {
    # 检查 MySQL 连接
    if ! check_mysql_connection; then
        exit 2
    fi
    
    # 执行健康检查
    if check_cluster_health; then
        log_message "OK: 集群运行正常"
        exit 0
    else
        local ret=$?
        log_message "CRITICAL: 检测到集群问题"
        exit ${ret}
    fi
}
# =================================

# 执行主函数
main
bash 复制代码
# 设置环境变量(推荐)
export MYSQL_PASS="YourStrongRootPassword"
./pxc-healthcheck.sh
相关推荐
A小辣椒1 天前
TShark:Wireshark CLI 功能
linux
A小辣椒1 天前
TShark:基础知识
linux
AlfredZhao1 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
大树883 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式