重生——第九次面试2026.8.13某车一面

重生——第九次面试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 通用应用层协议

  1. 连接模式
  • HTTP:短连接为主,每次请求建立 / 释放连接;也可以长连接 keep‑alive。无状态。
  • MCP:基于流的长连接(stdio、websocket),一次连接复用,持续双向通信。
  1. 数据模型
  • HTTP:Request‑Response 一问一答模式。
  • MCP:JSON‑RPC 2.0,可以并行多路请求,同一个连接同时发多个调用,不需要等待上一个返回。支持通知(不需要 response)。
  1. 用途
  • HTTP:通用服务调用,前后端、微服务。
  • MCP:专门给大模型做 Tool Call;工具、资源、提示词标准化,模型可以发现可用工具。
  1. 开销
  • HTTP:http 头、cookie 等头部开销大。
  • MCP:二进制 / 流式 json,头部少,多次调用开销更低。
  1. 认证
  • HTTP:header token、cookie、oauth2。
  • MCP:支持 transport 层认证(ws token、stdio 环境变量),协议本身不强制。

简单总结:HTTP 适合通用微服务;MCP 面向 AI 工具调用,长连接 + JSON‑RPC,支持并行调用,专为模型工具交互设计。


3. 系统之间认证怎么做(服务间认证)

  1. Token 方式(JWT)服务 A 生成 jwt,放到请求头传给服务 B;B 校验签名。适合网关、跨服务。缺点:无法主动作废 token。

  2. OAuth2.0 客户端凭证模式 Client Credentials服务账号,专门用于服务与服务之间,拿 access_token 访问资源服务。适合多微服务。

  3. API Key简单,请求头放 api‑key,服务端校验 key,配置在配置中心。适合第三方调用,缺点密钥泄露风险。

  4. mTLS 双向 TLS双方都持有证书,握手阶段互相校验证书。安全高,适合内网核心服务,运维重。

  5. Spring Cloud Alibaba 微服务体系:Sentinel + Nacos 元信息 + token 透传内网服务也可以网关统一鉴权。

  6. MCP 场景:transport 层携带密钥,ws url 带 token,或者环境变量传密钥。

区分:

  • 用户登录认证:面向人;
  • 服务间认证:机器对机器,不需要用户参与

4.InnoDB 索引结构

InnoDB 索引是B + 树

  1. B + 树所有数据都在叶子节点;非叶子节点只存索引键 + 页号,用于路由查找。
  2. 主键索引(聚簇索引):叶子节点保存完整行数据;表数据本身就是按主键 B + 树组织。
  3. 二级索引(普通索引):叶子节点存索引列 + 主键值,不存完整行。查到主键之后再去主键索引拿完整行,就是回表
  4. 页: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. 索引失效常见场景

  1. 索引列做运算、函数、隐式类型转换where substr(name,1,1)='a'/where str='123'字段是 int
  2. like 以通配符开头like '%abc'
  3. or 一边条件没有索引
  4. not in、!=、is not null 不一定失效,要看数据分布,不能直接说一定失效
  5. mysql 优化器判断全表扫描比走索引更快,放弃索引。数据量占比大的时候触发。
  6. 联合索引不满足最左前缀原则。

注意: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。大量这种请求压垮数据库。

解决方案:

  1. 缓存空值(缓存存 null,设置短过期时间)
  2. 布隆过滤器,拦截不存在 key,直接返回,不去查缓存、DB。

布隆过滤器原理

bit 数组 + 多个 hash 函数组成。

  1. 存入 key:key 经过 N 个不同 hash 函数,算出 N 个 bit 下标,把对应 bit 位置 1。
  2. 查询 key:同样 N 次 hash,如果所有对应 bit 位都是 1 →可能存在;只要有一个 bit 是 0 →一定不存在

特点:

  • 存在误判率:判定存在实际可能不存在;不会漏判
  • 不支持删除元素(删除会影响其他 key),一般用计数布隆过滤器解决删除。
  • 占用内存很小,适合海量数据做存在性判断。

缓存击穿:热点 key 过期,大量请求打数据库;缓存雪崩:大量 key 同时过期,redis 宕机。

8. 批量导入:Redisson 分布式锁 + 先更新库后延迟删缓存;其他解决方案

场景:人员信息批量导入,多线程并发修改同一组织节点,权限树错乱;方案:Redisson 分布式锁 + 先更新数据库,延迟删除缓存保证最终一致性。

先回顾:先更新数据库,再删除缓存

问题:更新成功,删除缓存失败 → 缓存旧数据,数据不一致。用延迟双删:更新 DB → 删除缓存 → 休眠一小段时间,再删一次缓存。Redisson 锁保证同一组织节点串行执行。

除 Redis 分布式锁之外,解决并发修改同一资源,防止错乱的方案:

  1. 数据库乐观锁(version 版本号)表增加 version 字段;更新时update xxx set ... version=version+1 where id=#{id} and version=#{oldVersion};更新行数 0 代表已经被别人修改,捕获异常重试。不需要锁,适合并发冲突不多场景。缺点大量冲突会大量重试。

  2. 数据库悲观锁select ... for update行锁。事务内锁住这行,其他线程阻塞。 缺点:数据库压力大,长事务容易死锁,不适合高并发批量导入。

  3. 业务层队列,按组织 ID 分片队列同一个组织节点的所有导入任务投递到同一个队列,单线程消费。天然串行,无锁。Kafka/RabbitMQ。适合批量导入,削峰。

  4. 数据库唯一约束如果业务可以,利用唯一索引避免重复脏写。

  5. Zookeeper 分布式锁临时有序节点实现分布式锁,可靠性高,性能比 Redis 差。

选型对比: 冲突少优先乐观锁;批量任务可以消息队列串行;高并发争抢用 Redis 分布式锁;强一致性可以 zk 锁。

注意:分布式锁只能解决并发写错乱;不能彻底解决缓存 DB 不一致,还是依赖延迟双删、MQ 重试删除缓存

9.IOC 和 AOP

IOC(控制反转 Inversion of Control)

  1. 控制反转:把对象创建、依赖交给 Spring 容器,而不是自己 new 对象。
  2. DI 依赖注入是 IOC 实现方式:构造器注入、setter 注入、字段 @Autowired 注入。
  3. 好处:解耦,便于单元测试,容器统一管理生命周期。
  4. Bean 的生命周期:实例化 → 属性填充 →初始化 →销毁。

AOP(面向切面编程 Aspect‑Oriented Programming)

通用横切逻辑抽离出来:日志、权限校验、事务、限流、埋点,不和业务代码耦合。

  • 底层两种代理: 1)JDK 动态代理:实现接口的类,生成接口代理对象。 2)CGLIB 代理:继承目标类生成子类,类没有实现接口时使用。SpringBoot 默认 CGLIB。

AOP 概念:

  • 切面 Aspect:通知 + 切点
  • 切点 Pointcut:匹配哪些类哪些方法
  • 通知 Advice:执行逻辑 @Before @After @AfterReturning @AfterThrowing @Around
  • 连接点 JoinPoint:被拦截到的方法。

@Around 环绕通知功能最强,可以控制目标方法要不要执行。