Java高频面试考点场景题17

从点击按钮到数据库落库,数据都经历了哪些险境

接入层:需通过限流(令牌桶 / 漏桶算法)和熔断(断路器状态机流转)抵御流量冲击,防止下游服务被拖垮。

业务层:扣库存需根据读写比例选择乐观锁或悲观锁,预扣库存可通过 Redis 的 DECR 命令优化;幂等性需结合数据库唯一索引与分布式锁实现。

中间件:引入消息队列异步处理请求,需解决消息丢失、重复消费和积压问题,如开启生产者确认、消费者手动 ACK、临时扩容消费者实例。

存储层:分库分表需选择合适分片键(如用户 ID 哈希),ID 生成需用雪花算法,并说明其组成结构及时钟回拨的应对方案。

回答需分环节拆解风险与对策,体现全链路抗风险能力。

视频讲解了每秒 10w QPS 的爆火视频点赞导致数据库行锁卡死的解决方案及底层逻辑。

  • 问题根源解析:InnoDB 引擎执行 UPDATE 语句需获取排它 X 锁,10 万并发请求排队获取锁,会使操作系统上下文切换频繁、MySQL 死锁检测压力剧增,CPU 利用率飙至 100%,吞吐量跌到个位数。
  • 常规方案局限:仅用 Redis 原子递增加 MQ 异步写库,会出现 Redis 单机达到物理极限、MQ 消费者逐条更新仍导致数据库行锁排队的问题,只是推迟故障时间。
  • 端侧本地缓冲:在 Web Server 内存开辟 200ms 时间窗口,用 AtomicLong 合并器将窗口内的散点点赞合并为单次批量请求,从源头减少 RPC 调用频率。
  • Redis 热点拆分:借鉴 LongAdder 空间换时间思想,将单个视频 ID 拆分为多个子 Key 分片,按用户 ID 取模分流请求,每个分片仅承担 1w QPS,查询时求和所有分片数据。
  • 消费端批量写合:在 MQ 消费端搭建内存聚合引擎,按视频 ID 累加点赞数,最终仅向数据库执行一条合并后的 SQL,使加锁频率骤降三个数量级,终结行锁竞争。

满分方案为端侧聚合、缓存分片、批量写合的四位一体架构,配合定期快照与 Binlog 日志保障最终一致性与宕机恢复。

秒杀场景下仅靠前端防抖无法彻底解决恶意请求问题。

前端层:通过按钮置灰或防抖函数拦截普通用户因网络卡顿产生的重复请求,成本低但无法防脚本。

网关层:在 Nginx 层面配置 IP 频次限流,限制同一 IP 单位时间内的请求量,过滤机器脚本流量。

业务层:基于 Redis 原子计数器实现 UID 维度限流,同一账号单位时间内仅允许一次有效请求,避免多线程并发问题。

兜底层:通过 Redis 分布式锁(以用户 ID 和商品 ID 为 key)和数据库联合唯一索引,防止重复下单,保证数据一致性。视频详细拆解了四层漏斗模型的具体实现逻辑。

使用 Executors 工具类创建线程池可能导致内存溢出,手动配置 ThreadPoolExecutor 需结合业务场景动态调优。

Executors 工具类的问题:视频指出 Executors 创建的线程池使用无界队列(如 LinkedBlockingQueue 默认无界),任务提交速度超过处理速度时会导致队列无限增长,最终引发内存溢出。

ThreadPoolExecutor 核心参数:视频列出 7 个核心参数,包括核心线程数、最大线程数、任务队列、存活时间、线程工厂、拒绝策略等,强调必须明确所有参数。

动态调优方法:视频提到可通过配置中心(如 Apollo、Nacos)监听配置变更,调用 setCorePoolSize、setMaximumPoolSize 等方法实现运行时动态调整,应对流量波动。

监控告警:视频建议监控线程池指标(如活跃线程数、队列积压任务数),通过定时任务或 Prometheus+Grafana 实现可视化监控和告警。

视频通过面试场景展示了线程池配置的常见误区,并提供了从参数理解到动态调优的完整解决方案。

三年经验的后端候选人在 MySQL 死锁场景题中完全卡壳。

问题暴露:视频指出该现象反映部分资深工程师缺乏数据库并发问题的系统化处理能力。

面试官期待:针对线上死锁问题,面试官期待的排查解决步骤包括查看死锁详情、检查事务设计、审视索引设计、业务层并发控制、调整事务隔离级别。

能力要求:视频强调 3-5 年开发者应具备数据库深层调优能力,熟练使用死锁日志分析工具。

建议方向:视频建议建立数据库问题清单,将常见并发场景处理流程标准化。

视频提到收集了生产环境中的数据库问题及解决思路,可提供给粉丝学习借鉴。

Java 开发面试中被问及设计模式时,单纯背诵模式定义是错误回答。

错误回答特征:直接罗列单例、工厂、策略等模式名称并解释定义,会被面试官判定为不合格。

正确回答逻辑:需结合真实业务场景,说明问题、选择模式的原因及落地方式。

消息通知场景案例:以消息通知系统(短信、邮件、站内信等多渠道)为例,先通过策略模式定义统一接口,实现调用方与具体渠道解耦;再通过模板方法在抽象类中固定 "校验 - 发送 - 记日志" 流程,仅开放校验和发送步骤给渠道实现类;最后通过简单工厂扫描带渠道标识的注解类,实现调用时的动态路由。

模式区别:模板方法强调流程复用,仅开放部分步骤;策略模式强调行为切换,允许整体实现替换。

视频指出消息通知、导出报表等场景均适用该组合策略,能有效证明项目经验。

相关推荐
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
此时不提桶,更待何时3 天前
01-06-A-JVM排查实战详解
java·jvm
伞伞悦读3 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
晨米酱3 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
C语言小火车3 天前
C/C++ 为什么需要编译器?
开发语言·c++
AI产品测评官3 天前
海内外AI招聘工具分赛道横向对比:五大品类的技术路线与选型参考
人工智能·ai·求职招聘
霍霍的袁3 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
彧azz3 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
孙启超3 天前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int3 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++