04 存储与数据库运维

0 阅读12分钟

面试官关注点:MySQL/Redis 原理题是基础,真正有含金量的是 大表 DDL、主从延迟、缓存穿透击穿雪崩、备份恢复演练 的实战经验。


一、存储产品全景

1.1 块存储(ESSD)关键认知

  • 性能和容量绑定(详见 01 文档),PL1~PL3 为主流
  • ESSD AutoPL:解耦容量和性能,IOPS/带宽独立付费
  • 多重挂载:同一云盘挂给多个 ECS(配合集群文件系统或 Oracle RAC)
  • 快照:增量、异步、不影响业务;快照成本 = 增量数据 × 存储单价
  • 加密盘:基于 KMS,符合等保/合规要求

1.2 快照策略

  • 自动快照策略:生产盘每天 1 次 + 保留 7 天
  • 应用一致性快照:打快照前冻结文件系统 fsfreeze 或应用层 flush
  • 快照跨 Region 复制:DR 场景
  • 快照恢复:快照 → 新盘 → 挂载(原盘回滚也可,但会覆盖现有数据)

1.3 对象存储 OSS

  • 强一致性:写入后立即可读(PUT-after-PUT、PUT-after-DELETE 都一致)
  • 版本控制:防误删,必须开启
  • 跨区域复制(CRR):异步复制到另一 Region
  • 回源:Bucket 可配置回源规则(回源到自建或另一 Bucket)
  • 防盗链:Referer 白名单、签名 URL(临时访问)
  • 服务端加密:OSS 托管密钥 / KMS 密钥 / 客户自带密钥
  • 传输加速:全球加速域名,海外上传提速
  • 性能:单 Bucket 无限容量,但前缀分区 TPS 有限(建议 key 散列)

1.4 文件存储 NAS

  • 通用型 NAS:NFSv3/v4、SMB,容量/性能型
  • 极速型 NAS:基于全 SSD,微秒级延迟,小文件密集
  • CPFS:并行文件系统,GB/s 级带宽,AI/HPC
  • 实战:K8s PV 用 NAS CSI 驱动,ReadWriteMany 首选

二、MySQL 生产运维

2.1 版本与分支选择

版本特性建议
MySQL 5.7成熟稳定存量维护,新项目勿用(官方 EOL 已至)
MySQL 8.0默认字符集 utf8mb4、CTE、窗口函数、原子 DDL、InnoDB 增强新项目首选
PolarDB MySQL存算分离,一写多读中大型业务
AnalyticDB MySQLOLAP分析型

2.2 关键参数(生产模板)

# innodb_buffer_pool_size: 物理内存 50-70%(独占 MySQL 的机器)
innodb_buffer_pool_size = 32G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 2G          # 5.7 redo 大小(8.0 自动管理)
innodb_flush_log_at_trx_commit = 1 # 严格 ACID,牺牲一点性能换持久性
sync_binlog = 1                    # 同步刷 binlog,双 1 配置
innodb_flush_method = O_DIRECT
innodb_io_capacity = 20000         # SSD,NVMe 可调更高
innodb_io_capacity_max = 40000
innodb_read_io_threads = 8
innodb_write_io_threads = 8

max_connections = 3000             # 按业务评估
max_connect_errors = 100000
wait_timeout = 600
interactive_timeout = 600

# 慢查询
slow_query_log = 1
long_query_time = 0.5
log_queries_not_using_indexes = 1

# binlog
binlog_format = ROW                # 推荐 ROW,主从一致性好
binlog_row_image = MINIMAL         # 减少 binlog 体积
expire_logs_days = 7

# 字符集
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci

2.3 主从复制原理

主库 binlog → dump 线程 → 从库 IO 线程(写 relay log) → SQL 线程(回放)
  • 异步复制:默认,主库不等从库确认
  • 半同步:至少一个从库收到 relay log 才返回(rpl_semi_sync_master_enabled=ON
  • 组复制 MGR:多主或单主,基于 Paxos 强一致
  • PolarDB 物理复制:共享存储,读节点秒级加入

2.4 主从延迟排查

现象Seconds_Behind_Master 持续上升

常见原因

  1. 大事务:一个事务几 GB,从库串行回放耗时
  2. DDL:大表 alter,从库阻塞
  3. 从库硬件差:CPU/磁盘弱于主库
  4. 单线程回放:5.6 以前 SQL 线程单线程(5.7+ 支持并行回放 slave_parallel_workers
  5. 从库被业务查询占用
  6. 网络延迟

诊断命令

SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 延迟秒数
-- Retrieved_Gtid_Set vs Executed_Gtid_Set
-- Last_SQL_Error / Last_IO_Error

-- 查看正在回放的事件
SELECT * FROM performance_schema.replication_applier_status_by_worker;

并行复制调优(5.7+)

slave_parallel_type = LOGICAL_CLOCK   # 基于组提交的并行
slave_parallel_workers = 16
slave_preserve_commit_order = 1
binlog_transaction_dependency_tracking = WRITESET  # 更细粒度并行

2.5 慢查询优化链路

发现 → 定位 → 分析 → 优化 → 验证

发现:慢查询日志、pt-query-digest、DMS/DAS

定位

EXPLAIN SELECT ...;     -- 看执行计划
EXPLAIN ANALYZE ...;    -- 8.0+ 实际执行耗时
SHOW PROFILE FOR QUERY <id>;

关键看点

  • typeALL(全表)→ indexrangerefconst
  • rows:扫描行数(越少越好)
  • ExtraUsing filesort(文件排序,需优化)、Using temporary(临时表)、Using index(覆盖索引,好)

优化手段

  1. 加索引:高选择度列优先,组合索引遵循最左前缀
  2. 覆盖索引:查询列全部在索引里
  3. 避免回表:主键查询或覆盖索引
  4. 改写 SQL:避免 !=OR、函数包裹列、隐式类型转换
  5. 分页优化LIMIT 100000, 20WHERE id > last_id LIMIT 20
  6. 大表 JOIN:确保 join 列有索引、小表驱动大表(MySQL 自动选)
  7. 拆分:分库分表、冷热分离、归档

2.6 大表 DDL 方案

问题ALTER TABLE 阻塞业务、binlog 暴增、从库延迟严重

方案对比

方案原理优势局限
Online DDL5.6+ 支持,INPLACE 不锁表简单加索引/加列可以,部分操作仍拷贝表
pt-online-schema-change影子表 + 触发器 + 增量拷贝兼容性好触发器有性能开销
gh-ost基于 binlog,无触发器对主库压力小需要 binlog row 格式
DMS 无锁结构变更阿里云 DMS 产品功能傻瓜式依赖阿里云

生产建议

  • 表 < 1GB:直接 Online DDL
  • 表 > 1GB 或业务敏感:gh-ost
  • DBA 团队熟悉 PT:pt-osc

2.7 死锁排查

SHOW ENGINE INNODB STATUS\G
-- LATEST DETECTED DEADLOCK 段

-- 持续监控
SET GLOBAL innodb_print_all_deadlocks = ON;

-- 当前锁
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;

典型死锁

  • 两事务以不同顺序更新同两行
  • 间隙锁(Gap Lock)冲突(RR 隔离级下常见)
  • 批量更新未排序

解决:业务统一按主键 ID 排序再更新;降级到 RC 隔离级减少间隙锁。

2.8 备份与恢复

  • 物理备份:Xtrabackup(全量 + 增量),恢复快,生产首选
  • 逻辑备份mysqldump / mydumper,跨版本兼容,恢复慢
  • 阿里云 RDS 备份:自动每日全量 + 秒级 binlog,任意时间点恢复(PITR)
  • 演练原则没演练过的备份等于没备份,每季度全流程恢复一次

2.9 DAS / DMS / HDM

  • DAS(数据库自治服务):阿里云 DB AI 诊断平台,自动发现慢查、索引建议、异常根因
  • DMS(数据管理):跨云/跨 DB 统一入口、权限审批、审计、数据分发、无锁 DDL
  • HDM / DTS:数据传输服务,用于迁移、双向同步、订阅 binlog
  • 面试加分项:说"我们用 DAS 自动识别 TopSQL 并接入告警",比说"我手写 pt-query-digest 脚本"更有说服力

三、Redis 生产运维

3.1 部署模式对比

模式说明场景
主从(master-replica)简单读写分离小规模
哨兵(Sentinel)自动故障转移中等规模
Cluster分片 + 高可用大规模 / 高吞吐
阿里云 Redis 标准版内置哨兵通用
阿里云 Redis 集群版代理 + 分片大容量
阿里云 Redis 读写分离版1 主 + 多读读多写少
Tair(增强版)性能/容量/持久型阿里自研

3.2 内存管理

内存淘汰策略maxmemory-policy):

  • noeviction:内存满拒绝写入(默认,危险
  • allkeys-lru:全局 LRU,推荐缓存场景
  • allkeys-lfu:LFU,访问频次,4.0+
  • volatile-lru:只淘汰有 TTL 的 key
  • volatile-ttl:优先淘汰 TTL 短的

内存碎片

  • mem_fragmentation_ratio > 1.5 碎片率高
  • 激活内存碎片整理:CONFIG SET activedefrag yes

3.3 持久化

  • RDB:内存快照,恢复快,可能丢数据
  • AOF:追加日志,appendfsync everysec(推荐)
  • 混合持久化 4.0+:RDB + 增量 AOF,兼顾速度与数据安全
  • 生产建议缓存场景关持久化数据存储场景开混合持久化

3.4 缓存三大经典问题

缓存穿透(查不存在的 key):

  • 布隆过滤器前置
  • 空值缓存(缓存 null,短 TTL)
  • 接口层限流

缓存击穿(热点 key 过期):

  • 互斥锁(只放一个请求回源)
  • 逻辑过期:不设 TTL,后台异步刷新
  • 永不过期热点:人工维护

缓存雪崩(大量 key 同时过期或 Redis 挂):

  • TTL 加随机抖动(基础值 + rand)
  • 多级缓存(本地 Caffeine + Redis)
  • 限流降级

3.5 大 key / 热 key 排查

# 阿里云 Redis 控制台有内置分析
# 自建可用
redis-cli --bigkeys
redis-cli --hotkeys          # 4.0+
redis-cli -n 0 --memkeys

# MEMORY USAGE key
MEMORY USAGE bigkey

大 key 危害:阻塞主线程(单线程模型)、迁移失败、集群分片不均 处理:拆分(hash 分桶)、异步 UNLINK(替代 DEL

热 key 危害:单分片打爆 处理:本地缓存、读写分离节点、key 打散(加随机后缀 + 广播写)

3.6 阻塞命令清单(禁用!)

  • KEYS *:全扫描 → 用 SCAN
  • FLUSHALL:清库 → ACL 禁用
  • SUNIONSINTER 大集合:慢查询
  • DEL 大 key:用 UNLINK
  • LRANGE list 0 -1 大 list:分批取

生产必做rename-command 把危险命令改名或禁用,ACL(6.0+)精细权限。


四、其他数据库产品

4.1 MongoDB

  • 副本集(Replica Set):3 节点起,自动选主
  • 分片(Sharded Cluster):config server + mongos + shard
  • 热点问题:shard key 选择不当 → 单片热
  • 事务支持:4.0+ 副本集事务,4.2+ 分片事务
  • 阿里云有托管 MongoDB,版本跟进较快

4.2 Lindorm(HBase 增强)

  • 宽表 + 时序 + 搜索 + 文件一体化
  • 兼容 HBase/Cassandra/OpenTSDB/Solr
  • 适合海量 IoT、日志、监控指标

4.3 Tablestore(表格存储 OTS)

  • Serverless 结构化大数据
  • 按量付费,自动扩展
  • 二级索引 + 多元索引(全文/地理位置)

4.4 ADB(分析型数据库)

  • MySQL/PostgreSQL 协议,OLAP
  • 列存、向量化执行
  • 与 DataWorks / MaxCompute 整合

五、数据迁移与同步

5.1 DTS(数据传输服务)

  • 迁移:自建 → 云、云 → 云、跨 Region
  • 同步:双向、多级联
  • 订阅:binlog/redo 订阅给下游(Kafka、Flink)
  • 校验:结构/数据/增量一致性校验

5.2 迁移方案选型

场景方案
MySQL 上云DTS 全量 + 增量,业务低峰切流
Oracle → PolarDB-ODTS + ADAM 评估改造
停机窗口可接受mysqldump / xtrabackup + 停机切换
几十 TB 海量数据数据闪电立方(物理运输)+ 增量追平

5.3 数据一致性校验

  • 行数比对SELECT COUNT(*)(粗略)
  • CheckSum:每行哈希比对(精确,慢)
  • DTS 一致性校验:托管方案
  • 抽样比对:生产常用折中

六、容量规划

6.1 MySQL 容量评估

  • 单表 > 500 万行 / > 5GB:考虑分表
  • 单实例 > 2TB:考虑分库或 PolarDB
  • QPS > 2 万:读写分离或分片
  • 连接数 > 5000:上 ProxySQL / DBProxy

6.2 Redis 容量评估

  • 内存 < 32GB/实例:超过影响 fork 和主从同步
  • QPS < 10 万/节点:超过考虑集群分片
  • 网络带宽:单节点 1Gbps 约 10 万 QPS 小 key

七、面试高频问答

Q1:MySQL 为什么用 B+ 树不用 B 树、哈希、红黑树? A:

  • B+ 树:非叶子节点只存 key,叶子节点存完整数据并双向链表相连,范围查询高效,磁盘 IO 次数少(树高低)
  • B 树:每个节点都存数据,范围查询要回溯
  • 哈希:等值快但无序,不支持范围
  • 红黑树:树高太高(二叉),磁盘 IO 次数多

Q2:InnoDB 的隔离级别、MVCC、间隙锁? A:

  • 默认 RR(可重复读),通过 MVCC + 间隙锁防止幻读
  • MVCC:每行有 trx_id + roll_ptr,基于 ReadView 判断可见性
  • 间隙锁:锁住索引范围之间的"间隙",防止新数据插入
  • RC(读已提交)不加间隙锁,高并发场景可选

Q3:redo log 和 binlog 的区别?两阶段提交? A:

  • redo log:InnoDB 引擎层,物理日志(数据页改动),循环写,崩溃恢复
  • binlog:Server 层,逻辑日志,追加写,主从复制和恢复
  • 两阶段提交:redo prepare → binlog write → redo commit,保证两个日志一致性(崩溃后通过 XID 协调)

Q4:Redis 为什么快? A:

  1. 内存操作
  2. 单线程(避免锁竞争,6.0 网络 IO 多线程但命令处理仍单线程)
  3. IO 多路复用(epoll)
  4. 高效数据结构(SDS、ziplist/listpack、quicklist、跳表)
  5. 零拷贝、pipeline

Q5:Redis 分布式锁怎么做? A:

  • SET key value NX EX 30:基础版
  • 要求:唯一标识(UUID)避免误删Lua 脚本原子释放续期(看门狗)
  • 高可靠:Redlock(多数节点加锁),但有争议(脑裂场景)
  • 生产推荐:Redisson(封装好看门狗、可重入),或 ZK/Etcd 做强一致锁

Q6:如何排查线上慢 SQL? A:标准流程:

  1. DAS / 慢查询日志定位 TopSQL
  2. EXPLAIN 看执行计划
  3. 检查索引、扫描行数、排序
  4. 改 SQL 或加索引(灰度验证)
  5. 验证:QPS、P99 延迟、系统负载
  6. 如果是突发慢:看是否有锁、大事务、统计信息过期、执行计划变更

Q7:主从延迟怎么处理? A:

  • 短期:业务读写分离层识别延迟大的从库并切走、强一致读走主库
  • 中期:开启并行复制、优化大事务(拆小)、升级从库硬件
  • 长期:上 PolarDB(共享存储,秒级同步)或 MGR

Q8:线上 Redis 内存快满了怎么办? A:

  1. 立即扩容(云上分钟级)
  2. 排查大 key--bigkeys / 内存分析
  3. 调整淘汰策略allkeys-lru
  4. 清理业务无用 key:按前缀 SCAN 删除
  5. 迁移冷数据:下沉到 MySQL / OSS
  6. 长期:拆业务、加分片、上 Tair 容量型(持久内存更便宜)

Q9:一次 MySQL update 语句的完整流程? A:

客户端 → 连接器(鉴权、会话)→ 查询缓存(8.0 移除)→ 分析器(词法/语法)
→ 优化器(选索引、join 顺序)→ 执行器
→ InnoDB:读页到 buffer pool → 写 undo log → 更新内存页(脏页)
→ 写 redo log(prepare)→ 写 binlog → redo commit
→ 后台刷脏页

Q10:为什么阿里内部推 PolarDB? A:

  • 存算分离:计算节点弹性伸缩,存储自动扩容
  • 物理复制:读节点秒级加入,延迟微秒级
  • 成本:相比 RDS 高规格 + 多副本更便宜
  • HTAP:列存索引支持 OLAP
  • 100% 兼容 MySQL,迁移无痛

八、生产 DB 巡检清单

  • 备份是否每日成功,是否有最近一次成功的恢复演练
  • 主从延迟告警(>10s)
  • 慢查询数量趋势(周环比)
  • 磁盘使用率 < 80%,增长率预测
  • 连接数 < 最大值 80%
  • Redis 内存使用率 < 75%(为 BGSAVE fork 留空间)
  • 大 key/热 key 日报
  • DDL 变更走无锁方案
  • 账号权限最小化,DBA 走堡垒机审计
  • 核心库版本在官方支持期内