重生——第九次面试2026.8.13某车一面
1. 拷打实习项目
面试重点:业务背景、遇到什么并发 / 数据问题、方案选型、踩坑、优化点、你负责模块,不要只讲功能。 STAR 思路: 1)S 场景:业务是什么,存在什么痛点(并发、数据不一致、性能慢) 2)T 任务:你的职责,需要解决什么问题 3)A 行动:技术方案,核心代码思路,中间踩过什么坑,怎么调优 4)R 结果:性能提升多少,解决了什么线上问题,学到什么
被追问高频方向:
- 为什么选这个技术,不用别的?
- 如果并发再放大 10 倍会出现什么问题?怎么优化?
- 线上出现 bug 你怎么排查?
- 这个方案有什么缺点?
2.MCP 协议 vs HTTP 协议调用区别
MCP:Model Context Protocol,AI 工具调用协议;HTTP 通用应用层协议
- 连接模式
- HTTP:短连接为主,每次请求建立 / 释放连接;也可以长连接 keep‑alive。无状态。
- MCP:基于流的长连接(stdio、websocket),一次连接复用,持续双向通信。
- 数据模型
- HTTP:Request‑Response 一问一答模式。
- MCP:JSON‑RPC 2.0,可以并行多路请求,同一个连接同时发多个调用,不需要等待上一个返回。支持通知(不需要 response)。
- 用途
- HTTP:通用服务调用,前后端、微服务。
- MCP:专门给大模型做 Tool Call;工具、资源、提示词标准化,模型可以发现可用工具。
- 开销
- HTTP:http 头、cookie 等头部开销大。
- MCP:二进制 / 流式 json,头部少,多次调用开销更低。
- 认证
- HTTP:header token、cookie、oauth2。
- MCP:支持 transport 层认证(ws token、stdio 环境变量),协议本身不强制。
简单总结:HTTP 适合通用微服务;MCP 面向 AI 工具调用,长连接 + JSON‑RPC,支持并行调用,专为模型工具交互设计。
3. 系统之间认证怎么做(服务间认证)
Token 方式(JWT)服务 A 生成 jwt,放到请求头传给服务 B;B 校验签名。适合网关、跨服务。缺点:无法主动作废 token。
OAuth2.0 客户端凭证模式 Client Credentials服务账号,专门用于服务与服务之间,拿 access_token 访问资源服务。适合多微服务。
API Key简单,请求头放 api‑key,服务端校验 key,配置在配置中心。适合第三方调用,缺点密钥泄露风险。
mTLS 双向 TLS双方都持有证书,握手阶段互相校验证书。安全高,适合内网核心服务,运维重。
Spring Cloud Alibaba 微服务体系:Sentinel + Nacos 元信息 + token 透传内网服务也可以网关统一鉴权。
MCP 场景:transport 层携带密钥,ws url 带 token,或者环境变量传密钥。
区分:
- 用户登录认证:面向人;
- 服务间认证:机器对机器,不需要用户参与。
4.InnoDB 索引结构
InnoDB 索引是B + 树
- B + 树所有数据都在叶子节点;非叶子节点只存索引键 + 页号,用于路由查找。
- 主键索引(聚簇索引):叶子节点保存完整行数据;表数据本身就是按主键 B + 树组织。
- 二级索引(普通索引):叶子节点存索引列 + 主键值,不存完整行。查到主键之后再去主键索引拿完整行,就是回表。
- 页:B + 树节点就是磁盘页,默认 16KB;一页存多条索引记录,减少磁盘 IO。
B + 树对比 B 树:B 树每个节点都存数据;B + 树只有叶子存数据,范围查询极强。
5. 回表是什么 & 索引失效
回表
查询使用二级索引,二级索引叶子只能拿到主键,再拿着主键去聚簇索引读取完整行数据,这个过程叫回表。
如果 select 只查索引本身包含的字段,不需要回表,叫覆盖索引。 例:索引 (name)
select name from t where name='xxx'→ 覆盖索引,不回表select name,age from t where name='xxx'→ 需要回表拿 age
6. 索引失效常见场景
- 索引列做运算、函数、隐式类型转换
where substr(name,1,1)='a'/where str='123'字段是 int - like 以通配符开头
like '%abc' - or 一边条件没有索引
- not in、!=、is not null 不一定失效,要看数据分布,不能直接说一定失效
- mysql 优化器判断全表扫描比走索引更快,放弃索引。数据量占比大的时候触发。
- 联合索引不满足最左前缀原则。
注意:is null 可以走索引;is not null 可能不走,看数据。
联合索引 abc,bc 失效,那 ba?有 a 就行是吧?
联合索引index(a,b,c)遵循最左前缀匹配有效条件:从索引最左开始连续使用。
✅有效: where a=? where a=? and b=? where a=? and b=? and c=? where a=? and c=? (a 生效,c 失效;b 没有,c 不能用索引排序过滤)
❌失效: where b=? and c=? 没有 a,整个索引无法使用 where b=? and a=? →SQL 条件顺序无关!mysql 优化器会自动调整条件顺序,等价 a and b,可以正常走 abc 索引。
关键点:SQL where 条件书写顺序不影响,要看是否包含索引最左列 a。
where b=? and a=?,有 a,优化器重排为 a and b,可以走索引。where b=?,没有 a,完全不走这个联合索引。
“有 a 就行” 不完全对:
where a=? and c=?:a 可以用索引定位;b 缺失,c 无法利用索引过滤排序。只能用到 a 这一部分。
7. 缓存穿透 + 布隆过滤器原理
缓存穿透
查询数据库和缓存都不存在的数据,缓存 miss,请求直接打到 DB。大量这种请求压垮数据库。
解决方案:
- 缓存空值(缓存存 null,设置短过期时间)
- 布隆过滤器,拦截不存在 key,直接返回,不去查缓存、DB。
布隆过滤器原理
由bit 数组 + 多个 hash 函数组成。
- 存入 key:key 经过 N 个不同 hash 函数,算出 N 个 bit 下标,把对应 bit 位置 1。
- 查询 key:同样 N 次 hash,如果所有对应 bit 位都是 1 →可能存在;只要有一个 bit 是 0 →一定不存在。
特点:
- 存在误判率:判定存在实际可能不存在;不会漏判。
- 不支持删除元素(删除会影响其他 key),一般用计数布隆过滤器解决删除。
- 占用内存很小,适合海量数据做存在性判断。
缓存击穿:热点 key 过期,大量请求打数据库;缓存雪崩:大量 key 同时过期,redis 宕机。
8. 批量导入:Redisson 分布式锁 + 先更新库后延迟删缓存;其他解决方案
场景:人员信息批量导入,多线程并发修改同一组织节点,权限树错乱;方案:Redisson 分布式锁 + 先更新数据库,延迟删除缓存保证最终一致性。
先回顾:先更新数据库,再删除缓存
问题:更新成功,删除缓存失败 → 缓存旧数据,数据不一致。用延迟双删:更新 DB → 删除缓存 → 休眠一小段时间,再删一次缓存。Redisson 锁保证同一组织节点串行执行。
除 Redis 分布式锁之外,解决并发修改同一资源,防止错乱的方案:
数据库乐观锁(version 版本号)表增加 version 字段;更新时
update xxx set ... version=version+1 where id=#{id} and version=#{oldVersion};更新行数 0 代表已经被别人修改,捕获异常重试。不需要锁,适合并发冲突不多场景。缺点大量冲突会大量重试。数据库悲观锁
select ... for update行锁。事务内锁住这行,其他线程阻塞。 缺点:数据库压力大,长事务容易死锁,不适合高并发批量导入。业务层队列,按组织 ID 分片队列同一个组织节点的所有导入任务投递到同一个队列,单线程消费。天然串行,无锁。Kafka/RabbitMQ。适合批量导入,削峰。
数据库唯一约束如果业务可以,利用唯一索引避免重复脏写。
Zookeeper 分布式锁临时有序节点实现分布式锁,可靠性高,性能比 Redis 差。
选型对比: 冲突少优先乐观锁;批量任务可以消息队列串行;高并发争抢用 Redis 分布式锁;强一致性可以 zk 锁。
注意:分布式锁只能解决并发写错乱;不能彻底解决缓存 DB 不一致,还是依赖延迟双删、MQ 重试删除缓存。
9.IOC 和 AOP
IOC(控制反转 Inversion of Control)
- 控制反转:把对象创建、依赖交给 Spring 容器,而不是自己 new 对象。
- DI 依赖注入是 IOC 实现方式:构造器注入、setter 注入、字段 @Autowired 注入。
- 好处:解耦,便于单元测试,容器统一管理生命周期。
- Bean 的生命周期:实例化 → 属性填充 →初始化 →销毁。
AOP(面向切面编程 Aspect‑Oriented Programming)
把通用横切逻辑抽离出来:日志、权限校验、事务、限流、埋点,不和业务代码耦合。
- 底层两种代理: 1)JDK 动态代理:实现接口的类,生成接口代理对象。 2)CGLIB 代理:继承目标类生成子类,类没有实现接口时使用。SpringBoot 默认 CGLIB。
AOP 概念:
- 切面 Aspect:通知 + 切点
- 切点 Pointcut:匹配哪些类哪些方法
- 通知 Advice:执行逻辑 @Before @After @AfterReturning @AfterThrowing @Around
- 连接点 JoinPoint:被拦截到的方法。
@Around 环绕通知功能最强,可以控制目标方法要不要执行。
