4. MySQL高可用实战:基于Operator的MySQL集群部署、主从复制、半同步复制与故障切换

各位好,今天我们聊点硬核的——MySQL高可用。说实话,在云原生时代之前,搞MySQL高可用那叫一个折腾:VIP漂移、MHA、Orchestrator,每个方案都有各自的坑。我最早在传统IDC里做MySQL主从切换,半夜被报警叫醒是家常便饭。后来到了Kubernetes环境,发现Operator模式确实把这件事简化了不少,但前提是你得理解它背后的原理。

今天这一章,我们就围绕MySQL Operator,把集群部署、主从复制、半同步复制、故障切换这几个核心环节彻底讲透。嗯,我会把我在生产环境中踩过的坑也一并分享出来。

4.1 为什么选择MySQL Operator?

说白了,Operator就是Kubernetes上的“自动化运维机器人”。它把DBA的日常操作——部署、扩缩容、备份、故障恢复——都变成了声明式的YAML配置。

我个人习惯用 Percona XtraDB Cluster Operator 或者 MySQL InnoDB Cluster Operator。前者基于Galera,后者基于Group Replication。今天咱们以Percona Operator为例,因为它社区活跃,文档也相对完善。

核心优势:

  • 声明式部署:一个CR(Custom Resource)搞定集群
  • 自动故障检测与恢复:Pod挂了自动拉起
  • 半同步复制原生支持:数据一致性有保障
  • 与Kubernetes生态无缝集成:Service、PV、ConfigMap

4.2 部署MySQL集群:从YAML到Running

先别急着写YAML,你得先装好Operator本身。我记得第一次部署时,忘了装CRD,结果apply下去报了一堆“unknown field”错误。嗯,这个坑我替你们踩过了。

安装Operator很简单,一条命令搞定:

kubectl apply -f https://raw.githubusercontent.com/percona/percona-xtradb-cluster-operator/main/deploy/bundle.yaml

然后,我们来定义一个MySQL集群的CR。这里我给出一个生产级别的配置示例:

apiVersion: pxc.percona.com/v1
kind: PerconaXtraDBCluster
metadata:
  name: mysql-cluster-prod
spec:
  secretsName: mysql-secrets
  pxc:
    size: 3
    image: percona/percona-xtradb-cluster:8.0.32
    resources:
      requests:
        memory: 2Gi
        cpu: "1"
      limits:
        memory: 4Gi
        cpu: "2"
    volumeSpec:
      persistentVolumeClaim:
        storageClassName: fast-ssd
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Gi
  haproxy:
    enabled: true
    size: 2
    image: haproxy:2.8
  backup:
    image: percona/percona-xtradb-cluster-operator:1.13.0-backup
    schedule: "0 2 * * *"
    storages:
      s3:
        type: s3
        bucket: my-backup-bucket
        region: us-east-1
        credentialsSecret: s3-secret

这里有几个关键点:

  • pxc.size: 3 —— 三节点集群,这是高可用的最低要求。两节点的话,脑裂风险很高。
  • haproxy.enabled: true —— 开启HAProxy做流量入口,应用层不需要关心后端哪个MySQL活着。
  • backup.schedule —— 定时备份到S3,我建议至少每天一次。

小提示: 存储类(storageClassName)一定要选对。我遇到过用普通HDD做MySQL数据盘的情况,那IO延迟简直感人。生产环境请务必用SSD,最好是本地NVMe盘。

4.3 主从复制与半同步复制:不只是“抄作业”

MySQL的复制,说白了就是主库写binlog,从库拉过来回放。但这里有个问题:异步复制下,主库写完binlog就返回客户端成功,从库可能还没收到。如果主库突然挂了,数据就丢了。

半同步复制(Semi-Sync Replication)就是为了解决这个问题的。它要求主库在提交事务时,至少等待一个从库确认收到了binlog,才返回客户端成功。这样,即使主库宕机,数据也不会丢。

在Percona Operator中,半同步复制是默认开启的。你可以通过配置来调整行为:

spec:
  pxc:
    configuration: |
      [mysqld]
      rpl_semi_sync_master_enabled=1
      rpl_semi_sync_master_timeout=10000
      rpl_semi_sync_slave_enabled=1

这里 rpl_semi_sync_master_timeout=10000 的意思是:如果10秒内没有从库确认,就退化为异步复制。为什么要设超时?因为如果从库一直不响应,主库会卡住,影响业务写入。

警告: 半同步复制不是万能的。它只能保证binlog被至少一个从库接收,但不能保证从库已经应用了这些日志。如果从库在应用前挂了,数据依然可能丢失。所以,你还需要配合可靠的备份策略。

4.4 故障切换:当主库挂了之后

这是高可用最核心的部分。Operator是怎么做故障切换的?我简单梳理一下流程:

  1. 检测故障: Operator通过Kubernetes的liveness/readiness探针,或者通过Galera的gcache状态,判断某个节点是否健康。
  2. 选主: 如果主库挂了,剩下的从库会通过Galera的投票机制选出一个新主。这个过程是自动的,不需要人工干预。
  3. 流量切换: HAProxy会自动将流量指向新的主库。应用层无感知。
  4. 旧主恢复: 如果旧主库重新加入集群,它会自动同步数据,然后作为从库运行。

我曾经遇到过一个问题:主库挂了,但Operator没有立即切换。排查后发现,是因为liveness探针的超时时间设置得太长。默认是30秒,我改成了10秒,切换速度明显提升。

spec:
  pxc:
    livenessProbes:
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
    readinessProbes:
      initialDelaySeconds: 10
      periodSeconds: 5
      timeoutSeconds: 3

避坑指南: 我曾经把readiness探针的timeoutSeconds设成1秒,结果集群频繁误判节点不可用,导致HAProxy不断切换后端,业务出现间歇性中断。后来我改成3秒,问题解决。探针参数一定要根据实际负载调整,别照抄文档。

4.5 知识体系与核心逻辑

为了让你更直观地理解整个架构,我画了一张流程图。它展示了从客户端请求到数据持久化的完整链路:

MySQL Operator 高可用架构流程图 客户端应用 HAProxy 负载均衡 MySQL 集群(3节点,半同步复制) Node 1 (主) Node 2 (从) Node 3 (从) PV(持久化存储,SSD) S3 备份 图例: 流量路径 半同步复制 备份

这张图里,你看到的是从客户端到存储的完整链路。HAProxy做流量分发,MySQL三节点通过半同步复制保证数据一致性,底层用SSD的PV做持久化,最后定时备份到S3。整个架构没有单点故障。

4.6 生产环境实战建议

最后,我总结几条实战建议,都是真金白银换来的经验:

场景 建议 原因
集群规模 至少3节点,推荐5节点 3节点可容忍1个节点故障,5节点可容忍2个
存储选型 本地NVMe SSD + 分布式存储(如Longhorn) 本地盘性能好,分布式存储提供高可用
备份策略 每天全量备份 + 每6小时增量备份 全量用于恢复,增量减少恢复时间
监控告警 Prometheus + Grafana + 自定义告警规则 关注复制延迟、连接数、磁盘空间
故障演练 每月至少一次手动杀Pod测试 验证Operator的自动恢复能力

最后说一句: 技术方案再完美,也抵不过人为误操作。我见过有人直接 kubectl delete pod 删了主库,结果Operator自动拉起后,数据因为半同步复制没丢。但如果是 kubectl delete pvc 呢?那数据就真没了。所以,权限管控和操作审计同样重要。

好了,这一章的内容就到这里。MySQL高可用不是一蹴而就的事,需要你在实践中不断调优。希望今天的分享能帮你少走一些弯路。

专注资料整理