Java高频面试考点场景题22

生产环境中使用 InheritableThreadLocal(ITL)处理线程池场景的 userId 传递,不仅无法解决问题,还会引发脏读事故。

数据丢失根源:主线程与异步线程存在内存隔离,若未显式桥接,数据无法跨线程传递,导致子线程读取 userId 为空。

ITL 的致命缺陷:在线程池复用机制下,ITL 仅在新建线程时复制主线程数据,复用线程时不会触发复制逻辑,导致新任务读取到旧任务的残留数据,引发脏读。

TTL 解决方案:通过阿里开源的 TransmittableThreadLocal(TTL)的 CRR 模式(Capture 捕获、Replay 重放、Restore 恢复),在任务提交时捕获上下文,执行前重放覆盖脏数据,执行后恢复线程状态,避免污染后续任务。

无侵入落地:采用 Java Agent 字节码增强技术,自动将普通任务包装为 TtlRunnable,业务层无需修改代码即可实现上下文自动流转。

视频明确指出,解决线程池场景下 userId 传递问题的核心是使用 TTL 的 CRR 模式。

五年经验的后端求职者因对数据库连接池原理的理解不足,导致面试回答无法应对实际事故场景。

事故场景:某系统将数据库连接池最大连接数从 50 调至 200 后,数据库连接数爆满、CPU 使用率达 100%,系统瘫痪。

核心问题:连接池并非越大越好,每个连接会占用数据库资源,连接数过大会导致上下文切换频繁、锁冲突放大,反而降低性能。

优化四层设计:

连接池原理:核心是复用连接,最佳连接数需根据核心线程数、等待时间和处理时间计算(公式为核心线程数 × 等待时间 ÷ 处理时间)。

数据库并发能力:PostgreSQL 每个连接占用 10-20MB 内存,200 个连接需 4GB 内存;高连接数会放大行锁、表锁冲突,有效并发可能低于 50。

连接池配置:需调整最小空闲连接、连接超时、空闲连接回收、连接生命周期等参数,不能仅调最大连接数。

监控与告警:通过 Prometheus+Grafana 监控活跃连接数、等待线程数、连接获取时间等指标,提前发现异常。

视频强调连接池配置需结合业务模型、数据库能力和监控数据科学调整。

京东零售 T7 架构题中,直接用动态规划解决优惠券组合问题会因状态爆炸被面试官淘汰。

业务筛选:通过漏斗图过滤过期、类目不匹配、未到时间的无效券,将 100 张券压缩至 20 张左右有效券。

算法优化:放弃动态规划(状态维度爆炸),采用回溯法结合图论降维(拆分连通孤岛)和支配剪枝(去除劣质券),降低计算复杂度。

工程落地:通过零 GC(用 long 类型、索引遍历避免 Young GC)、BitMap 位运算(互斥判断)、线程策略(巨型任务用 ForkJoinPool)、动静分离(规则引擎前置)等手段保证 200ms 内响应。

视频指出该题核心考察架构师对业务、底层和工程落地的综合能力。

候选人对 MQ 消费失败的回答仅停留在表面,未覆盖真实系统设计的核心问题。

候选人回答:消费失败时通过抛异常重试,多次失败后记录日志人工排查;针对重复投递,提出通过订单判断是否已处理。

核心问题:真实系统需解决消息不丢失、避免重复消费导致业务错误两个核心问题。

完整设计:采用三层机制,包括设置最大重试次数的自动重试、兜底的死信队列、保证幂等的业务逻辑(如通过订单 ID 判断是否已处理)。

视频明确指出真实系统需结合重试、死信队列和业务幂等三层机制。

仅依赖组件名称无法真正解决微服务雪崩问题,系统防护需完整治理体系。

依赖治理:通过 SkyWalking、Zipkin 等工具绘制服务调用拓扑图,区分核心服务(订单、支付)与非核心服务(积分、推荐),实现依赖隔离。

熔断器机制:需理解关闭、打开、半开三态逻辑,配置失败率阈值触发熔断,通过休眠窗口尝试恢复服务。

隔离策略:根据调用场景选择线程池隔离(适合慢调用)或信号量隔离(适合高并发快调用),主流工具为 Resilience4j 或 Sentinel。

动态监控:通过 Grafana 可视化 QPS、RT、错误率等指标,结合 Nacos、Apollo 配置中心实时调整熔断参数。

服务治理需从依赖、熔断、隔离、监控四个维度构建完整防护体系。

MySQL 索引失效的核心原因可归纳为一个 "变" 字,即让原本有序的索引变得无序或需要先计算结果才能查找。

三大忌

对索引列做运算或加函数,导致数据库无法直接使用索引,需全表计算。

模糊查询用百分号开头,类似字典按首字排序却查尾字,只能全表扫描。

隐式类型转换,如字符串字段用数字查询,系统会转换索引列导致失效。

两个坑

联合索引不符合最左前缀原则,跳过首字段会使后续字段无序,无法使用索引。

乱用 or 连接条件,若其中一个字段无索引,数据库会放弃所有索引进行全表扫描。

视频最后提出思考题:如何判断查询是否走索引。

相关推荐
虚无的纽扣7 分钟前
【力扣刷题】第五天:将 x 减到 0 的最小操作数、最大连续1的个数 III
算法·leetcode·职场和发展
qetfw12 分钟前
Bash 内置与外部命令:type、command 与 builtin 验证
linux·开发语言·bash
Dovis(誓平步青云)15 分钟前
车辆进入隧道后信号断开,座舱旅程怎样补回事件
java·开发语言·前端·数据库·电脑
砚底藏山河16 分钟前
数据新鲜度 SLA 监控
java·大数据·python·maven
Wzx19801220 分钟前
Python Agent 短期记忆设计:从对话历史到 LangGraph Checkpointer
开发语言·python
gopher951135 分钟前
RUST:错误处理 thiserror 详解
开发语言·后端·rust
杨杨杨大侠9 小时前
都能接模型、RAG 和 MCP,Java Agent 框架到底差在哪?
java
破茧蝴蝶9 小时前
Python分布式爬虫完整教程
开发语言·python
狗凯之家源码网9 小时前
全新 PHP 轻量客服聊天室源码深度评测
开发语言·php·聊天室系统
远离UE410 小时前
UE5 Substrate Thin Film 源码拆析
开发语言·javascript·ue5