04 MySQL / Redis / MQ
这一块在面试里是干什么的
主要看你是不是只停留在 Controller 和 Service 层。
高频到不能跳过。
MySQL
什么是索引
索引是帮助数据库快速定位数据的数据结构。
一句话:
“索引像书的目录,不用每次从头翻到尾。”
为什么索引能加快查询
因为它减少了全表扫描。
索引的代价
- 占空间
- 写入变慢
- 索引太多反而维护成本高
最左前缀原则
联合索引从最左边字段开始才更容易命中。
比如索引是 (a, b, c),优先命中从 a 开始的查询条件。
什么情况下索引可能失效
- 对索引列做函数操作
- 模糊查询以
%开头 - 类型隐式转换
- 联合索引没走最左前缀
事务四大特性 ACID
- 原子性
- 一致性
- 隔离性
- 持久性
隔离级别
短期先记 4 个名字:
- 读未提交
- 读已提交
- 可重复读
- 串行化
高频快答:
“MySQL InnoDB 默认隔离级别是可重复读。”
什么是脏读、不可重复读、幻读
- 脏读:读到别人未提交的数据
- 不可重复读:同一行前后读到的值不一样
- 幻读:前后两次查询,记录条数不一样
慢 SQL 怎么排查
先答步骤:
- 看执行计划
- 看是否走索引
- 看 SQL 写法是否合理
- 看数据量和回表情况
Redis
Redis 为什么快
主要因为:
- 基于内存
- 单线程模型避免线程切换开销
- IO 多路复用
Redis 常见数据类型
- String
- Hash
- List
- Set
- ZSet
零基础先知道使用场景就够了。
缓存为什么用 Redis
- 读快
- 适合热点数据
- 可以减轻数据库压力
缓存穿透
查不存在的数据,请求每次都打到数据库。
解决:
- 缓存空值
- 参数校验
- 布隆过滤器
缓存击穿
一个热点 key 失效,大量请求同时打到数据库。
解决:
- 热点不过期
- 加互斥锁
- 提前刷新
缓存雪崩
大量 key 同时过期,数据库瞬间被压垮。
解决:
- 过期时间加随机值
- 多级缓存
- 限流降级
双写一致性怎么答
先答思路,不必追求完美:
“常见做法是更新数据库后删除缓存,而不是先更新缓存。因为缓存是辅助层,可以允许短时间不一致。”
分布式锁
Redis 可以做分布式锁,但要注意:
- 过期时间
- 锁误删
- 续期问题
MQ
为什么要用消息队列
- 解耦
- 异步
- 削峰
一句话:
“MQ 把同步强依赖改成异步松耦合。”
常见问题
- 消息重复
- 消息丢失
- 消息顺序
- 消费积压
如何保证消息不重复消费
通常不是“绝对不重复”,而是“幂等处理”。
常见方式:
- 唯一业务 ID
- 数据库去重
- 状态机控制
如何保证消息可靠
回答框架:
- 生产者发送确认
- Broker 持久化
- 消费者手动确认
如何保证顺序
顺序消息通常会牺牲一部分吞吐,常见做法是同一业务 key 路由到同一队列。
高频快答
Redis 和 MySQL 怎么分工
MySQL 负责持久化和事务一致性,Redis 负责高并发热点读。
Redis 单线程为什么还能快
因为它避免了线程切换和锁竞争,主要瓶颈在内存和网络,不在 CPU 计算。
MQ 的本质价值
异步、削峰、解耦。
这一章最小记忆包
- MySQL 重点记索引、事务、隔离级别、慢 SQL
- Redis 重点记为什么快、数据类型、穿透击穿雪崩
- MQ 重点记为什么用、可靠性、幂等、顺序