MySQL 主从复制
用主从复制实现读写分离与容灾。
MySQL 主从复制把写入集中到主库,再同步到从库,读请求可以走从库。
核心要点
- 主库写入并生成 binlog
- 从库拉取 binlog 并重放
- 主从需要稳定网络身份
K8s 中的思路
- StatefulSet 保障实例顺序
- Headless Service 提供稳定 DNS
- 读写分离可用两个 Service
风险提示
- 复制延迟会影响读取一致性
- 主库不可用时需要故障切换
上线时我会先盯这几件事
MySQL 这种主从结构,问题通常不是“Pod 起不来”,而是“起是起了,但角色/数据不对”。我一般会先确认三件事:
- 每个实例是不是都有自己的 PVC(别共享卷)
- 主从的网络身份是不是稳定的(StatefulSet + Headless Service 的 DNS 是否可用)
- 探针是不是在“真的能服务”时才 Ready(否则会出现读写流量打到不该打的地方)
有问题时先把证据拿到手:
kubectl get pods -n <ns> -o wide
kubectl get pvc -n <ns>
kubectl describe pod -n <ns> <pod>
kubectl get svc -n <ns>
kubectl get endpoints -n <ns> <svc> -o wide
如果你遇到“读到旧数据/延迟很大”,第一反应别先改参数,先看复制延迟和磁盘 IO(很多时候就是节点磁盘顶住了,或者资源限得太紧导致抖动)。
实操要点
- 先做快速盘点:
kubectl get nodes、kubectl get pods -A、kubectl get events -A。 - 对比“期望状态”和“实际状态”,
kubectl describe往往能解释漂移或失败原因。 - 名称、Label、Selector 要一致,避免 Service 或控制器找不到 Pod。
快速检查清单
- 资源定义与业务意图一致。
- Namespace、权限、镜像与环境匹配。
- 上线前具备健康探针与可观测日志。
数据与身份的稳定性
有状态应用需要稳定身份与稳定存储。MySQL 复制 通过持久卷、稳定 DNS 与有序生命周期提供这种稳定性,目标是在自动调度与数据安全之间取得平衡。
复制拓扑与一致性
复制系统需要明确一致性模型。常见的是主从或多副本仲裁。Kubernetes 只负责调度与生命周期,不负责共识。你需要理解数据库的主从切换与客户端发现方式。
存储规划与隔离
每个副本应独立 PVC,除非应用明确支持共享卷。规划容量时要考虑增长空间,并通过反亲和性将副本分散到不同节点,降低单点故障影响。
备份与恢复习惯
持久卷不等于备份。建议结合快照与逻辑备份,并定期演练恢复。对于复制系统,恢复顺序会影响主从角色,要在文档中明确步骤。
升级与故障处理
有状态升级更慢,需要分批推进。准备好 readiness 探针,避免误判可用性。节点故障时卷重新挂载可能耗时,需监控挂载状态并考虑更长恢复窗口。
可观测与调优
关注复制延迟、磁盘延时与使用率。资源限制过紧会导致抖动,requests 要合理留出余量。数据库场景下 IO 延迟往往比 CPU 更关键。
主从路由与客户端策略
写流量应指向主节点,读流量可通过 Service 分发到从节点。需要直连时使用稳定 DNS 名称,并在客户端配置明确的角色路由。
维护与自动化
定期进行压缩、清理与一致性校验,选择低峰窗口执行。使用 Operator 或自动化任务管理备份、升级与故障恢复,降低人工操作风险。
kubectl get pods -n demo
kubectl get pvc -n demo
kubectl describe pod db-0 -n demo
运维清单
检查反亲和、PDB、备份任务是否到位。确认每个副本都有独立卷,并演练故障切换流程。稳定性来自配置与习惯的共同作用。
收个尾:主从系统最怕“你以为没事”
复制系统最麻烦的不是 Pod 起不来,而是它“看起来都在跑”,但其实已经开始落后:复制延迟慢慢变大,读请求读到旧数据,最后才爆。
所以我会建议你把两件事当成默认动作:
- 盯复制延迟:延迟上来先看 IO/CPU/网络,不要第一时间调参数。
- 演练切主:不演练你永远不知道真正出事时要多久、会丢多少数据。
如果访问异常,优先确认读写 Service 指向没错、endpoints 里到底是哪些 Pod;主从这类问题通常从“路由打错人”开始。