跳转到内容

RadonDB MySQL 面试题

30 道题
分类
数据库
子分类
mysql
题目数
30 道
已阅读 0 / 30 题
1 RadonDB MySQL 的整体架构是什么?核心组件有哪些?

答案:

RadonDB MySQL 是面向 Kubernetes 的云原生 MySQL 高可用数据库集群解决方案,由青云科技(QingCloud)开源的 RadonDB 社区维护。其架构基于 Kubernetes StatefulSet 部署,核心组件包括 MySQL(数据库引擎)、Xenon(高可用管理器)、Backup Sidecar(备份代理)以及 Operator(控制器)。

组件职责部署形态
MySQL数据库引擎,承载数据存储与查询StatefulSet 容器,每副本一个 Pod
Xenon高可用管理器,负责 Raft 选举、主从切换、故障检测与 MySQL 同 Pod 的 Sidecar 容器
Backup Sidecar执行全量/增量备份与恢复,基于 XtraBackup与 MySQL 同 Pod 的 Sidecar 容器
OperatorCRD 控制器,管理集群生命周期(创建/扩缩容/升级/删除)独立 Deployment,一个集群一个 Operator 实例
Metrics Exporter采集 MySQL 运行时指标,暴露 Prometheus 格式Sidecar 容器,集成 Prometheus ServiceMonitor
Init Container初始化数据目录、搭主从复制、从备份恢复Pod 启动时执行,一次性任务

每个 MySQL Pod 包含三个核心容器(MySQL + Xenon + Metrics Sidecar),共享同一网络命名空间和存储卷。Xenon 通过本地 Unix Socket 管理 MySQL,Backup Sidecar 通过 Job/CronJob 机制触发备份任务。

graph TD
    Operator["RadonDB Operator
(CRD Watch / Reconcile Loop)"] HeadlessSvc["Headless Service
(mysql-radondb-headless)"] subgraph StatefulSet["StatefulSet Replicas (3)"] Pod0["Pod-0: MySQL / Xenon / Exp
Leader"] Pod1["Pod-1: MySQL / Xenon / Exp
Follower"] Pod2["Pod-2: MySQL / Xenon / Exp
Follower"] end Operator -->|"Watch / Manage"| HeadlessSvc HeadlessSvc --> Pod0
2 Xenon 高可用管理器的核心原理是什么?

答案:

Xenon 是基于 Raft 协议实现的 MySQL 高可用管理器,以 Sidecar 模式与 MySQL 进程同 Pod 运行。它通过本地 Unix Socket 直接管理 MySQL 的生命周期、复制状态和故障切换。

Xenon 的核心工作流:

  1. Raft 选举:集群内所有 Xenon 节点构成 Raft Group,通过心跳和投票选出单一 Leader。Leader 即为主节点(Master/Primary),Follower 即为从节点(Slave/Secondary)。
  2. 心跳检测:Leader 周期性向 Follower 发送心跳(默认 3s / 6s 超时)。Follower 在超时窗口内未收到心跳即触发新的选举。
  3. MySQL 接管:Xenon 通过 Unix Socket 直接执行 STOP SLAVE / START SLAVE / CHANGE MASTER TO 等 MySQL 命令。选举出的 Leader 将本地 MySQL 提升为可写(read_only=OFF),Follower 将本地 MySQL 设为只读(read_only=ON)并建立复制。
  4. 故障检测与切换:检测到 Leader 故障或网络不可达后,Raft 自动选举新 Leader,新 Leader 接管 MySQL 写入。整个切换流程通常在 10-30 秒内完成。
  5. GTID 一致性保证:Xenon 依赖 GTID(Global Transaction Identifier)保证主从数据一致性。所有事务通过 GTID 标识,Failover 时新 Leader 基于 GTID 集合决定是否需要从其他节点补偿差异数据。
sequenceDiagram
    participant L as Leader Xenon
    participant F1 as Follower Xenon-1
    participant F2 as Follower Xenon-2
    L->>F1: Heartbeat
    L->>F2: Heartbeat
    Note over L: Leader 宕机 / 网络分区
    Note over L: Tick 超时
    Note over F1: Tick 超时
    F1->>L: RequestVote
    F1->>F2: RequestVote
    F2-->>F1: VoteGranted
    Note over F1: New Leader Elected
SET GLOBAL read_only=OFF F2-->>F1: Replication
3 RadonDB 如何实现 MySQL 主从复制与自动故障转移?

答案:

RadonDB 的主从复制基于 MySQL 原生 GTID 复制,由 Xenon 管理其生命周期。Operator 初始化集群时自动配置所有节点的半同步复制(Semi-Synchronous Replication)。

复制建立流程:

  1. Operator 创建 Init Container,在 Pod-0 上初始化 MySQL 数据目录并启动 MySQL。
  2. Xenon-0 通过 Raft 选举成为初始 Leader,设置 read_only=OFF
  3. Pod-1 的 Init Container 通过 XtraBackup 从 Pod-0 全量复制数据。
  4. Pod-1 启动 MySQL,Xenon-1 通过 Raft 获知 Leader 为 Pod-0,自动执行 CHANGE MASTER TO 建立复制。
  5. Pod-2 同理从 Leader 复制数据并建立复制链。

故障转移过程:

  1. Xenon Follower 在心跳超时(默认 6s)后判定 Leader 失联。
  2. Follower 发起 Raft RequestVote,获得多数票后成为新 Leader。
  3. 新 Leader 执行 STOP SLAVE,将本地 MySQL 设置 read_only=OFF
  4. 新 Leader 通过 GTID_PURGED 确认与旧 Leader 的数据差异,必要时从其他节点补偿。
  5. 其余 Follower 通过 Raft 感知 Leader 变更,自动 CHANGE MASTER TO 指向新 Leader。
  6. Operator 更新 Service 的 Selector/Endpoint 指向新 Leader,写流量自动切至新主节点。
机制配置说明
复制模式Semi-Synchronous(半同步)至少一个从库确认收到 binlog 后事务才提交成功
复制协议GTID全局事务 ID,保障 Failover 后数据一致性
复制过滤replicate-wild-do-table / replicate-wild-ignore-table选择性复制
只读保护super_read_only=ONFollower 节点禁止写入
4 Xenon 的 Raft 选举机制如何工作?

答案:

Xenon 实现了完整的 Raft 共识协议,用于在 MySQL 集群中选举 Leader 和维护一致性。

Raft 选举核心概念:

概念说明
Term(任期)全局单调递增的逻辑时钟,每次选举开始新 Term
Leader当前 Term 中处理所有写请求的节点
Follower被动接收日志的节点
Candidate发起选举的中间状态
Quorum多数派(N/2+1),3 节点集群需 2 票

选举触发条件:

  • Leader 心跳超时(raft-timeout,默认 3000ms)
  • 集群初始化时为 Term 0,所有节点争选
  • Leader 主动降级(如收到 SIGTERM)时触发新选举

选举流程:

  1. Follower 心跳超时后,递增 Term(Term += 1),自身转为 Candidate。
  2. Candidate 向所有节点发送 RequestVote RPC,携带自身 Term、最后一条日志的 Index 和 Term。
  3. 接收节点判断:Candidate 的 Term 必须 >= 自身 Term,且 Candidate 的日志不比自身旧(LastLogIndex 更大或同 Index 时 LastLogTerm 更新)。
  4. 若获多数票,Candidate 转为 Leader,立即发送心跳广播新 Leader 身份。
  5. 若未获多数票(或发现更高 Term 的消息),Candidate 退回 Follower,等待新一轮选举。

投票权重:Xenon 支持为不同节点配置不同投票权重(admit-defeat-hearbeat-count),生产环境三节点等权(各 1 票)为推荐配置。

# Xenon 选举相关配置参数
{
  "raft-timeout": 3000,        # 心跳超时(毫秒)
  "raft-election-timeout": 6000, # 选举超时(毫秒)
  "raft-heartbeat-interval": 150, # 心跳间隔(毫秒)
  "leader-start-command": "mysql -e 'SET GLOBAL read_only=OFF;'",
  "leader-stop-command": "mysql -e 'SET GLOBAL read_only=ON;'"
}
5 RadonDB CRD 资源的核心字段有哪些?

答案:

RadonDB 通过 Kubernetes CRD(Custom Resource Definition)描述 MySQL 集群的期望状态,Operator 负责 Reconcile Loop 将实际状态持续向期望状态收敛。

核心 CRD 类型:

  • MysqlCluster:描述 MySQL 集群拓扑
  • MysqlVersion:描述 MySQL 镜像版本
  • MysqlBackup:描述备份任务
  • MysqlRestore:描述恢复任务

MysqlCluster CRD 关键字段:

apiVersion: mysql.radondb.com/v1beta1
kind: MysqlCluster
metadata:
  name: my-cluster
spec:
  mysqlVersion: "8.0.30"                    # MySQL 版本
  replicas: 3                                # 副本数(奇数,至少 1)
  image: radondb/mysql:8.0.30                # MySQL 镜像
  xenonImage: radondb/xenon:1.1.7            # Xenon 镜像
  backupImage: radondb/percona-xtrabackup:2.4 # 备份镜像
  
  mysqlOpts:                                # MySQL 配置参数
    innodb_buffer_pool_size: "2G"
    max_connections: 1000
    slow_query_log: "ON"
    character-set-server: "utf8mb4"
    
  xenonOpts:                                # Xenon 配置参数
    raft-timeout: 3000
    raft-election-timeout: 6000
    
  resources:                                # 资源配额
    requests:
      cpu: "2"
      memory: "4Gi"
    limits:
      cpu: "4"
      memory: "8Gi"
      
  persistence:                              # 持久化存储
    size: "100Gi"
    storageClassName: "local-storage"
    
  backup:                                   # 备份策略
    schedule: "0 2 * * *"                  # Cron 表达式,每天凌晨 2 点
    keepNum: 7                              # 保留最近 7 个备份
    type: "full"                            # full / incremental
    
  monitoring:                               # 监控配置
    exporterImage: radondb/mysqld-exporter:0.14.0
    serviceMonitorLabels:
      team: dba
    
  service:                                  # 服务暴露方式
    type: ClusterIP                         # ClusterIP / NodePort / LoadBalancer
    nodePort: 30306

Status 子资源反映集群实时状态:

status:
  conditions:
  - type: Ready
    status: "True"
    lastTransitionTime: "2025-03-15T10:00:00Z"
  leader: my-cluster-0                       # 当前主节点
  replicas: 3                                # 实际副本数
  readyReplicas: 3                           # Ready 状态副本数
6 RadonDB 在 Kubernetes 上的部署架构(StatefulSet / Headless Service)如何设计?

答案:

RadonDB 基于 Kubernetes StatefulSet 部署,每个 Pod 分配唯一且稳定的网络标识和持久化存储,满足有状态应用对稳定身份和存储顺序的要求。

部署架构要点:

Kubernetes 资源用途说明
StatefulSet管理 MySQL Pod 的生命周期有序启停(0→1→2),每个 Pod 绑定独立 PVC
Headless ServicePod 间服务发现clusterIP: None,DNS 记录直接指向 Pod IP
Service业务读写接入ClusterIP/NodePort/LoadBalancer,通过 Label 路由到 Leader
PersistentVolumeClaim持久化存储每个 Pod 独立 PVC,StatefulSet 生成的固定命名(data-my-cluster-0
ConfigMapMySQL/Xenon 配置挂载为配置文件
Secret凭证管理root 密码、复制用户密码、备份密钥
# Headless Service - 为每个 Pod 提供稳定 DNS
apiVersion: v1
kind: Service
metadata:
  name: my-cluster-headless
spec:
  clusterIP: None
  selector:
    app: mysql
    cluster: my-cluster
  ports:
  - name: mysql
    port: 3306

# 读写 Service - 由 Operator 动态将 Label 指向 Leader
apiVersion: v1
kind: Service
metadata:
  name: my-cluster
spec:
  type: ClusterIP
  selector:
    app: mysql
    cluster: my-cluster
    role: leader          # Operator 动态管理此 Label
  ports:
  - name: mysql
    port: 3306

DNS 解析规则:

  • my-cluster-headless.default.svc.cluster.local → 所有 Pod IP(SRV 记录)
  • my-cluster-0.my-cluster-headless.default.svc.cluster.local → Pod-0 IP(A 记录)
  • my-cluster.default.svc.cluster.local → 当前 Leader IP

Pod 拓扑分布:通过 podAntiAffinity 确保同集群 MySQL Pod 分布在不同 Kubernetes 节点上,避免单节点故障导致多个副本同时不可用。

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchLabels:
          app: mysql
          cluster: my-cluster
      topologyKey: kubernetes.io/hostname
7 RadonDB 的备份与恢复机制(XtraBackup + CronJob)如何实现?

答案:

RadonDB 使用 Percona XtraBackup 执行物理热备份,通过 Kubernetes CronJob 定时触发备份任务的执行。

备份流程:

  1. Operator 根据 MysqlCluster.spec.backup.schedule 创建 MysqlBackup CRD。
  2. Operator 根据 CRD 创建 Job,Job 以 Sidecar 模式在 Leader Pod 中执行 xtrabackup --backup
  3. XtraBackup 直接读取 MySQL 数据目录(/var/lib/mysql),不需要锁表,基于 InnoDB 的 MVCC 机制实现一致性备份。
  4. 备份文件通过 xbstream 打包,上传到对象存储(S3 / MinIO / Ceph RGW)或 PersistentVolume。
  5. 备份完成后 Operator 更新 MysqlBackup CRD 的 Status(Completed/Failed),根据 keepNum 自动清理过期备份。

备份类型:

类型命令说明
全量备份xtrabackup --backup --target-dir=/backup/full备份全部数据文件
增量备份xtrabackup --backup --target-dir=/backup/inc --incremental-basedir=/backup/full仅备份自上次全量以来的变更页
选择性备份xtrabackup --backup --databases="db1 db2"只备份指定库

恢复流程:

  1. 创建 MysqlRestore CRD,指定源备份和恢复目标集群。
  2. Operator 创建 Init Container,挂载备份卷或从对象存储下载备份。
  3. Init Container 执行 xtrabackup --prepare 对备份做 Crash Recovery(前滚 Redo Log,回滚未提交事务)。
  4. 恢复完成后启动 MySQL,Xenon 自动建立复制拓扑。
# 全量备份 CronJob 示例
apiVersion: mysql.radondb.com/v1beta1
kind: MysqlBackup
metadata:
  name: my-cluster-backup-20250315
spec:
  clusterName: my-cluster
  type: full                        # full / incremental
  storage:
    type: s3
    s3:
      bucket: radondb-backups
      endpoint: s3.example.com
      region: us-east-1
      secretName: s3-credentials

备份周期推荐:

  • 生产关键库:每日全量 + 每 6 小时增量
  • 一般业务库:每周全量 + 每日增量
  • 备份保留:至少保留最近 14 天的每日备份
8 RadonDB 的读写分离如何实现?

答案:

RadonDB 集群具备两种数据库访问入口,天然支持读写分离。

读写入口设计:

ServiceLabel Selector用途
my-clusterrole: leader写流量接入,始终指向当前 Leader Pod
my-cluster-readonlyrole: follower读流量接入,负载均衡到所有 Follower Pod

读写分离架构:

Application
    ├── Write ──► Service(role:leader) ──► Leader Pod (read_only=OFF)
    └── Read  ──► Service(role:follower) ──► Follower Pod-1 (read_only=ON)
                                          ──► Follower Pod-2 (read_only=ON)

应用层实现方式:

  1. 双数据源配置(Spring / Django / Rails):配置两个数据源,写操作走 Leader,读操作走 Follower。
  2. 数据库中间件(ProxySQL / ShardingSphere / Vitess):在应用与数据库之间部署 SQL 路由中间件,根据 SQL 类型自动分流。
  3. 连接池路由(HikariCP Read/Write Split):利用连接池的读/写数据源分离能力。
# 只读 Service 示例
apiVersion: v1
kind: Service
metadata:
  name: my-cluster-readonly
spec:
  type: ClusterIP
  selector:
    app: mysql
    cluster: my-cluster
    role: follower
  ports:
  - name: mysql
    port: 3306

Follower 节点默认设置 super_read_only=ON,从数据库层面杜绝意外写入。Xenon 在 Leader 切换后自动更新两个 Service 的 Label Selector,确保路由始终指向正确的角色。

9 RadonDB 如何与 Prometheus 集成实现监控?

答案:

RadonDB 部署 mysqld-exporter Sidecar 容器采集 MySQL 运行时指标,通过 Prometheus ServiceMonitor 或 PodMonitor 接入 Prometheus。

监控架构:

graph TD
    Prometheus["Prometheus"]
    ServiceMonitor["ServiceMonitor CRD"]
    Grafana["Grafana"]
    Exporter["mysqld-exporter
(Sidecar)
:9104"] MySQL["MySQL"] Prometheus --> ServiceMonitor --> Grafana Prometheus -->|"Scrape /metrics"| Exporter ServiceMonitor --> Exporter Exporter -->|"Localhost:3306"| MySQL

核心监控指标:

指标类别关键指标说明
连接状态mysql_global_status_threads_connected当前连接数
QPS/TPSmysql_global_status_queries, com_select/insert/update/delete查询与事务吞吐量
缓冲池mysql_global_status_innodb_buffer_pool_read_requests, _reads缓冲池命中率
复制延迟mysql_slave_status_seconds_behind_master主从延迟(秒)
慢查询mysql_global_status_slow_queries慢查询累计数
锁等待mysql_global_status_innodb_row_lock_waits行锁等待次数
磁盘使用mysql_global_variables_datadir_size_bytes数据目录大小
线程状态mysql_global_status_threads_running活跃线程数
# ServiceMonitor CRD 示例
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: my-cluster-mysql
  labels:
    release: prometheus
spec:
  selector:
    matchLabels:
      app: mysql
      cluster: my-cluster
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

告警规则示例:

  • MySQLDownmysql_up == 0
  • MySQLReplicationLagmysql_slave_status_seconds_behind_master > 30
  • MySQLHighThreadsmysql_global_status_threads_connected > 800
  • MySQLSlowQueriesHighrate(mysql_global_status_slow_queries[5m]) > 10
10 RadonDB 如何实现滚动升级与零停机运维?

答案:

RadonDB 的滚动升级由 Operator 协调,按 Follower → Leader 的顺序逐个重建 Pod,保障升级期间集群始终可写。

升级流程:

  1. 版本镜像准备:更新 MysqlCluster.spec.image 为新版本镜像。
  2. Follower 升级:Operator 从最高索引 Follower 开始(Pod-2 → Pod-1),逐个滚动重建。
    • 删除旧 Pod → PVC 保持绑定 → 新 Pod 以 Init Container 方式启动旧版本 MySQL → 对比数据目录一致性 → 替换为新版本镜像 → 重新加入复制
  3. Leader 降级:所有 Follower 升级完成后,Operator 触发 Leader 主动退位。
    • Operator 发送 Leader Transfer 指令(Patch Xenon API)→ 当前 Leader 放弃 Leader 身份 → Raft 自动选举出新 Leader(已升级的 Follower)
  4. 原 Leader 升级:已降为 Follower 的原 Leader Pod 被删除重建,升级完成后重新加入复制。
  5. 验证:确认所有 Pod Ready,Leader 可写,Follower 复制正常。

升级过程中的保护机制:

  • PodDisruptionBudget(PDB)限制不可用副本数(minAvailable: 2),确保滚动升级期间至少 2 个 Pod 在线。
  • Init Container 校验数据目录与镜像兼容性,不兼容则拒绝启动。
  • Xenon 的 Raft 机制保证 Leader 切换期间无写入丢失。
# PDB 示例
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-cluster-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: mysql
      cluster: my-cluster

升级命令:

kubectl patch mysqlcluster my-cluster --type='merge' \
  -p '{"spec":{"image":"radondb/mysql:8.0.35"}}'
11 RadonDB 的存储配置(PersistentVolume)如何规划?

答案:

RadonDB 每个 MySQL Pod 绑定独立的 PersistentVolumeClaim(PVC),StatefulSet 的 volumeClaimTemplates 确保每个副本拥有独立的持久卷。

存储规划要素:

规划维度方案说明
存储类型Local PV / Rook Ceph / Longhorn / OpenEBS优先 Local PV 获取更高 IOPS,其次分布式存储保障可迁移性
卷大小生产环境不低于 100Gi预留足够空间应对数据增长和 binlog 膨胀
访问模式ReadWriteOnce(RWO)每个 PV 只能被一个 Pod 挂载
存储类按性能分级(fast / standard)不同业务库使用不同性能级别
扩容策略allowVolumeExpansion: true支持在线扩容 PVC 而不重启 Pod
# MySQLCluster 持久化配置
spec:
  persistence:
    size: "200Gi"
    storageClassName: "local-ssd"
    accessModes:
    - ReadWriteOnce
    resources:
      requests:
        storage: 200Gi

存储性能基线:

级别IOPS(4K 随机读)吞吐量延迟适用场景
Local SSD / NVMe300000+2GB/s+<1ms核心交易库
Rook Ceph (SSD)50000+500MB/s2-3ms一般业务库
云厂商云盘(ESSD PL3 / Premium SSD)100000+1GB/s<1ms云上部署
Longhorn (SSD)30000+300MB/s3-5ms一般业务库

存储空间规划公式:

总需求 = (数据大小 + 索引大小) × 1.5(碎片/膨胀) + binlog 保留大小 + 临时表空间 + 快照/克隆预留
12 RadonDB 的 XtraBackup 全量与增量备份的区别是什么?

答案:

XtraBackup 是 Percona 提供的 MySQL 物理在线热备份工具,RadonDB 利用其对不同备份粒度实现灵活的备份策略。

维度全量备份增量备份
原理备份数据集中所有 InnoDB 页面仅备份自上次全量/增量以来变更的页面(LSN 差异)
命令xtrabackup --backup --target-dir=/backup/fullxtrabackup --backup --target-dir=/backup/inc --incremental-basedir=/backup/full
数据量等于当前数据集大小取决于变更量,通常远小于全量
备份时间分钟级(100Gi 约 5-15 分钟)秒级到分钟级
恢复复杂度低,直接 Prepare → Copy Back高,需先 Prepare 全量,再逐一 Apply 增量
恢复时间分钟级(100Gi 约 10-30 分钟)分钟级(取决于增量层数)
存储开销高(每个全量一份完整副本)低(仅存储差异页)
适用场景周期性基线备份频繁的时间点保护

备份策略组合:

graph LR
    F1["全量
Day 1(周日)"] --> I1["增量(1)
Day 2"] I1 --> I2["增量(2)
Day 3"] I2 --> I3["增量(3)
Day 4"] I3 --> F2["全量
Day 5(周四)"] F2 --> I4["增量(1)
Day 6"] I4 --> I5["增量(2)
Day 7"] I5 --> F3["全量
Day 8(周日)"]

XtraBackup Prepare 流程:

  1. xtrabackup --prepare --apply-log-only --target-dir=/backup/full(全量 Prepare)
  2. xtrabackup --prepare --apply-log-only --target-dir=/backup/full --incremental-dir=/backup/inc1(Apply 第一个增量)
  3. xtrabackup --prepare --target-dir=/backup/full --incremental-dir=/backup/inc2(Apply 最后一个增量,不加 --apply-log-only
  4. xtrabackup --copy-back --target-dir=/backup/full(恢复到数据目录)

恢复时间对比:

备份链步骤数典型恢复时间(100Gi 数据)
纯全量110-20 分钟
全量 + 1 增量212-25 分钟
全量 + 5 增量620-40 分钟
全量 + 10 增量1130-60 分钟
13 RadonDB 的故障检测与 Leader 切换流程是怎样的?

答案:

RadonDB 的故障检测依赖 Xenon 的 Raft 心跳机制,由所有 Follower 节点独立判断 Leader 是否存活。

故障检测层次:

检测层机制阈值说明
Raft 心跳Leader 定期向 Follower 发送心跳心跳间隔 150ms,超时 3000msXenon 进程级检测
MySQL 探活Xenon 通过 Unix Socket 定期 mysqladmin ping通常 1s防止 Xenon 正常但 MySQL 僵死
Readiness ProbeKubernetes Liveness/Readiness ProbefailureThreshold: 3容器级检测

故障检测时间线:

T+0s      Leader 故障(OOM/NodeFailure/XenonCrash)
T+0~3s    Follower 心跳超时(raft-timeout: 3000ms)
T+3s      Follower 转为 Candidate,发送 RequestVote
T+3~4s    获得多数票,新 Leader 选出
T+4s      新 Leader 执行 leader-start-command(read_only=OFF)
T+4~5s    新 Leader 广播心跳,Follower 感知新 Leader 身份
T+5~8s    Follower CHANGE MASTER TO 新 Leader
T+5~10s   Operator 更新 Service Label(role: leader 指向新 Pod)
T+10~30s  应用感知连接中断 → 重连 → 恢复写入

Leader 切换类型:

切换类型触发条件数据影响RTO
计划内切换(Planned)滚动升级、维护窗口、手动 kubectl cordon无数据丢失5-10s
故障切换(Unplanned)Leader Pod OOM、节点宕机可能丢失未同步的事务(半同步则 0 丢失)10-30s
脑裂切换(Split-Brain)网络分区导致双 LeaderRaft Quorum 保障仲裁后唯一 Leader15-30s
# 手动触发 Leader 切换
kubectl exec -it my-cluster-0 -c xenon -- xenoncli raft transfer

# 查看集群当前状态
kubectl exec -it my-cluster-0 -c xenon -- xenoncli cluster raft
kubectl exec -it my-cluster-0 -c xenon -- xenoncli mysql status
14 RadonDB 的日志管理(Error / Slow Query / Binlog)如何配置?

答案:

RadonDB 的日志体系覆盖 MySQL 服务器日志、二进制日志(Binlog)和慢查询日志,通过 ConfigMap 集中管理配置,通过 Sidecar(如 Filebeat / Fluent Bit)采集并输出到集中式日志平台。

日志类型MySQL 参数输出路径用途
Error Loglog_errorstderr(容器日志)启动错误、崩溃、复制错误、表损坏
Slow Query Logslow_query_log, long_query_timestderr 或数据目录文件性能瓶颈分析、索引优化
General Loggeneral_logstderr(默认关闭)连接和查询审计(生产环境关闭)
Binloglog_bin, binlog_format数据目录下 binlog.xxxxxx主从复制、PITR(时间点恢复)
Relay Logrelay_log数据目录下Follower 从中继日志重放 Leader 事务
# MySQLCluster 日志相关配置
spec:
  mysqlOpts:
    # Error Log
    log_error_verbosity: "2"        # 1:errors 2:errors+warnings 3:errors+warnings+notes
    
    # Slow Query
    slow_query_log: "ON"
    long_query_time: "1.0"         # 超过 1 秒计入慢查询
    log_queries_not_using_indexes: "ON"
    log_slow_admin_statements: "ON"
    min_examined_row_limit: "1000" # 扫描行数超过 1000 才记录
    
    # Binlog
    log_bin: "ON"
    binlog_format: "ROW"           # ROW 格式利于复制一致性
    binlog_row_image: "FULL"
    sync_binlog: "1"               # 每次事务同步 binlog 到磁盘
    expire_logs_days: "7"          # binlog 保留 7 天
    max_binlog_size: "500M"
    binlog_cache_size: "32768"

日志采集架构:

MySQL Container stdout/stderr
     ├──► kubectl logs (临时查看)
     └──► Fluent Bit / Filebeat DaemonSet
              ├──► Elasticsearch / Loki
              └──► Grafana (日志查询)

配置日志持久化(将日志写入持久化 Volume):

spec:
  mysqlOpts:
    log_output: "FILE"                    # 输出到文件而非 stderr
    slow_query_log_file: "/var/lib/mysql/slow-query.log"
    general_log_file: "/var/lib/mysql/general.log"
15 RadonDB 如何实现集群扩缩容?

答案:

RadonDB 支持水平扩缩容(增减 Replica)和垂直扩缩容(调整 CPU/内存),由 Operator 协调执行。

水平扩容(增加 Follower)

  1. 修改 MysqlCluster.spec.replicas 为目标副本数(如 3 → 5)。
  2. Operator Reconcile 检测到 spec.replicas > status.replicas,创建新 Pod(my-cluster-3)。
  3. Init Container 从当前 Leader 通过 XtraBackup 全量复制数据。
  4. 新 Pod 启动 MySQL 和 Xenon,Xenon 加入 Raft Group 成为 Follower。
  5. Xenon 自动执行 CHANGE MASTER TO 指向当前 Leader,建立复制。

水平缩容(减少 Follower)

  1. 修改 replicas 为目标副本数(如 5 → 3)。
  2. Operator 从最高索引 Pod 开始删除(my-cluster-4my-cluster-3)。
  3. 被删除的 Pod 对应的 PVC 保留(StatefulSet 不自动删除 PVC),需手动清理。
  4. Raft 成员列表自动剔除已删除节点。

垂直扩缩容(调整资源)

  1. 修改 MysqlCluster.spec.resources.requests/limits

  2. Operator 按滚动更新策略(先 Follower 后 Leader)逐个重建 Pod。

  3. 设置 MysqlCluster.spec.updateStrategy.type: OnDelete 可在手动删除时触发重建。

  4. PVC 扩容(若支持 allowVolumeExpansion):

    kubectl patch pvc data-my-cluster-0 -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'
    

扩容注意点:

| 约束 | 说明 |
|------|------|
| 副本数为奇数 | 满足 Raft 多数派投票要求(1 / 3 / 5 / 7) |
| PodAntiAffinity | 扩容需确保目标 Node 不被已有 Pod 占用 |
| 存储容量 | 新 Pod 需匹配存储类支持的容量 |
| 网络带宽 | XtraBackup 数据同步占用带宽,生产环境限制传输速率 |
| Binlog 同步压力 | 新 Follower 追赶数据期间的 IO 压力 |
16 RadonDB 的 MysqlVersion CRD 与版本管理机制是什么?

答案:

MysqlVersion CRD 定义可用的 MySQL 镜像版本元数据,Operator 通过该 CRD 校验升级路径的兼容性,并管理不同 MySQL 版本对应的镜像、Sidecar 版本和配置模板。

apiVersion: mysql.radondb.com/v1beta1
kind: MysqlVersion
metadata:
  name: mysql-8.0.30
spec:
  version: "8.0.30"
  mysqlImage: "radondb/mysql:8.0.30"
  xenonImage: "radondb/xenon:1.1.7"
  mysqlExporterImage: "radondb/mysqld-exporter:0.14.0"
  backupImage: "radondb/percona-xtrabackup:8.0.30"
  initImage: "radondb/mysql:8.0.30"
  # 升级限制:仅允许从指定版本平滑升级
  upgradeConstraints:
    - from: "8.0.28"
    - from: "8.0.29"
    - from: "8.0.30"
```text

版本管理能力:

| 能力 | 说明 |
|------|------|
| 版本发现 | Operator 启动时加载所有 `MysqlVersion` CRD,构建版本映射表 |
| 升级校验 | 创建集群时指定 `spec.mysqlVersion`,Operator 查找匹配的 `MysqlVersion` CRD |
| 滚动升级 | 更新 `MysqlCluster.spec.mysqlVersion`,Operator 按升级约束执行滚动升级 |
| 多版本共存 | 不同集群可使用不同 MySQL 版本,同一集群所有 Pod 版本一致 |
| 镜像替换 | 通过修改 `MysqlVersion.spec.mysqlImage`,所有引用该版本的集群均可感知变更 |

升级路径约束:MySQL 版本升级存在限制——只能跨越一个 GA 版本(如 8.0.288.0.34 不等同于 8.0.288.0.308.0.34 两次升级),Operator 依据 `upgradeConstraints` 拒绝跨版本直升。

查看支持的 MySQL 版本

kubectl get mysqlversion

修改集群使用的 MySQL 版本

kubectl patch mysqlcluster my-cluster –type=‘merge’
-p ‘{“spec”:{“mysqlVersion”:“8.0.35”}}’

17 RadonDB 的参数配置管理(ConfigMap 热更新)如何实现?

答案:

RadonDB 通过 ConfigMap 管理 MySQL 和 Xenon 的运行时配置,支持静态配置(需重启生效)和动态参数(在线修改 SET GLOBAL 生效)两类变更方式。

配置分布:

配置来源管理方式生效方式
spec.mysqlOpts写入 ConfigMap,挂载为 my.cnf静态参数需重启,动态参数可在线修改
spec.xenonOpts写入 ConfigMap,挂载为 xenon.json需重启 Xenon Sidecar
动态参数mysql -e 'SET GLOBAL xxx=yyy'立即生效
持久化动态参数写入 ConfigMap 同时执行 SET GLOBAL重启后从 ConfigMap 重新加载
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-cluster-config
data:
  my.cnf: |
    [mysqld]
    server-id=100
    innodb_buffer_pool_size=2G
    max_connections=1000
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    slow_query_log=ON
    long_query_time=1.0
    binlog_format=ROW
    sync_binlog=1
    gtid_mode=ON
    enforce-gtid-consistency=ON

  xenon.json: |
    {
      "raft-timeout": 3000,
      "raft-election-timeout": 6000,
      "admit-defeat-hearbeat-count": 5,
      "leader-start-command": "mysql -e 'SET GLOBAL read_only=OFF; SET GLOBAL super_read_only=OFF;'",
      "leader-stop-command": "mysql -e 'SET GLOBAL super_read_only=ON; SET GLOBAL read_only=ON;'"
    }
```text

可在线修改的动态参数:

- `max_connections`
- `innodb_buffer_pool_size`(MySQL 8.0+- `slow_query_log` / `long_query_time`
- `read_only`(由 Xenon 自动管理)
- `innodb_flush_log_at_trx_commit`
- `sync_binlog`
- `general_log`

配置变更最佳实践:

1. 修改 ConfigMap 后重新应用

kubectl apply -f configmap.yaml

2. 执行滚动重启,使静态参数生效

kubectl rollout restart statefulset my-cluster

3. 仅修改动态参数(无需重启)

kubectl exec -it my-cluster-0 – mysql -e “SET GLOBAL max_connections=2000;”

18 RadonDB 与 Percona Operator 的对比分析?

答案:

两者都提供 Kubernetes 上运行 MySQL 集群的能力,但在架构、高可用机制、备份方式等方面存在差异。

维度RadonDBPercona Operator for MySQL (PXC)
高可用机制Xenon Raft + GTID 半同步复制Galera Cluster(Multi-Master/Active-Active)
写入模型单 Leader(Leader/Follower)多 Master(任意节点可写,提交时跨节点认证)
一致性模型最终一致性(半同步)强一致性(Galera 基于 Paxos 的认证复制)
故障切换 RTO10-30 秒(Raft 选举 + 复制重建)0 秒(任意节点可写,故障节点自动从集群剔除)
备份工具XtraBackupXtraBackup
最低节点数1(无 HA)或 3(HA)3(Galera 要求奇数票)
跨 DC 延迟敏感性低(异步/半同步)高(Galera 写操作受最慢节点制约)
读扩展读写分离 ServiceProxySQL 集成,透明读写分离
存储引擎InnoDBInnoDB(Galera 支持 wsrep API 的 InnoDB)
Operator 实现语言GoGo
社区活跃度RadonDB 社区(青云主导)Percona(企业支撑)

选型建议矩阵:

场景推荐方案原因
跨 AZ/跨 DC 部署RadonDBXenon Raft 对跨 DC 延迟容忍度高于 Galera
强一致性需求Percona PXCGalera 提供写操作强一致性保证
读密集型业务RadonDB读写分离 Service 简单高效
大量并发写入RadonDBGalera 多 Master 写入的流控机制可能成为瓶颈
运维复杂度RadonDBXenon + MySQL 标准复制,运维心智成本低
19 RadonDB 与 KubeBlocks 的对比分析?

答案:

KubeBlocks 是 ApeCloud 开源的数据库 Kubernetes Operator 平台,提供统一的数据库管理抽象层。RadonDB 是独立 MySQL Operator,两者定位不同但存在交集。

维度RadonDBKubeBlocks
定位单一 MySQL 数据库 Operator多数据库通用 Operator 平台
支持数据库MySQLMySQL / PostgreSQL / Redis / MongoDB / Kafka 等
高可用Xenon Raft + GTID集成 Xenon / Patroni / Sentinel 等 HA 组件
抽象层仅 MySQL 领域模型Add-on 插件化,新增数据库类型以 Add-on 方式接入
运维面板无内建 UIKubeBlocks Dashboard(Web UI)
备份恢复内建 XtraBackup + CronJob统一 Backup API,支持多种备份目标
参数管理ConfigMap + OpsRequest CRDClusterDefinition 中声明式定义 + Reconfiguring
CLI 工具kubectl 直接操作kbcli 命令行
水平扩容直接修改 replicaskbcli cluster horizontal-scaling
垂直扩容修改 resources + 滚动重启kbcli cluster vertical-scaling

核心差异:

  • RadonDB 以 MySQL 为中心的深度优化(Xenon Raft、XtraBackup 集成、MySQL 配置模板),在 MySQL 专项场景深度更高。
  • KubeBlocks 以通用平台为设计目标,通过 Add-on 机制统一管理多数据库,在异构数据库统一治理场景更有优势。
  • KubeBlocks 的 Reconfiguring(参数变更)支持在线/滚动/重启多种策略,抽象层次更高。
  • RadonDB 的 Xenon Raft 选举与 KubeBlocks 的 Xenon Add-on 共享同一组件。
20 RadonDB 与 KubeDB 的对比分析?

答案:

KubeDB 是 AppsCode 开发的 Kubernetes 原生数据库 Operator,覆盖多种数据库类型。两者在 MySQL 管理上的对比:

维度RadonDBKubeDB
开发商青云科技 / RadonDB 社区AppsCode
架构Xenon Raft + MySQL 半同步MySQL Group Replication / 单实例 / Semi-Sync
高可用方案Xenon(内建 HA Manager)MySQL Group Replication(MGR)/ Semi-Sync
TLS/SSL支持 TLS 加密传输内建 cert-manager 自动化 TLS 证书
备份XtraBackup + S3/MinIOStash(AppsCode 自研备份框架)
监控Prometheus mysqld-exporter + ServiceMonitorPrometheus 内建集成 + Grafana Dashboard
许可证Apache 2.0社区版 Apache 2.0 / 企业版付费
Hooks无显式 Hook 机制支持 Init / Backup / Restore 等 Hook 脚本
Schema 管理不涉及支持以 YAML 方式声明 Schema(Table/View/Procedure)
归档支持将旧数据归档至对象存储
弹性伸缩修改 Replicas / ResourcesHPA/ VPA 集成 + 自动扩缩容

核心差异:

  • KubeDB 的 Stash 备份框架提供比 RadonDB CronJob 更丰富的备份治理(保留策略、回滚、跨集群恢复)。
  • KubeDB 内建 cert-manager 集成简化了 TLS 证书生命周期管理。
  • RadonDB 的 Xenon Raft 比 KubeDB 的 Semi-Sync 方案在故障检测和自动切换方面更加自动化。
  • KubeDB 企业版功能(Auto-Scaling、Schema Management、Database Proxy 集成)在部分场景不可用(需付费)。
21 RadonDB 的分布式事务有哪些限制?

答案:

RadonDB MySQL 集群基于 MySQL 异步/半同步主从复制,不提供分布式事务支持。架构为共享存储(单 Leader 写入),而非 Shared-Nothing 分片架构。

事务支持范围:

事务类型支持状态说明
单节点事务完全支持ACID 事务,通过 InnoDB 保证
跨节点写入事务不支持无分布式事务协调器
跨分片事务(XA)不支持RadonDB 不做数据分片
两阶段提交(2PC)不支持无全局事务管理器
读已提交(Read Committed)支持InnoDB 默认隔离级别
可重复读(Repeatable Read)支持InnoDB 默认隔离级别
读未提交(Read Uncommitted)支持不推荐使用
串行化(Serializable)支持性能开销大,谨慎使用
保存点(Savepoint)支持MySQL 原生 Savepoint

数据分布模型:

graph TD
    subgraph Leader["Leader (my-cluster-0)"]
        Data["db1 / db2 / db3 (全量数据)<br/>所有写入在此完成"]
    end

    Leader -->|"Binlog Replication"| Follower1["Follower<br/>(只读副本)<br/>全量数据"]
    Leader -->|"Binlog Replication"| Follower2["Follower<br/>(只读副本)<br/>全量数据"]

对比分片架构(如 Vitess / ShardingSphere):

维度RadonDB分片架构
数据分布全量副本按 Shard Key 分片存储
写扩展垂直扩展(单机升级)水平扩展(增加分片)
跨分片 JOINN/A(无分片)不支持或通过中间件模拟
事务语义完整 ACID单分片 ACID,跨分片最终一致
运维复杂度高(需管理分片键、路由规则、再平衡)
22 RadonDB 的 Service 暴露方式有哪些?

答案:

RadonDB 提供三种 Service 暴露方式,分别适用于集群内部访问、开发测试远程连接和生产环境 LoadBalancer。

Service 类型访问范围适用场景注意事项
ClusterIPKubernetes 集群内部同集群内应用访问数据库默认方式,最安全
NodePort集群节点 IP + 指定端口开发调试、VPN 访问端口范围 30000-32767
LoadBalancer云厂商 LB / MetalLB外部应用访问数据库需 LB 控制器支持
# ClusterIP(默认)
spec:
  service:
    type: ClusterIP

# NodePort
spec:
  service:
    type: NodePort
    nodePort: 30306

# LoadBalancer
spec:
  service:
    type: LoadBalancer
    loadBalancerIP: "10.0.0.100"
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-internal: "true"
      service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
```text

Service Endpoint 动态切换:Operator 实时监控 Xenon Raft 状态,当 Leader 切换后立即更新 Service 的 Label Selector(`role: leader` 指向新 Leader),确保写流量自动切到新主节点。

只读 Service 配置:

apiVersion: v1 kind: Service metadata: name: my-cluster-readonly labels: app: mysql cluster: my-cluster spec: type: ClusterIP selector: app: mysql cluster: my-cluster role: follower ports:

  • name: mysql port: 3306 targetPort: 3306

Pod 端口映射:

| 端口 | 用途 | 说明 |
|------|------|------|
| 3306 | MySQL 服务端口 | 数据库连接 |
| 9104 | mysqld-exporter Metrics | Prometheus 采集 |
| 8080 | Xenon HTTP API | Xenon 状态查询与管理 |
23 RadonDB 的 TLS 加密与安全配置如何实现?

答案:

RadonDB 支持 MySQL 客户端与服务器之间的 TLS 加密通信,以及节点间复制链路的 TLS 加密。

TLS 配置架构:

spec:
  tls:
    enabled: true
    # 引用包含 TLS 证书的 Secret
    secretName: mysql-tls-secret
    # 可选:指定 SAN(Subject Alternative Name)
    issuerRef:
      name: mysql-ca-issuer
      kind: Issuer
```text

Secret 内容要求(`mysql-tls-secret`):

| Key | 内容 | 说明 |
|------|------|------|
| `ca.crt` | CA 根证书 | 签发客户端和服务端证书 |
| `tls.crt` | 服务端证书 | MySQL 服务端使用的 X.509 证书 |
| `tls.key` | 服务端私钥 | 对应服务端证书的私钥 |

MySQL TLS 配置项(Xenon 自动设置):

[mysqld] ssl_ca=/etc/mysql/certs/ca.crt ssl_cert=/etc/mysql/certs/tls.crt ssl_key=/etc/mysql/certs/tls.key require_secure_transport=ON


安全配置集成:

| 安全维度 | 配置 | 效果 |
|------|------|------|
| 传输加密 | `require_secure_transport=ON` | 所有客户端连接必须使用 TLS |
| 复制加密 | Slave 连接自动使用 `MASTER_SSL=1` | 主从复制链路加密 |
| 密码策略 | `validate_password` 插件 | 密码复杂度校验 |
| 连接限制 | `max_connect_errors` / `connect_timeout` | 防暴力破解 |
| 网络安全 | NetworkPolicy 仅允许白名单 CIDR | 最小化暴露面 |
| 审计 | General Log(关闭)+ 应用层审计 | 可审计 SQL 操作 |

NetworkPolicy 限制数据库访问来源

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: mysql-network-policy spec: podSelector: matchLabels: app: mysql cluster: my-cluster policyTypes:

  • Ingress ingress:
  • from:
    • namespaceSelector: matchLabels: name: backend
    • podSelector: matchLabels: app: my-app ports:
    • protocol: TCP port: 3306

用户权限最小化:

– 应用用户仅授权必要库表 CREATE USER ‘app_user’@’%’ IDENTIFIED BY ‘secure_password’ REQUIRE SSL; GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO ‘app_user’@’%’;

– 监控用户仅授予查询权限 CREATE USER ‘monitor’@’%’ IDENTIFIED BY ‘monitor_password’ REQUIRE SSL; GRANT PROCESS, REPLICATION CLIENT, SELECT ON . TO ‘monitor’@’%’;

24 RadonDB 的监控告警规则如何配置?

答案:

RadonDB 复用 Prometheus + Alertmanager + Grafana 栈实现监控告警,告警规则通过 PrometheusRule CRD 定义。

告警分层设计:

层级告警类型紧急程度
P0 / CriticalMySQL 进程停止、主从复制中断、磁盘满立即响应
P1 / Warning复制延迟 > 30s、连接数 >80%、缓冲池命中率 <95%15 分钟内响应
P2 / Info慢查询增长、磁盘使用 >70%、连接异常断连工作时间处理

PrometheusRule 示例:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: mysql-alerts
  labels:
    release: prometheus
spec:
  groups:
  - name: mysql-critical
    rules:
    # P0: MySQL 实例宕机
    - alert: MySQLDown
      expr: mysql_up == 0
      for: 1m
      labels:
        severity: critical
      annotations:
        summary: "MySQL instance {{ $labels.pod }} is down"
        description: "MySQL on pod {{ $labels.pod }} has been down for more than 1 minute."
        runbook_url: "https://wiki.example.com/mysql-down"

    # P0: 复制中断
    - alert: MySQLReplicationBroken
      expr: mysql_slave_status_slave_io_running == 0 or mysql_slave_status_slave_sql_running == 0
      for: 1m
      labels:
        severity: critical
      annotations:
        summary: "MySQL replication broken on {{ $labels.pod }}"

  - name: mysql-warning
    rules:
    # P1: 复制延迟
    - alert: MySQLReplicationLag
      expr: mysql_slave_status_seconds_behind_master > 30
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "MySQL replication lag {{ $value }}s on {{ $labels.pod }}"

    # P1: 连接数超过 80%
    - alert: MySQLHighConnectionUsage
      expr: (mysql_global_status_threads_connected / mysql_global_variables_max_connections) * 100 > 80
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "MySQL connection usage {{ $value | humanize }}% on {{ $labels.pod }}"

    # P1: 缓冲池命中率低于 95%
    - alert: MySQLLowBufferPoolHitRate
      expr: (rate(mysql_global_status_innodb_buffer_pool_read_requests[10m]) - rate(mysql_global_status_innodb_buffer_pool_reads[10m])) / rate(mysql_global_status_innodb_buffer_pool_read_requests[10m]) < 0.95
      for: 10m
      labels:
        severity: warning
      annotations:
        summary: "InnoDB buffer pool hit rate below 95% on {{ $labels.pod }}"

    # P1: 磁盘增长预测
    - alert: MySQLDiskSpacePrediction
      expr: predict_linear(mysql_global_variables_datadir_size_bytes[6h], 24*3600) > 200*1024*1024*1024
      for: 1h
      labels:
        severity: warning
      annotations:
        summary: "MySQL data directory predicted to exceed 200GB in 24h"

  - name: mysql-info
    rules:
    # P2: 慢查询增长
    - alert: MySQLSlowQueriesIncrease
      expr: rate(mysql_global_status_slow_queries[5m]) > 10
      for: 10m
      labels:
        severity: info
      annotations:
        summary: "Slow queries rate {{ $value }}/s on {{ $labels.pod }}"

    # P2: 磁盘使用超过 70%
    - alert: MySQLDiskSpaceUsage
      expr: (mysql_global_variables_datadir_size_bytes / 200*1024*1024*1024) * 100 > 70
      for: 1h
      labels:
        severity: info
      annotations:
        summary: "MySQL data directory usage {{ $value | humanize }}%"

Grafana Dashboard 推荐面板:

面板指标可视化
QPS / TPSrate(mysql_global_status_queries[1m])Graph(双线)
连接数mysql_global_status_threads_connectedGraph
缓冲池命中率计算指标Gauge(0-100%)
复制延迟mysql_slave_status_seconds_behind_masterGraph(单线,按 Pod)
慢查询速率rate(mysql_global_status_slow_queries[5m])Graph
表锁/行锁等待mysql_global_status_innodb_row_lock_waitsGraph
InnoDB IOmysql_global_status_innodb_data_reads/writesGraph
事务提交/回滚rate(mysql_global_status_com_commit[1m])Graph
25 RadonDB 的网络分区与脑裂防护机制是什么?

答案:

RadonDB 的脑裂防护依赖 Raft 协议的 Quorum 机制和 Xenon 的 Lease 检查,多层防护保证任意网络分区下仅存在一个可写 Leader。

脑裂场景分析:

分区类型分区拓扑Raft Quorum结果
对称分区{0} 与 {1, 2} 隔离节点 0: 1票(1/3) < Quorum(2),节点 1,2: 2票(2/3) >= Quorum{1,2} 侧选出新 Leader,节点 0 降为 Follower 且 read_only=ON
完全分区{0} / {1} / {2} 互相隔离每个节点仅 1票 < Quorum全集群无 Leader,所有节点只读
少数派分区{0} 与 {1,2,3,4} 隔离(5 节点){0}: 1票 < Quorum(3),{1,2,3,4}: 4票 >= Quorum(3)多数派侧继续服务

脑裂防护机制层次:

防护层机制作用
Raft Leader LeaseLeader 需持续获得多数节点确认分区后旧 Leader 在 Lease 到期后确认失去多数派支持
Xenon 降级检查leader-stop-command 断开时自动执行 read_only=ON旧 Leader 发现自身不再是 Raft Leader 后立即只读
MySQL super_read_only所有 Follower 强制 super_read_only=ON防止旧 Leader 残留写入
Raft Pre-Vote防止网络恢复后已退位的节点发起无意义选举防止集群恢复时的扰动
// Xenon 脑裂防护配置
{
  "raft-timeout": 3000,
  "raft-election-timeout": 6000,
  "leader-start-command": "mysql -e 'SET GLOBAL read_only=OFF; SET GLOBAL super_read_only=OFF;'",
  "leader-stop-command": "mysql -e 'SET GLOBAL read_only=ON; SET GLOBAL super_read_only=ON;'",
  "admit-defeat-hearbeat-count": 5
}

分区恢复后的处理:

  1. 网络恢复后,分区节点重新收到 Raft 心跳。
  2. 旧 Leader 发现 Raft Term 落后,退回 Follower 状态。
  3. Xenon 自动 CHANGE MASTER TO 指向新 Leader。
  4. 如果旧 Leader 在分区期间产生了未同步的写入(发生在脑裂未完全防护的场景),Xenon 根据 GTID 差异检测并触发告警——这部分数据无法恢复,需人工介入评估。
26 RadonDB 的跨可用区部署如何规划?

答案:

RadonDB 利用 Kubernetes 节点亲和性和拓扑分布约束,实现 MySQL 集群跨可用区(AZ)部署,抵御单 AZ 故障。

跨 AZ 部署架构(3 AZ 示例):

graph TD
    subgraph AZ1["AZ-1 (us-east-1a)"]
        subgraph NodeA["Node-A"]
            Pod0["my-cluster-0<br/>MySQL<br/>Xenon<br/>PVC (SSD)"]
        end
    end
    subgraph AZ2["AZ-2 (us-east-1b)"]
        subgraph NodeB["Node-B"]
            Pod1["my-cluster-1<br/>MySQL<br/>Xenon<br/>PVC (SSD)"]
        end
    end
    subgraph AZ3["AZ-3 (us-east-1c)"]
        subgraph NodeC["Node-C"]
            Pod2["my-cluster-2<br/>MySQL<br/>Xenon<br/>PVC (SSD)"]
        end
    end

    Pod0 <-->|"Raft Heartbeat (跨 AZ)"| Pod1
    Pod1 <-->|"Raft Heartbeat (跨 AZ)"| Pod2
    Pod0 <-->|"Raft Heartbeat (跨 AZ)"| Pod2
```text

跨 AZ 关键配置:

spec: replicas: 3 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app: mysql cluster: my-cluster topologyKey: topology.kubernetes.io/zone # 跨 AZ 分布


存储层跨 AZ 方案:

| 方案 | 说明 | 优缺点 |
|------|------|------|
| 云厂商跨 AZ 云盘 | 每个 AZ 独立 PV | 性能最优,依赖云平台 |
| Rook Ceph 跨 AZ 集群 | OSD 分布在多个 AZ,副本数>=3 | 统一存储层,跨 AZ 延迟增加 |
| 每个 AZ 独立 Local PV | 无共享存储 | 性能最高,无跨 AZ 存储依赖 |

跨 AZ 复制延迟考量:

| 场景 | 机房间延迟 | 复制模式 | 对写入事务的影响 |
|------|------|------|------|
| 同 AZ | <0.5ms | 半同步 | 几乎无额外延迟 |
| 跨 AZ(同 Region) | 1-3ms | 半同步 | 每个事务增加 1-3ms(等一确认) |
| 跨 Region | 30-100ms | **异步** | 无延迟影响,但故障时可能丢失数据 |

Raft 选举跨 AZ 影响:跨 AZ 部署时 Raft 心跳延迟略有增加,将 `raft-timeout` 从默认3000ms 调整为5000ms 可避免因跨 AZ 网络抖动导致的误触发选举。

// 跨 AZ 部署 Xenon 建议配置 { “raft-timeout”: 5000, “raft-election-timeout”: 10000, “raft-heartbeat-interval”: 250 }

27 RadonDB 的性能优化参数有哪些?

答案:

RadonDB 基于 MySQL InnoDB 存储引擎的性能优化参数覆盖缓冲池、日志、并发控制、查询优化等多个维度。

InnoDB 核心参数:

参数推荐值(生产环境)说明
innodb_buffer_pool_size物理内存的 60-70%缓冲池,缓存数据和索引
innodb_buffer_pool_instances8(buffer_pool_size >= 8G 时)减少缓冲池竞争
innodb_log_file_size2GRedo Log 大小,大值减少 checkpoint 频率
innodb_log_buffer_size256MRedo Log 缓冲,减少磁盘 IO
innodb_flush_log_at_trx_commit1每次事务刷盘(安全),可设为 2 提升性能但丢失 1s 数据
innodb_flush_methodO_DIRECT绕过 OS 页缓存,避免双重缓存
innodb_io_capacitySSD:2000-4000,HDD:200后台 IO 速率,影响刷脏页速度
innodb_io_capacity_maxSSD:8000-12000脏页比例高时的最大 IO 速率
innodb_read_io_threads8预读线程
innodb_write_io_threads8刷脏页线程
innodb_page_cleaners8脏页清理线程
innodb_purge_threads4Undo Log 清理线程
innodb_adaptive_hash_indexON自适应哈希索引,加速热点数据查找

连接与线程:

参数推荐值说明
max_connections500-2000最大连接数,取决于应用并发量
thread_cache_size100-200线程缓存,避免频繁创建销毁
table_open_cache4000表缓存
table_definition_cache2000表定义缓存
back_log500TCP 连接队列大小

Binlog 与复制:

参数推荐值说明
sync_binlog1(安全)每次事务同步 binlog 到磁盘
binlog_cache_size64K-1Mbinlog 事务缓存
binlog_group_commit_sync_delay0Group Commit 延迟(微秒),0=不延迟
slave_parallel_workers4-8并行复制 worker 线程数
slave_parallel_typeLOGICAL_CLOCK基于逻辑时钟的并行复制

查询优化:

参数推荐值说明
tmp_table_size128M内存临时表最大大小
max_heap_table_size128MMEMORY 表最大大小
sort_buffer_size4M-16M排序缓冲区
join_buffer_size4M-16MJOIN 缓冲区
read_buffer_size2M顺序扫描缓冲区
read_rnd_buffer_size4M随机读缓冲区
eq_range_index_dive_limit200等值范围索引下探限制

生产环境 InnoDB 配置推荐:

[mysqld]
# InnoDB 核心
innodb_buffer_pool_size = 16G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 2G
innodb_log_buffer_size = 256M
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_read_io_threads = 8
innodb_write_io_threads = 8
innodb_page_cleaners = 8

# 连接
max_connections = 1000
thread_cache_size = 200
table_open_cache = 4000

# Binlog
binlog_format = ROW
sync_binlog = 1
binlog_cache_size = 1M

# 复制
slave_parallel_workers = 8
slave_parallel_type = LOGICAL_CLOCK
28 RadonDB 的故障排查流程是什么?

答案:

RadonDB 故障排查遵循分层定位原则,从顶层集群状态到底层日志逐级排查。

排查层级与工具:

层级检查内容命令
集群层CRD Status、Pod 状态、事件kubectl describe mysqlcluster / kubectl get events
Pod 层容器状态、探活、资源kubectl describe pod / kubectl top pod
Xenon 层Raft 状态、集群成员、Leader 身份xenoncli cluster raft / xenoncli mysql status
MySQL 层连接、复制、锁、慢查询SHOW PROCESSLIST / SHOW SLAVE STATUS / SHOW ENGINE INNODB STATUS
系统层CPU / Memory / Disk IO / 网络top / iostat / ping / dstat

常见故障排查:

场景 1:集群 Pod 不 Ready

排查步骤:
1. kubectl describe pod my-cluster-0 → 查看 Events
2. kubectl logs my-cluster-0 -c init → Init Container 日志
3. kubectl logs my-cluster-0 -c mysql → MySQL 启动日志
4. kubectl logs my-cluster-0 -c xenon → Xenon 启动日志

常见原因:
- Init Container 数据目录校验失败 → PVC 损坏或目录为空
- MySQL 挂载卷权限问题 → fsGroup / runAsUser 未正确设置
- Xenon 无法连接 MySQL → /var/run/mysqld/mysqld.sock 不存在
- 磁盘空间不足 → PV 配额耗尽
```text

**场景 2:主从复制中断**

– 第 1 步:检查从库复制状态 SHOW SLAVE STATUS\G

– 关键字段: – Slave_IO_Running / Slave_SQL_Running: 应为 Yes – Seconds_Behind_Master: 延迟秒数 – Last_IO_Error / Last_SQL_Error: 错误信息

– 常见错误及修复: – Error 1236 (binlog 被清理 / GTID 不一致) STOP SLAVE; RESET SLAVE; CHANGE MASTER TO …; START SLAVE;

– Error 1062 (主键冲突 / 重复数据) STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;

– Error 1032 (记录不存在 / DELETE/UPDATE 时找不到行) STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;


**场景 3:Raft 集群分裂**

查看 Raft 状态

kubectl exec -it my-cluster-0 -c xenon – xenoncli cluster raft

手动重建 Raft 集群

kubectl exec -it my-cluster-0 -c xenon – xenoncli cluster add –address my-cluster-1:8801 kubectl exec -it my-cluster-0 -c xenon – xenoncli cluster add –address my-cluster-2:8801

Xenon 日志排查

kubectl logs my-cluster-0 -c xenon | grep -E “raft|leader|election|timeout”


**场景 4:备份失败**

查看 Backup Job 状态

kubectl get mysqlbackup kubectl describe mysqlbackup my-cluster-backup-xxx

查看 Job Pod 日志

kubectl logs job/my-cluster-backup-xxx

常见原因:

- S3/MinIO 认证失败 → Secret 中的 AK/SK 错误

- 磁盘空间不足 → 备份路径空间不足

- MySQL 连接失败 → Xenon 未处于正常状态

- 备份进程超时 → 数据集过大,xtrabackup 超时


**场景 5:性能下降**

– 查看当前活跃查询 SHOW FULL PROCESSLIST;

– 查看 InnoDB 引擎状态(锁争用 / 事务状态) SHOW ENGINE INNODB STATUS\G

– 查看当前锁等待 SELECT * FROM information_schema.innodb_lock_waits; SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA = ‘mydb’;

– 查看慢查询 SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 20;

– 查看表统计信息 SELECT TABLE_NAME, TABLE_ROWS, DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA = ‘mydb’;

29 RadonDB 的 CLI 工具(radondb-mysql-operator 命令行)如何使用?

答案:

RadonDB Operator 提供 radondb-mysql-operator 命令行工具和 kubectl 插件,用于集群管理、状态查看和运维操作。

核心 CLI 命令:

# 查看 Operator 版本
radondb-mysql-operator version

# 查看集群列表
kubectl get mysqlcluster

# 查看集群详细状态
kubectl describe mysqlcluster my-cluster

# 创建集群
kubectl apply -f mysql-cluster.yaml

# 手动触发备份
kubectl apply -f - <<EOF
apiVersion: mysql.radondb.com/v1beta1
kind: MysqlBackup
metadata:
  name: my-cluster-manual-backup-$(date +%Y%m%d%H%M%S)
spec:
  clusterName: my-cluster
  type: full
EOF

# 从备份恢复
kubectl apply -f mysql-restore.yaml

# 查看备份列表
kubectl get mysqlbackup

# 删除集群(保留 PVC)
kubectl delete mysqlcluster my-cluster
```text

Xenon CLI(`xenoncli`):

进入 Xenon 容器

kubectl exec -it my-cluster-0 -c xenon – /bin/bash

查看 Raft 集群状态

xenoncli cluster raft

查看 Raft 成员

xenoncli cluster members

查看当前节点 MySQL 状态(角色、复制、GTID)

xenoncli mysql status

查看当前节点为 Leader 还是 Follower

xenoncli mysql role

手动触发 Leader 转移

xenoncli raft transfer

查看 Xenon 日志级别

xenoncli log level


MySQL 运维命令:

通过 kubectl 直接进入 MySQL

kubectl exec -it my-cluster-0 – mysql -uroot -p"${MYSQL_ROOT_PASSWORD}"

查看主从复制状态

kubectl exec -it my-cluster-1 – mysql -e “SHOW SLAVE STATUS\G”

查看当前 Leader

kubectl get pods -l app=mysql,cluster=my-cluster,role=leader

查看所有可用的只读副本

kubectl get pods -l app=mysql,cluster=my-cluster,role=follower

临时重启 Xenon(不影响 MySQL)

kubectl exec -it my-cluster-0 -c xenon – kill -HUP 1


Operator 日志查看:

查看 Operator 日志

kubectl logs -f deployment/radondb-mysql-operator -n radondb-system

按关键字过滤

kubectl logs deployment/radondb-mysql-operator -n radondb-system | grep -i “reconcile|error|leader”

30 RadonDB 生产环境最佳实践有哪些?

答案:

RadonDB 生产环境部署需覆盖部署架构、资源规划、安全加固、备份策略、监控告警、升级运维六大领域。

部署架构

实践说明
最少 3 副本满足 Raft Quorum(多数派投票 + 半同步 ACK)
跨可用区部署抵御单 AZ 故障,拓扑 Key 使用 topology.kubernetes.io/zone
PodAntiAffinity 强制分散避免多个副本落在同一 Node
单独命名空间radondb-prod,区分环境
Operator 高可用Operator Deployment replicas >= 2,避免 Operator 单点

资源规划

资源推荐值说明
内存 Request = Limit如 16Gi = 16GiQoS 为 Guaranteed,避免 OOM 驱逐
CPU Request < LimitRequest 4核 / Limit 8核允许 Burst,收益可控
innodb_buffer_pool_size内存 Limit × 60-70%避免 OOM
PV 大小磁盘 × 1.5-2 倍预估预留增长空间
PV StorageClassallowVolumeExpansion: true支持在线扩容
资源隔离使用不同 Node Pool数据库与其他负载避免混部

安全加固

  • TLS 加密传输:require_secure_transport=ON
  • 密码策略:启用 validate_password 插件,最小长度 12 位
  • 废弃匿名用户和 test 数据库
  • 网络隔离:NetworkPolicy 仅允许业务 Pod CIDR 访问 3306 端口
  • Secret 管理:密码存储于 Kubernetes Secret,不在 CRD Spec 中明文
  • 定期审计:至少每季度执行安全基线扫描
  • RBAC:Operator 使用最小权限 ServiceAccount

备份策略

数据等级备份策略保留期异地副本
P0(核心)每日全量 + 每 6 小时增量30 天有(跨 Region S3 复制)
P1(重要)每日全量 + 每日增量14 天
P2(一般)每日全量7 天
P3(非关键)每周全量4 周
  • 备份验证:每月至少一次恢复演练,验证备份可用性和恢复时间
  • 备份加密:S3 端开启 SSE(Server-Side Encryption)
  • 备份监控:备份作业失败告警,延迟超过窗口告警

监控告警

告警阈值通知级别
MySQL 不可用mysql_up == 0 for 1minCritical,立即处理
复制中断Slave_IO/SQL_Running == No for 1minCritical,立即处理
复制延迟Seconds_Behind_Master > 30s for 5minWarning,15min 内处理
磁盘使用使用率 > 80%Warning,4h 内处理
连接使用率Threads_connected / max_connections > 80% for 5minWarning,30min 内处理
缓冲池命中率Hit Rate < 95% for 10minInfo,工作时间处理
慢查询Slow_queries > 10/s for 10minInfo,工作时间处理

升级运维

  • 升级窗口:选择业务低峰期(如每周四凌晨 2:00-4:00)
  • 升级验证:先在 staging 环境验证整个升级流程,确认无误后操作生产
  • 灰度策略:先升级一个 Follower,观察复制延迟和业务性能,确认正常后逐级升级
  • 回滚方案:保留旧版本镜像和备份,确认回滚路径可行
  • PDB 配置:minAvailable: ceil(replicas/2)+1,确保滚动升级期间 Raft 多数派存活
  • 变更管理:每次变更记录 CRD 变更前后的 YAML 快照

容量管理

指标检查频率扩容触发条件
磁盘使用率每周连续 2 周超过 70%
CPU 使用率每周连续 2 周峰值超过 70%
内存使用率每周连续 2 周超过 80%
连接数每周连续 2 周峰值超过 70%

附录:快速检查清单

# 集群健康检查
kubectl get mysqlcluster                              # CRD 状态 Ready
kubectl get pods -l cluster=my-cluster                # 所有 Pod Running
kubectl exec -it my-cluster-0 -c xenon -- xenoncli cluster raft  # Raft 正常
kubectl exec -it my-cluster-1 -- mysql -e "SHOW SLAVE STATUS\G"   # 复制正常

# 备份检查
kubectl get mysqlbackup                               # 最近备份 Completed
# 验证备份文件存在于 S3/MinIO

# 资源检查
kubectl top pods                                      # CPU/Memory 未达上限
kubectl get pvc                                       # PV 空间充足
```text