面灵AI→

顺丰 Java 二面:二级缓存一致性、分布式锁与类加载

轮次
二面
时间
2026-10
来源
牛客网

《面试题目》

  1. 你实习中第一个项目跑一次一般需要多久?
  2. 项目使用 Caffeine + Redis 二级缓存,如何保证缓存与数据库一致性?
  3. Redisson 分布式锁和单纯使用 SETNX 实现锁,二者有什么区别?
  4. 除了滑动窗口 + 摘要压缩管理 LLM 上下文,还有哪些记忆方案?
  5. 把上下文压缩交给大模型侧执行存在什么问题?该怎么解决?
  6. 能不能自定义一个和 JDK 中包名、类名完全一样的类?能不能自定义和 Redis 三方依赖包名、类名完全一样的类?这两种类能不能被加载?
  7. 定义 JDK 中类名完全一样的类,会抛出什么错误?是编译期、运行期还是其他阶段?

《参考解析》

二级缓存一致性:Caffeine 是进程内缓存,Redis 是分布式缓存,两者叠加后一致性难度更高。常用做法是 Cache Aside:读本地 → 读 Redis → 回源数据库,写路径先更新数据库,再删除 Redis,最后通过广播/消息让各实例删除本地缓存。只删缓存不更新缓存,能减少并发写导致的旧值覆盖。对强一致要求高的数据,不要放本地缓存,或者给本地缓存设很短的 TTL 并接受短暂不一致。延迟双删只能降低概率,不能证明强一致;真正的兜底是版本号、binlog 订阅或读时校验。

Redisson 与 SETNX:裸 SET NX EX 只解决「互斥 + 过期」,释放锁要 Lua 比对 value,续期要自己实现,拿不到锁要自己轮询。Redisson 在这些基础上提供了可重入、看门狗续期、阻塞等待、公平锁、读写锁和 RedLock 等能力,封装了锁续期和释放的原子性。代价是依赖更重、行为更复杂,排查时要看 Redis 里的锁结构。答题时补一句:无论用哪种,业务侧都要幂等,因为锁可能因超时、主从切换或网络分区失效。

LLM 记忆:除了滑动窗口和摘要压缩,还可以做分层记忆:短期保留最近对话,长期把事实、偏好、任务状态抽成结构化条目,按重要性/时间衰减检索;用向量库存语义记忆,用关系库存用户画像和业务状态;对工具调用结果做摘要和引用,原始内容落对象存储。压缩交给模型侧的问题是:模型可能丢关键约束、产生幻觉、不可复现,且每次压缩都花 token。更稳的是规则先行(保留系统提示、最近 N 轮、未完成任务、用户显式约束),模型只做摘要,摘要结果可回查原文。

类加载:自定义 java.lang.String 这类 JDK 核心类,编译期在模块化 JDK 下就可能报「package exists in another module: java.base」;即使绕过编译,JVM 在定义类时会做包名保护,抛 SecurityException: Prohibited package name: java.lang。自定义和第三方依赖同包同名的类,双亲委派下会先加载父加载器里的版本,自定义类不会被加载;如果自定义类加载器破坏双亲委派,可能出现两个同名类,互转时抛 ClassCastException 或 LinkageError。所以结论不是「能不能写」,而是「写了也未必按你以为的那个类生效」。