摘要
本文整理中间件方向的系统运维面试题共 75 道,覆盖 19 个组件:Redis / MySQL / Kafka / RabbitMQ / RocketMQ / Nginx / Elasticsearch / ZooKeeper / Nacos / Seata / MongoDB / PostgreSQL / ClickHouse / 时序数据库 / XXL-Job / 负载均衡 / Tomcat / 对象存储 / EMQX。每题给出答题要点,适合面试前速查,建议收藏。
Redis(12 题)
1. 缓存穿透、击穿、雪崩分别是什么?怎么解决?
- 穿透:查一个不存在的 key,请求直穿 DB。解决:布隆过滤器、缓存空值。
- 击穿:一个热点 key 过期瞬间,大量请求打到 DB。解决:互斥锁重建缓存、逻辑过期。
- 雪崩:大量 key 同时过期或 Redis 挂了,DB 被打垮。解决:过期时间加随机值、多级缓存、限流降级、Redis 高…
- 加分:能讲清"布隆过滤器能挡穿透但挡不了击穿"的区别。
2. Redis 变慢了,你会怎么排查?
- redis-cli –latency 先确认是不是 Redis 本身慢
- SLOWLOG GET 看慢命令:大 key、KEYS/SMEMBERS 全量操作
- 查 big key:大 key 导致阻塞式删除、迁移、读放大
- 客户端侧:频繁重连、连接池耗尽、超时配置不合理
- 系统层:AOF 刷盘策略、fork 阻塞(大实例 BGSAVE)、内存碎片、swap
3. Redis 的 RDB 和 AOF 两种持久化有什么区别?怎么选?
- RDB:全量快照文件,恢复快、文件小,但两次快照之间的数据可能丢。
- AOF:记录写命令日志,数据丢失少(取决于 appendfsync),但文件大、恢复慢;
- 主流组合:RDB 做冷备 + AOF 做数据恢复兜底,或 4.0+ 混合持久化。
- 选型:能接受丢失几分钟→RDB;几乎不能丢→AOF(建议 everysec);追求简单→混合。
4. Redis 内存淘汰策略有哪些?生产上你怎么配?
- noeviction:内存满直接报错不写(默认)
- allkeys-lru:全体按 LRU 淘汰最久未用
- volatile-lru:只在设了过期时间的 key 里 LRU
- allkeys-lfu / volatile-lfu:按访问频率(4.0+)
- allkeys-random / volatile-random:随机淘汰
5. 如何用 Redis 实现分布式锁?有哪些坑?
- 基础版:SET key value NX EX 10 原子加锁;解锁用 Lua 脚本比对 value 再 DEL,防止误删…
- 锁过期而业务没跑完:加续期机制(看门狗)或锁内不做过长操作
- 主从切换丢锁:严格场景考虑 RedLock 或 etcd/zk
- value 必须唯一(线程标识),否则释放锁可能误删
- 重入:需要重入计数或改用 Redisson 的实现
- 加分:能主动说出"Redis 锁不是银弹,一致性要求极高时考虑 etcd"。
6. 什么是热 key 和 big key?分别怎么治理?
- 热 key:单位时间被超高并发访问的 key。治理:本地缓存 + 多级缓存、热点 key 打散加后缀分片、读写分离副本分摊。
- big key:单个 key 的 value 过大(大 string、大 hash/set/list)。
- 检测:redis-cli –bigkeys、memory usage、慢日志交叉分析。
7. Redis 哨兵(Sentinel)和 Cluster 分别解决什么问题?
- Sentinel:管理主从架构,监控主节点,挂了自动故障转移(选新主、改从、通知客户端)。
- Cluster:数据分片到多节点(16384 槽位),横向扩展容量与吞吐;每个分片可配副本做高可用。解决"容量与扩展性"。
- 选型:单机内存够、要省事→主从+哨兵;数据量大/写量大→Cluster(客户端要支持 cluster 协议,跨槽位操作有限…
8. Redis 主从切换时为什么可能丢数据?脑裂是什么?
- 主从切换丢数据的原因:
- 异步复制:主库把命令发给从库就返回成功,切换瞬间没同步完的命令就丢了
- 脑裂:主库网络抖动被判定下线,但从库还活着,客户端短暂写入"假主"(旧主),切回时旧主数据被丢弃
- min-replicas-to-write + min-replicas-lag:从库少于 N 个/落后太多时拒绝写入,宁…
- 业务侧容忍少量丢失/幂等补偿
- 加分:能说"Redis 默认是 AP 系统,强一致要用红锁/其他组件"。
9. 缓存和数据库的一致性怎么保证?延迟双删靠谱吗?
- 方案与取舍:
- 先更库再删缓存(主流):删失败概率比写库后更缓存小,配合延迟队列兜底重删
- 延迟双删:先删缓存→更库→延迟再删,减少窗口期不一致,但延迟多久难定,治标不治本
- binlog 订阅(推荐做补偿):监听 binlog 异步删缓存/更新,兜底一切漏删
- 认知:缓存一致性没有银弹,关键是:
- 加分:主动承认"强一致应该读主库或干脆不用缓存,缓存是性能换最终一致"。
10. Redis 为什么那么快?单线程模型还能扛高并发?
- 纯内存操作:数据在内存,无磁盘 IO
- 单线程无锁:没有线程切换与锁竞争开销(6.0 后多线程只用于网络 IO)
- IO 多路复用:epoll 单线程同时管理海量连接,事件驱动
- 高效数据结构:底层 SDS/跳表等针对场景优化
- 单线程为什么扛得住:命令执行本身微秒级,瓶颈通常在网络与内存带宽,不在 CPU。
11. Redis 的过期键是怎么删除的?为什么要这样设计?
- 两种策略结合:
- 惰性删除:读的时候才检查,过期了就删——省 CPU,但过期键会一直占内存(没被读到就一直留着)
- 定期删除:周期性地抽样检查一部分过期键并删除——平衡 CPU 与内存,不阻塞主流程太久
- 内存角度:纯惰性会导致"写了很多很快过期的 key,内存一直不释放",所以要靠定期删除+内存淘汰兜底。
- 考点:过期键在主库删了,从库怎么知道?——主库删除后发 DEL 命令同步;所以从库读到"已过期但还没同步删除"的键,需要先…
12. Redis 主从第一次同步和增量同步分别是怎么做的?
- 全量同步(首次/断连太久):
- 从库发 PSYNC,主库生成 RDB 快照发给从库(期间新命令进复制积压缓冲区)
- 从库加载 RDB,再接收积压缓冲区增量命令
- 增量同步(短暂断连):
- 从库带上上次复制偏移量重新 PSYNC
MySQL(12 题)
13. MySQL 索引为什么用 B+ 树而不是红黑树或 Hash?
- B+树矮胖:非叶子节点只存键,扇出大,三层能支撑千万级数据,磁盘 IO 少
- 叶子节点有序链表:天然支持范围查询和排序
- Hash 索引:单点查询 O(1) 但无法范围查询、无法排序、有哈希冲突,只适合等值查询场景(如内存表)
- 红黑树:高度高,磁盘访问次数多
- 追问加分:能说出 InnoDB 聚簇索引叶子存整行、二级索引叶子存主键、回表的概念。
14. MySQL 的四种事务隔离级别是什么?默认是哪个?
- 读未提交(脏读)→ 读已提交(不可重复读)→ 可重复读(幻读)→ 串行化(性能最差)。
- MySQL/InnoDB 默认:可重复读(REPEATABLE READ)。
- InnoDB 靠 MVCC 快照读解决"不可重复读",靠间隙锁/临键锁基本解决"幻读"。
- 常见追问:RR 下 MVCC 快照的生成时机(事务内第一次 SELECT),以及为什么有些公司调到 RC(并发与日志解析考…
15. MySQL 连接数被打满,如何排查与解决?
- show processlist 看连接来源与状态:Sleep 多还是执行中多
- 慢查询日志:哪条 SQL 长期占用连接
- 应用侧:连接池 maximum-pool-size 是否偏大、连接是否泄漏未归还
- 治标:调 max_connections、优化慢 SQL、清理僵尸连接
- 治本:连接池总量 < 数据库上限留 20% 余量、SQL 走索引、热点上缓存
16. 有一条 SQL 特别慢,怎么定位和优化?
- 慢查询日志定位 SQL 与耗时基线
- EXPLAIN 看执行计划:type、key、rows、Extra
- 常见问题:没走索引(函数/隐式转换/前导通配符)、扫大行数、filesort/临时表、深分页
- 优化:联合索引(最左前缀)、覆盖索引、改写 SQL、深分页改游标、必要时归档拆表
- 加分:先查"是不是统计信息过期导致选错索引",再量化前后 rows 与耗时对比。
17. 主从复制延迟是怎么产生的?怎么监控和缓解?
- 主库大事务:一个事务的 binlog 一次性传/执行,慢
- 从库单线程应用(默认 SQL 线程串行),高并发主库时追不上
- 从库上有慢查询/大查询抢占 IO
- 网络带宽、binlog 格式(ROW 大事务量更大)
- 监控:SHOW SLAVE STATUS 的 Seconds_Behind_Master(注意它不准的边界条件)。
18. 分库分表后,查询、事务、自增主键怎么办?
- 查询:单分片键查询路由到对应库表;跨片查询走中间件聚合(sharding-jdbc/mycat),避免全表扫
- 事务:本地事务只保单库,跨库事务引入分布式事务(补偿/最终一致),很多场景用"先本地后异步"规避
- 自增主键:改用雪花算法、号段模式,保证全局唯一有序
- 分片键选择:选查询最频繁、分布最均匀的字段,后患最小
- 加分:能说出"能不分就不分,先做读写分离/归档/索引优化,分库分表是最后手段"。
19. 死锁是怎么产生的?如何定位和处理?
- 产生:两个事务互相持有对方需要的锁并等待,形成环。典型:不同事务以不同顺序更新同一组行/间隙锁冲突。
- show engine innodb status 看 LATEST DETECTED DEADLOCK
- 结合死锁日志里的 SQL 与加锁行,还原加锁顺序
- 统一加锁顺序(业务规则层面)
- 缩短事务:少锁行、快速提交、避免事务里做远程调用
- 加分:说出"死锁无法完全避免,重点是快速发现+重试+减少发生概率"。
20. 大表 LIMIT 100000,20 为什么越来越慢?怎么优化?
- 原因:OFFSET 100000 要扫描并丢弃前 10 万行,即使只取 20 行,IO 全花在翻过的行上。
- 延迟关联:先只查主键再 join 回原表:
- SELECT * FROM t JOIN (SELECT id FROM t ORDER BY id LIMIT 1000…
- 游标分页(推荐):WHERE id > 上次最大值 ORDER BY id LIMIT 20,配合 id 索引
- 业务限制:只允许翻前 N 页,深层用筛选条件
- 加分:说明"游标分页不依赖页码,数据新增删除也不跳动",并对比不同方案适用场景。
21. binlog 的三种格式有什么区别?ROW 格式的影响是什么?
- STATEMENT:记录 SQL 语句,日志小,但非确定性函数(UUID/NOW)从库执行结果可能不一致
- ROW:记录行级变更前后值,最准确(默认),但从库执行/日志传输量大,大事务膨胀明显
- MIXED:自动切换,多数用 STATEMENT,不确定时转 ROW
- 选择:5.7+ 生产基本全用 ROW:准确、支持闪回解析、对数据一致性最好;代价是大事务日志量增大,因此要控制大事务。
- 加分:能说 ROW 格式与 Canal 监听 binlog、误删数据闪回工具的关系。
22. 大事务会带来哪些危害?怎么发现和处理大事务?
- 锁持有久:阻塞其他事务,引发锁等待甚至死锁
- 回滚慢:回滚段大,出问题要很久才滚完
- binlog 膨胀:大事务日志大,主从同步被拖慢,从库延迟
- 复制放大:ROW 格式下大事务到从库执行很久
- information_schema.innodb_trx 查长事务(trx_started 太早)
23. MySQL 误删数据了(update 忘加 where),怎么恢复?
- 前提:开启 binlog 且格式为 ROW——没有就基本只能靠备份+时间点恢复。
- 立即止损:停相关写入,防新数据覆盖现场;先锁或摘流量
- 找误操作点:通过 binlog 定位误操作的位置(时间/pos)
- 构造反向 SQL:ROW 格式 binlog 里记录了每一行的"前镜像",用 binlog2sql/flashback 类…
- 执行恢复:在隔离环境验证恢复出的数据,再导回(注意与误操作后新数据的关系)
24. count(*) 很慢怎么办?统计行数有没有更好的方案?
- 为什么慢:InnoDB 不支持常数时间行数统计(要扫),不像 MyISAM 存了行数;
- 近似值:explain 的 rows、show table status 的 rows 字段——需求是"大概多少行"时够用
- 计数表/Redis:独立计数(插入+1、删除-1),注意一致性与并发(配合事务或用消息)
- 精确需求但数据量大:分区表统计、汇总表定期算
- 加条件过滤的 count:靠索引覆盖减少扫描
- 加分:能说"业务先问自己:要精确值还是近似值?很多场景 1 分钟前的数字完全可接受"。
Kafka(6 题)
25. Kafka 如何保证消息不丢失?(生产/服务/消费三端)
- 生产端:acks=all 等所有副本确认,发送失败重试;禁止裸 fire-and-forget
- 服务端:min.insync.replicas=2 保证最小同步副本,副本落后自动剔除 ISR
- 消费端:业务处理成功再手动提交 offset,禁止自动提交
- 追问一:不丢与不重如何兼得?——消费幂等(唯一键/状态机)。
- 追问二:为什么配了 acks=all 还会丢?——单分区只有 1 个副本时 min.insync 没意义。
26. 消费堆积了上百万条消息,你会怎么处理?
- 先定位堆积在哪:消费慢还是生产暴涨。
- 扩容消费者:消费者数 ≤ 分区数,先扩分区再扩消费者
- 检查消费逻辑瓶颈:慢 SQL/串行调用/无超时,先修消费速度
- 紧急降级:堆积不影响主流程的先停掉次要消费者,保核心链路
- 积压太久可考虑补数据脚本/重建消费位点(谨慎,先备份 offset)
- 加分:先答"扩分区+扩消费者",再答"治本在消费逻辑",最后强调先保核心链路。
27. 如何保证 Kafka 消息的有序性?
- Kafka 只保证分区内有序,全局无序。
- 按业务 key 分区:同一订单/同一用户的消息进同一分区,分区内天然有序
- 消费端不要并行拆散:同一分区由同一消费线程串行处理;用了多线程要自己维护顺序或按 key 分组
- 重试别破坏顺序:失败重试可能插队,需要阻塞重试或延迟队列
- 加分:主动点破"顺序性在重试和并发消费时最容易被打破",并给出按 key 分区 + 串行消费的完整链路。
28. 消费者组频繁发生 rebalance(重平衡),是什么导致的?
- rebalance 触发:消费者加入/退出、分区数变化、消费者没在 session.timeout 内发心跳。
- 频繁原因排查:
- 消费耗时超过 max.poll.interval.ms,被判定死亡踢出
- GC 停顿/网络抖动导致心跳超时
- 单消费者处理太慢拖全组(一个慢全组重平衡)
- 加分:说清"rebalance 期间消费暂停、可能重复消费",以及尽量缩小 rebalance 影响面(Sticky 策略…
29. Kafka 分区数怎么定?分区多了有什么副作用?
- 分区作用:并行度(生产写多分区并行、消费按分区并行)、扩展性。
- 吞吐需求:单分区吞吐上限(数百 MB/s 级)能否满足,不够再扩
- 消费并行度:消费者数 ≤ 分区数,分区数 ≈ 期望消费者数×备份余量
- 业务分区键:保证同 key 有序时,分区数要固定,扩容分区会打乱顺序分配
- 分区过多的副作用:
30. Kafka 单机为什么能支撑百万级消息?聊聊它的高性能设计
- 顺序写磁盘:追加日志文件,顺序写比随机写快几个数量级,接近内存速度
- 页缓存(page cache):读写都走 OS 页缓存,热数据命中内存,自己不搞缓存
- 零拷贝:消费时 sendfile 直接把页缓存数据发网卡,减少用户态拷贝
- 批量+压缩:批量发送、批量落盘、批量拉取,压缩传输
- 分区并发写,突破单文件写入上限
- 加分:能解释"页缓存+顺序写"让 Kafka 的"磁盘存储"实际跑出内存级吞吐。
RabbitMQ(3 题)
31. RabbitMQ 的三种交换器(exchange)类型有什么区别?
- Direct:按 routing key 精确匹配队列
- Fanout:广播,消息发给所有绑定的队列(忽略 key)
- Topic:按通配符规则匹配,点号分段,如 order.# 匹配 order.create.suc;
- 选型:精确路由→direct;一对多广播→fanout;复杂订阅规则→topic。
- 常见坑:绑定关系记错导致消息"凭空消失"——先确认交换器/队列/绑定三者都建好,且带持久化。
32. RabbitMQ 消息确认机制:Publisher Confirm 与 Consumer Ack 是什么?
- Publisher Confirm:发送后 broker 确认收到才放心,没确认的重发。
- Consumer Ack:消费者处理完返回 ack,basicNack 表示失败可重投;
- 队列/消息持久化(durable + delivery_mode=2),重启不丢
- 手动 ack + 失败重投/死信队列(DLX)
- 重试消费要防"毒消息"无限循环:超次数进死信队列人工处理
- 加分:答出 dead-letter-exchange 处理失败消息的完整姿势。
33. 死信队列(DLX)是干什么的?配一个消息重试的完整链路
- 死信:消息被拒绝(requeue=false)、TTL 过期、队列满时,消息转到绑定的死信交换器(DLX)。
- 重试链路设计:
- 业务队列消费失败→basicNack(requeue=false)→进死信队列
- 死信队列消费者做延迟重试(配合 TTL 或延迟插件),超过 N 次进人工死信队列
- 人工队列告警,人工排查后重新投递
- 加分:能画全链路——业务队列→死信→延迟→重试→人工,并说出每层怎么监控。
RocketMQ(2 题)
34. RocketMQ 和 Kafka 有什么区别?各自适合什么场景?
- 相同:都是分布式消息队列,分区/消费者组/顺序写/页缓存思想类似。
- 延迟与实时:RocketMQ 消息毫秒级即时投递;Kafka 吞吐极致但延迟略高(设计目标不同)
- 功能丰富度:RocketMQ 自带延迟消息、事务消息、消息重试队列、Tag 过滤;Kafka 需要外围实现
- 协议与生态:Kafka 开源生态/流处理(Kafka Streams/Flink 衔接)更强;
- 消费模型:RocketMQ 默认 push(长轮询模拟),Kafka 是纯 pull
35. RocketMQ 事务消息是怎么保证"本地事务和发消息"一致性的?
- 解决场景:先更新 DB 再发消息,发消息失败/DB 回滚导致不一致。
- 流程(两阶段+回查):
- 发送半消息(对消费者不可见)
- 执行本地事务
- 本地事务成功→提交消息,消费者可见;失败→回滚,消息删除
- 加分:对比说明"可靠消息最终一致"方案(本地消息表也是思路之一)。
Nginx(6 题)
36. Nginx 返回 502 和 504 分别是什么原因?怎么排查?
- 502 Bad Gateway:upstream 没接住请求——后端进程挂了、端口不通、连接被拒。
- 504 Gateway Timeout:后端在 proxy_read_timeout 内没返回——后端慢。
- 先分清"连不上"还是"响应慢",排查方向完全不同。
37. Nginx 常见的负载均衡算法有哪些?分别适用什么场景?
- 轮询(默认):请求均匀分发,适合无状态、机器性能均衡
- 加权轮询:weight 按机器性能调,容量不均时用
- ip_hash:按客户端 IP 哈希,保证同一来源固定后端(需会话时临时用)
- least_conn:发给当前连接最少的,长连接/耗时波动大时更合理
- 第三方一致性哈希:按 key 分散且扩展影响面小
- 加分:主动说"有状态会话优先用分布式会话存储,而不是依赖 ip_hash"。
38. 用 Nginx 怎么实现限流?漏桶和令牌桶思路的区别?
- ngx_http_limit_req_module:漏桶思路——请求进队列按固定速率处理,超出排队的直接返回 503
- ngx_http_limit_conn_module:限制同一 IP/域名的并发连接数
- 令牌桶思路:桶里存令牌,拿得到令牌才放行,允许突发(limit_req 的 burst + nodelay 近似实现突发放…
- 区别一句话:漏桶强行平滑速率,令牌桶允许短时突发。
- 生产配置要点:按 IP + 接口维度限,配合错误码和降级页,别把所有限流写死在一个维度。
39. Nginx 改完配置怎么生效?reload 和 restart 的区别?
- 改配置后:nginx -t 先校验,再 nginx -s reload。
- reload:master 进程校验新配置→平滑拉起新 worker,旧 worker 处理完存量连接后退出——不断连接,…
- restart:全部停再起,存量连接全断,有发布窗口风险,尽量别用。
- 其他管理信号:stop(快速停)、quit(优雅停)、reopen(重开日志文件,日志轮转后使用)。
- 加分:说"nginx -t 是 reload 前的铁律,配置错误时 reload 会报错且不生效"。
40. Nginx 怎么做动静分离与静态资源缓存?
- 动静分离:静态资源(js/css/图片)由 Nginx 直接返回或走 CDN,动态请求 proxy_pass 到后端:
- location ~* .(js|css|png|jpg)$ { root /data/static;
- 后端响应缓存:proxy_cache_path 定义缓存目录与 zone,location 里:
- proxy_cache mycache;
- proxy_cache_valid 200 10m;
- 加分:能说"动态接口缓存要小心(登录态/个性化),宁可少缓存不可错缓存"。
41. worker_processes 和 worker_connections 怎么配?
- worker_processes:worker 进程数,建议 = CPU 核数(容器按核数),IO 密集可略多。
- worker_connections:单个 worker 最大并发连接数。
- 最大并发公式:最大连接 ≈ worker_processes × worker_connections(反向代理场景减半,…
- 先按 CPU 核数定 worker,再用公式反推 connections 满足业务峰值
- 别无限调大 connections——受 fd 限制(ulimit -n 要同步调)与内存限制
Elasticsearch(6 题)
42. ES 的倒排索引是什么?为什么适合搜索?
- 正排:文档→词,检索要遍历全文。
- 倒排:词→文档列表,查询时先分词,再查词对应的文档列表取交集。
- 流程:文档写入时 analyzer 分词建倒排;查询时同样分词匹配,再按相关性打分排序。
- 适合:大量文本的包含性检索、模糊搜索;不适合精确数值统计与事务场景(那是数据库的事)。
- 加分:能说出分词器差异(IK/standard)对检索结果的影响。
43. ES 分页超过 10000 条报错或极慢,怎么解决深分页?
- from+size 大分页:每次都要在每个分片取大量文档再全局排序,代价随页深指数增长;
- 业务上只给浅分页(前几百页)+ 搜索关键词约束
- search_after:基于上一页排序值续查,稳定高效,适合"下一页"场景(缺点:不能跳页)
- scroll:生成快照游标批量拉取,适合导出/全量扫描,不适合实时前端分页
- 加分:按场景答——用户翻页用 search_after,后台导出用 scroll,并主动说明跳页限制。
44. ES 集群里分片和副本怎么设置才合理?
- 分片数:创建索引后不可改,要提前估。经验:单分片 20-40GB 左右,总分片数别超过节点 CPU 核数太多
- 副本:至少 1 份保高可用(挂一个节点不丢数据),读多场景加副本分摊查询
- 分片过少→单分片太大、恢复慢;分片过多→元数据开销大、小分片碎片化
- 写多读少:副本 1 即可,副本写放大是开销
- 索引按日期滚动(日志场景):hot-warm 冷热分层,控制活跃分片总量
- 加分:能说出"分片大小和总数比单纯数量更重要"。
45. ES 的 mapping 是什么?为什么中文搜索要配 IK 分词?
- mapping:索引的字段类型定义,决定字段怎么索引与查询(类似表结构)。字段类型/分词器建了难改,一般要重建索引+rei…
- 为什么 IK:默认 standard 分词按空格/标点切,中文整句被切成一个词,搜"运维面试"无法直接命中"运维 面试"的…
- 加分:能答出 IK 自定义词典(行业词库)、以及 mapping 设计时 text+keyword 双字段(要聚合用 ke…
46. 写入 ES 的数据为什么不能立刻搜到?refresh、flush、translog 是什么?
- 写入路径:写内存 buffer →(每秒)refresh 生成 segment 可被搜索 → segment 定期 mer…
- refresh:把 buffer 变成可搜索的 segment,默认 1 秒一次——所以刚写入的数据最多延迟 1 秒可见
- flush:把 segment fsync 落盘并清 translog(由 merge/内存触发或手动)
- translog:写盘日志,防"内存 segment 丢了"——宕机后重放
- 日志批量导入想快:调大 refresh_interval(如 30s),换吞吐换实时性
- 加分:答出"可搜索≠已落盘"的两段式设计,以及 translog 是数据安全底线。
47. ES 集群脑裂是怎么回事?怎么避免?
- 脑裂:网络分区后,节点们互相看不到对方,各自选主,出现多个"主节点",写一致性被破坏。
- 候选主节点数要奇数次,且 discovery.zen.minimum_master_nodes = N/2 + 1(7.0…
- 只有法定多数存在才能选主——分区两侧只有一边够数,防止双主
- 主节点专用:master-eligible 节点独立部署,别和数据节点混跑
- 网络质量:集群节点间低延迟网络,心跳超时设置合理(别设太长掩盖问题)
- 加分:强调"法定多数(minimum_master_nodes/quorum)是防脑裂的根基,配错等于裸奔"。
ZooKeeper(3 题)
48. ZooKeeper 是干什么的?znode 有哪些类型?
- ZooKeeper:分布式协调服务,提供强一致的数据存储与通知机制,常用来做分布式锁、选主、配置/元数据存储(旧版 Kaf…
- 核心概念 znode(数据节点):
- 持久节点:创建后一直存在
- 临时节点:创建它的会话断开自动删除——"服务在不在"用它探活
- 顺序节点:名字带自增序号——天然适合排队/选主(谁序号最小谁主)
49. ZK 怎么选主(Leader 选举)?它和 etcd 有什么区别?
- ZK 选主:启动时节点用临时顺序节点抢占,序号最小者为 Leader;Leader 挂了,其余节点靠 watch 感知重新…
- 与 etcd 对比:
- 协议:ZK 用 ZAB,etcd 用 Raft——都是多数派共识,写要过半节点确认
- 数据模型:ZK 是 znode 树,etcd 是 key-value(带版本/租约)
- 生态:云原生时代 etcd 成为 K8s 存储事实标准,ZK 更多在旧 Kafka/HBase 生态
50. 基于 ZooKeeper 的分布式锁怎么实现?有什么坑?
- 实现(临时顺序节点方案):
- 在锁目录创建临时顺序节点
- 判断自己是不是序号最小:是→拿到锁;不是→watch 前一个节点,等它释放
- 释放:删除自己节点(或会话断开自动删临时节点)
- 优点:无惊群(只 watch 前一个),会话断开自动释放(比 Redis 锁天然防"客户端挂了锁还在")。
- 加分:主动对比"ZK 锁重一致、Redis 锁轻快但不防主从切换丢锁"。
Nacos(3 题)
51. Nacos 作为注册中心,AP 模式和 CP 模式是什么?临时实例是什么?
- 注册中心的两种一致性取向:
- AP(可用性优先):服务注册信息允许短暂不一致——业务服务注册场景选 AP(服务 A 多实例,一两个实例注册状态旧问题不大…
- CP(一致性优先):要求所有节点看到同一份注册数据——需要强一致的场景(如配置元数据、集群选主)用 CP
- 临时实例:服务心跳保活,失联自动剔除,适合常规服务;持久实例:不依赖心跳,适合非临时下线场景(如 K8s 里的特殊服务)。
- 注册中心选型小结:Nacos(国内主流,注册+配置一体)、Eureka(纯 AP,已维护停滞)、ZooKeeper(CP)…
52. Nacos 动态配置"改了秒生效"是怎么实现的?
- 核心:客户端长轮询 + 服务端变更通知。
- 客户端发请求"查配置",服务端不立刻返回,挂起等待(最长约 30 秒)
- 期间配置变了→服务端立即返回响应;没变→超时后返回,客户端立刻发起下一次长轮询
- 客户端拿到新配置后,刷新本地缓存并回调(监听器),应用数据源随之更新(如 Spring 的 @RefreshScope)
- 比"定时拉取"实时;比 WebSocket/推送实现简单且兼容性好。
53. 服务注册中心如果全挂了,已经运行的服务会怎样?
- 认知:注册中心主要影响"服务发现",不影响已建立连接。
- 挂掉后的表现:
- 已注册实例间的既有连接不受影响,流量正常
- 新实例无法注册——新扩容的机器进不了流量池
- 客户端本地缓存兜底:多数客户端(如 Nacos 客户端、Eureka 客户端)会缓存注册表,注册中心不可用时用本地缓存继续…
- 加分:强调"注册中心是控制面组件,控制面抖动不应打断数据面既有流量"。
Seata(3 题)
54. Seata 是什么?AT 模式是怎么实现分布式事务的?
- Seata:阿里巴巴开源的分布式事务框架,提供 AT/TCC/Saga/XA 四种模式。
- AT 模式(最常用,对业务侵入小):
- 一阶段:业务在本地库执行 SQL(undo_log 记录数据前镜像),直接提交本地事务,不持锁
- 二阶段提交:全局事务成功→异步删 undo_log;失败→按 undo_log 反向补偿(生成反向 SQL 恢复数据)
- 全局锁:写冲突时靠全局锁协调,防脏写
55. AT、TCC、Saga、XA 四种分布式事务模式怎么选?
- XA:数据库原生两阶段提交,强一致,但需要数据库支持 XA 且锁持有久、性能差——老旧系统/强一致场景
- AT:自动生成补偿(基于 undo_log),侵入小、性能好——大多数"跨库事务"首选
- TCC:业务自己写 Try/Confirm/Cancel 三方法,控制力最强、无锁,但开发量大——对一致性要求高、愿意投入…
- Saga:长事务编排,每步正向+补偿(类似 TCC 简化版,适合长流程、无"锁定资源"概念),弱隔离
- 选型:能接受的开发量小→AT;强一致且库不支持分布式→XA;资源预留型业务(库存/资金)且能投入→TCC;
- 加分:点破"没有银弹,先想清楚能不能用最终一致/消息方案避免分布式事务"。
56. 分布式事务是不是所有跨服务场景都需要?什么时候可以不用?
- 先问:跨库/跨服务操作是不是真的需要"同时成功"?多数业务场景可以设计成不强依赖:
- 消息最终一致:主流程写库+发消息,从流程消费消息异步处理(可重试)——能覆盖大部分"下游更新"需求
- 本地消息表/事务消息:先落本地事务把"待发消息"一起提交,再可靠投递
- 对账兜底:定时核对两边数据,差异补偿
- 需要真分布式事务的场景:强一致要求(资金/库存强约束)、无法容忍中间状态。
- 加分:强调"分布式事务是复杂度很高的最后手段,架构上优先通过拆分(单库事务)或异步化(最终一致)绕开它"。
MongoDB(2 题)
57. MongoDB 和 MySQL 怎么选?什么业务适合文档型数据库?
- MongoDB 优势场景:
- 数据结构灵活多变:文档嵌套、字段不固定,省去频繁 ALTER
- 海量写与水平扩展:分片集群横向扩容比 MySQL 分库分表省心
- 读写都按主键/单文档:日志、IoT 数据、用户资料、内容/评论这类"单文档读写多"的场景
- 强事务/多表关联复杂查询(虽然 4.0+ 支持事务,但跨文档事务成本高)
58. MongoDB 副本集和分片分别解决什么问题?
- 副本集(Replica Set):解决高可用——一个主多个从,主挂自动选举新主;数据冗余防单点。
- 分片(Sharding):解决容量与吞吐——按分片键把数据分布到多个分片(每片可以是一个副本集),支持海量数据横向扩展。
- 分片键决定一切:要选分布均匀且查询带它(否则全片广播);选了难改,和 MySQL 分库分表同款教训
- 分片架构组件:mongos(路由)+config server(元数据)+shard
- 先副本集后分片:数据量没到(如 < 几百 GB/单机扛得住)别急着分片,分片是运维复杂度
- 加分:点破"副本集管不挂,分片管装得下+扛得住,两个维度别混淆"。
PostgreSQL(3 题)
59. PostgreSQL 和 MySQL 核心区别是什么?怎么选?
- 进程模型:PG 每个连接一个进程(连接开销大,需连接池);MySQL 线程模型(轻)
- 事务与 MVCC:PG 用元组多版本(update 产生新版本行),MySQL InnoDB 用 undo 日志,垃圾回收…
- 功能:PG 更强——完整 ACID/外键约束严格、JSONB/数组/全文检索/复杂索引(GIN/GiST)/窗口函数完整、…
- 运维:MySQL 主从与周边工具生态更普及(国内);PG 逻辑复制/流复制同样成熟
- 选型:复杂查询/数据分析/GIS/JSON 混合 → PG;业务简单/团队熟悉/生态配套 → MySQL。
- 加分:说清"不是谁替代谁,看业务查询复杂度与团队运维能力"。
60. PostgreSQL 的流复制和逻辑复制有什么区别?各有什么用?
- 流复制(物理复制):直接传输 WAL 日志,从库和主库物理一致。
- 同步/异步模式;同步模式可做到"主提交前从已确认"
- 用途:高可用(备库 failover)、只读扩展
- 限制:所有表都要复制,不能跨大版本随意复制
- 逻辑复制:基于 WAL 解码出行级变更发布/订阅。
- 加分:注意区分——物理复制管"高可用",逻辑复制管"数据分发"。
61. PostgreSQL 变慢了,除了慢 SQL 还有什么 PG 特有的排查点?
- PG 特有排查点:
- 连接数:每个连接一个进程,连接堆积会耗尽内存(max_connections),先看连接数
- 锁等待:pg_locks/等待事件查阻塞——和 MySQL 类似但视图不同
- Vacuum 问题:更新/删除产生死元组,不及时 vacuum 会导致表膨胀(bloat)与索引膨胀,扫描变慢——查 au…
- 磁盘 IO/Checkpoint:频繁 checkpoint 会拖慢(shared_buffers 与 wal 配置)
- 加分:能主动说"PG 性能问题里 vacuum 没跟上导致膨胀是新手最常忽略的",并建议周期性维护。
ClickHouse(2 题)
62. 为什么 ClickHouse 做大数据量聚合分析那么快?
- 核心:列式存储 + 向量化执行 + 压缩。
- 列式存储:分析只要几列,只读这几列的数据块,避免像行式存储那样整行 IO
- 高压缩比:同列同类型数据相似度高,压缩率惊人,减少磁盘 IO
- 向量化执行:一批数据一次计算,充分利用 CPU SIMD
- 稀疏索引/分区裁剪:按分区与主键索引跳过无关数据
- 加分:对比 MySQL——OLTP 行式按行更新,OLAP 列式按列聚合,存储模型和查询模式必须匹配。
63. ClickHouse 有哪些"坑"?什么场景不适合它?
- 不适合/注意的场景:
- 高频单行更新/点查:它是分析型数据库,update/delete 是"突变",代价高;点查(按主键随机取一行)性能差
- 高并发查询:适合"大查询慢但并行",不适合每秒几万个小查询(连接并发上限明显)
- 事务与强一致:没有完整事务模型,多表 Join 能力弱
- 实时性:数据写入后要经过后台合并才可见性最好,不是"写后立即可读最新"的 OLTP 心智
- 加分:结论——“OLAP 数据仓库用它,OLTP/事务/高并发点查别碰”。
时序数据库(2 题)
64. 什么时候该上时序数据库(InfluxDB/TDengine)?和 Prometheus 什么关系?
- Prometheus 的定位:监控领域的时序存储+告警一体化,适合"指标监控",但:单机容量有限、长期历史数据贵、查询能力…
- 要上独立时序库(TSDB)的信号:
- 数据量大且要长留存(监控/业务指标按年留)
- 来源多样(设备采集/业务埋点/日志衍生指标)而非只服务监控告警
- 需要复杂时序查询/聚合(降采样、滑动窗口、实时分析)
- 加分:选型考虑点——压缩比、写入吞吐、SQL 能力(TDengine 支持类 SQL,团队上手快)、集群与成本。
65. 时序数据库的核心设计是什么?为什么比普通数据库能存更多指标?
- 时序数据特征:持续追加、按时间排序、同组指标重复度高。基于此的设计:
- 列式/按时间组织:同一时间段的指标连续存放,利于顺序扫描与批量压缩
- 专用压缩:相邻值差分+变长编码(Gorilla 类压缩),浮点指标能压 10 倍以上
- 标签(series)索引:按 series(指标+标签组合)存储,查询先定位 series 再扫时间段
- 降采样与过期策略:老数据自动降精度/删除,控制成本(如 7 天原始+90 天 5 分钟均值)
- 加分:能对比"普通行式库为什么存时序低效(随机写/无压缩)",凸显 TSDB 的设计针对性。
XXL-Job(2 题)
66. 分布式任务调度(XXL-Job/Quartz)解决什么问题?
- 单机 Cron 的问题:任务跑在单台机器,机器挂了任务没了;多台机器部署又会重复执行。
- 分布式调度解决:
- 选主执行:同一任务只在一台执行(Quartz 集群模式用 DB 锁/ZK 选主)
- 分片广播:大任务按机器分片(每台处理一部分,如按用户取模)
- 失败重试/告警:执行失败自动重试与通知
67. 定时任务"到了时间没跑/重复跑/跑一半失败",怎么排查?
- 到了没跑:看调度中心日志与执行器心跳——调度中心挂了?执行器离线?任务被上次执行卡住(阻塞策略)
- 重复执行:同一任务多执行器同时跑(没有选主/分布式锁)、上次失败重试与新触发重叠——任务要幂等,加锁或状态机
- 跑一半失败:看执行日志(哪一步挂)、数据是否部分成功——任务要有断点重跑能力(按批/按时间范围)
- 时间不准:服务器时间不同步、Cron 表达式写错(时区!)
- 监控:任务成功率/执行时长纳入监控,静默失败最可怕
- 加分:强调"定时任务三大纪律——幂等、可重跑、有监控",并提分片任务要处理部分分片失败。
负载均衡(2 题)
68. LVS 的 NAT/DR/TUN 三种模式区别?和 Nginx 负载的区别?
- LVS 三种模式:
- NAT:进包出包都过 LVS,做地址转换——后端无需特殊配置,但 LVS 成瓶颈(进出都走它)
- DR(最常用):请求进 LVS,响应由后端直接回客户端(LVS 只改 MAC,不进出流量)——吞吐高,要求后端与 LVS …
- TUN:封装 IP 隧道转发,可跨网段,配置复杂
- LVS vs Nginx:
69. Keepalived/VRRP 是怎么做 VIP 高可用的?脑裂怎么防?
- VRRP 原理:多台机器抢同一个虚拟 IP(VIP),通过心跳互报优先级——优先级高的当 MASTER 持有 VIP 对外…
- 为什么 VIP 要漂移:LVS/Nginx 等负载入口,客户端只认 VIP;负载节点挂了,VIP 漂到备用节点,对客户端无…
- 脑裂风险:心跳链路断了但两边都活着,两台同时持有 VIP 对外服务,流量分流出错。
- 心跳网卡与业务网卡分离,多心跳线(组播+单播+脚本探测)
- 仲裁:配合第三方(云 API/存储锁)做"谁该持有"的裁决
- 加分:强调"脑裂的本质是谁活着一票的问题,单靠心跳永远有盲区,要加仲裁维度"。
Tomcat(2 题)
70. Tomcat 的连接器(Connector)和线程池是什么?怎么调优?
- Tomcat 架构要点:Connector 负责接收 HTTP 连接,交给线程池中的线程处理 Servlet。
- maxThreads:最大处理线程数(默认 200)——瓶颈常见于此
- acceptCount:排队队列长度,满了直接拒绝
- maxConnections:最大连接数(与线程池配合,连接多了排队)
- connectionTimeout:连接超时
- 加分:强调"线程池满往往是下游慢的信号,参数是退路不是药"。
71. 应用服务器的演进:war 包时代到现在容器化,发生了什么?
- 传统部署(war 时代):应用打成 war 部署到 Tomcat(应用服务器管理连接与生命周期),一台机器一个 Tomca…
- 嵌入式(Spring Boot):应用自己内嵌 Tomcat/Jetty,打成可执行 jar——应用自包含,部署变简单
- 容器化:镜像里带上运行时与依赖,发布=换镜像,环境一致、秒级伸缩
- 平台化:K8s 管编排与生命周期,应用只管业务逻辑
- 核心变化:从"部署到服务器"变成"应用自带服务器并作为不可变单元运行"。
- 加分:能说清"应用服务器职责(连接管理/线程/会话)在容器化后被平台(K8s+运行时)承接,DevOps 的人更关心进程与…
对象存储(2 题)
72. 对象存储(OSS/S3/MinIO)和块存储、文件存储有什么区别?
- 块存储(云盘):像硬盘,给单台机器格式化挂载,性能最好,不能跨机器共享
- 文件存储(NFS):像共享目录,多台机器挂载共享,适合传统应用共享文件
- 对象存储(OSS/S3):桶(Bucket)+对象(Key),通过 HTTP API 访问,无限扩容、跨机器共享、自带冗余…
- 对象存储适合:图片/视频/日志归档/备份/大数据湖;不适合:数据库数据文件(需要随机读写低延迟)、POSIX 语义应用。
- 选型:性能敏感用块,共享小规模用文件,海量+API 访问用对象。
- 加分:能说"对象存储为什么能无限扩展(分布式架构+元数据服务)"及 HTTPS API 的普及性。
73. MinIO 的高可用和数据安全是怎么做的?纠删码是什么?
- MinIO:开源自建对象存储,兼容 S3 API。
- 纠删码(EC):数据分片+冗余块分布在多块盘/多节点,如 4+2(数据 4 块+校验 2 块)——坏任意 2 块盘数据不丢…
- 多节点集群:每个节点多块盘,纠删码跨节点,允许同时挂 N 台
- 数据保护:版本控制+对象锁(防误删/合规)
- 加密:服务端加密(SSE)与传输加密(TLS)
- 加分:强调"自建对象存储要按生产系统规划(节点/盘数/异地副本/演练恢复),别当玩具装两台就完"。
EMQX(2 题)
74. EMQX 是干什么的?MQTT 协议适合什么物联网场景?
- EMQX:开源 MQTT 消息服务器(broker),海量物联网设备接入与消息转发。
- MQTT 特点(为什么 IoT 用它):
- 轻量:报文头小、带宽占用低,适合嵌入式/弱网设备
- 发布订阅:设备上报与命令下发解耦
- 三种 QoS:0(最多一次)/1(至少一次)/2(恰好一次),按场景选
- 加分:能说"QoS1+消息去重是物联网生产标配,以及 TLS/设备鉴权(用户名密码/证书)是上线必配"。
75. 百万级设备接入 EMQX,集群和高可用怎么设计?
- 集群:多节点组成集群(分布式消息路由),节点间共享订阅关系,加节点扩容量;生产至少 3 节点
- 接入层:LB(四层)分发设备连接,设备重连自动均衡
- 消息分发:Topic 订阅在集群内路由,单点订阅跨节点也能收到
- 持久化与集成:消息一般不长期存 EMQX,规则引擎转存——数据入库用桥接(消息转发 Kafka/MySQL/TSDB)
- 安全:设备接入启用 TLS+鉴权;数据面与集群管理面分离
这些题我整理成了一个微信小程序
上面这些题(以及更多)我整理成了一个微信小程序「系统运维面试题学习随手记」,295 道题按 8 个模块分类:
中间件 · DevOps · SRE · 云原生 · Linux · AIOps · Shell · 综合开放题
- 题库全部免费,不用登录,打开就能刷,每题都有参考答案(就是上面这种"排查步骤 + 回答结构"的形式)
- 把简历和 JD 粘进去,会出 20 道针对你经历的押题,并给一份适配度分析(哪些 JD 要求你有对应经验、哪些要提前准备说法)
- 还有录像练习:摄像头答题 → 回放 → 按要点自评,练表达(本地处理,不上传)
微信搜索小程序「系统运维面试题学习随手记」。
以上 75 道题整理自自建的运维面试题库(共 295 题,覆盖中间件/DevOps/SRE/云原生/Linux/AIOps/Shell/综合开放题 8 个模块,免费刷),需要的话评论区留言。





