25年11月它思科技 Java开发 二面

#JAVA##JAVA面经##JAVA内推#

1. 项目中你负责的模块如何保证接口的幂等性?

回答思路

  • 核心锚定:幂等性核心是「同一请求多次执行结果一致」,需按请求类型+业务场景选择方案,核心逻辑是「唯一标识+状态校验+防重拦截」;
  • 分层拆解方案(按场景适配)
    1. 读接口:天然幂等,无需额外处理;
    2. 写接口(如订单创建、支付回调)
      • 方案1:唯一请求ID(幂等号)+ Redis防重锁
        • 流程:前端/网关生成唯一requestId,接口接收后先通过SET requestId 1 NX EX 300加锁,成功则执行业务,失败则返回重复请求;
      • 适用场景:短链接、支付回调等一次性请求;
      • 项目落地:订单创建接口,requestId关联用户ID+订单业务号,Redis锁有效期覆盖业务最大处理时长;
      • 核心:NX保证只有一次执行,EX防止死锁;
    3. 写接口(如库存扣减)
      • 方案2:业务唯一键+数据库唯一索引
        • 流程:以「用户ID+商品ID+活动ID」为唯一键创建数据库唯一索引,重复插入时触发主键冲突,捕获异常并返回“操作已执行”;
      • 适用场景:有明确业务唯一标识的场景;
    4. 状态机控制
      • 流程:针对有状态流转的业务(如订单:待支付→已支付→已完成),执行业务前校验当前状态,仅允许合法状态流转(如已支付订单不允许重复扣减库存);
  • 核心结论:核心是「唯一标识拦截重复请求 + 业务状态校验防止重复处理」,按场景选择Redis防重锁/数据库唯一索引/状态机。

标准答案

我负责的订单模块按场景分层保证幂等:① 支付回调接口:用网关生成的唯一requestId作为幂等号,接口层先通过Redis SET requestId 1 NX EX 300加防重锁,成功则执行业务,失败则返回重复请求;② 订单创建接口:以「用户ID+商品ID+活动ID」为业务唯一键,创建数据库唯一索引,重复插入触发主键冲突时,捕获异常并返回“订单已创建”;③ 库存扣减接口:增加状态机校验,仅当订单处于“待支付”状态时允许扣减,已支付/已取消状态直接拒绝。核心逻辑是「唯一标识拦截重复请求 + 业务状态校验防止重复处理」,确保同一请求多次执行结果一致。

2. 高并发场景下,如何解决数据库读写性能瓶颈?

回答思路

  • 核心锚定:数据库瓶颈核心是「读多写少/写多读少」,解决方案围绕「读写分离+缓存+分库分表+SQL优化」,按“先缓存→再分离→最后分库分表”的优先级落地;
  • 分层拆解方案
    1. 读性能优化(核心:减轻数据库读压力)
      • 缓存层:热点数据(如商品详情、用户信息)接入Redis,设置合理过期时间+缓存预热+缓存击穿/穿透/雪崩防护;
      • 读写分离:主库写、从库读,通过中间件(MyCat/Sharding-JDBC)实现读写路由,从库可水平扩容;
      • 只读实例:针对超高频读场景,部署多个只读实例,分摊读压力;
    2. 写性能优化(核心:减少写冲突+提升写效率)
      • 分库分表:按用户ID/订单ID哈希分片,拆分大表为小表,减少单表数据量和锁竞争;
      • 批量写入:将高频小批量写入(如日志、埋点)改为批量提交,减少事务次数和IO;
      • 异步写入:非核心数据(如订单日志)通过MQ异步写入,降低接口响应时间;
    3. 基础优化(兜底)
      • SQL优化:避免大表全扫、优化JOIN、控制返回字段;
      • 数据库参数调优:增大InnoDB Buffer Pool、优化日志刷盘策略;
  • 核心结论:先通过缓存扛读压力,再读写分离扩展读能力,最后分库分表解决写瓶颈,配合基础优化兜底。

标准答案

高并发下数据库读写瓶颈按“先轻量后重度”解决:① 读瓶颈:热点数据接入Redis缓存(设置过期时间+布隆过滤器防穿透),主从分离(主库写、多从库读),通过MyCat实现读写路由;② 写瓶颈:按用户ID哈希分库分表拆分大表,高频小写入改为批量提交,非核心数据通过MQ异步写入;③ 基础优化:优化慢SQL(避免全表扫描、控制JOIN表数),调大InnoDB Buffer Pool提升缓存命中率。核心逻辑是“缓存扛读、分库分表扛写、读写分离扩容量”,优先用轻量方案(缓存),再用架构方案(分库分表)。

3. JDK 动态代理与 CGLIB 动态代理的底层实现差异是什么?

回答思路

  • 核心锚定:差异核心是「代理对象创建方式+目标类依赖」,JDK基于接口,CGLIB基于继承;
  • 分层拆解差异
    维度 JDK 动态代理 CGLIB 动态代理
    底层原理 反射机制,生成实现目标接口的代理类 ASM字节码框架,生成目标类的子类
    目标类要求 必须实现接口 无需实现接口,不能代理final类/方法
    代理对象创建 Proxy.newProxyInstance() 创建代理实例 Enhancer.create() 创建子类实例
    方法调用 通过InvocationHandler.invoke() 拦截 通过MethodInterceptor.intercept() 拦截
    性能 反射调用,创建快、执行稍慢 字节码生成,创建慢、执行稍快
  • 核心结论:JDK代理依赖接口,基于反射;CGLIB代理基于继承,基于ASM字节码,两者拦截方式和性能特性不同。

标准答案

JDK动态代理与CGLIB的核心差异:① 底层原理:JDK基于反射,生成实现目标接口的代理类;CGLIB基于ASM字节码框架,生成目标类的子类;② 目标类要求:JDK要求目标类必须实现接口,CGL

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏

全部评论

相关推荐

03-11 20:19
已编辑
门头沟学院 Java
太压力了,面了2个多小时,本菜比已经被拷打的瑟瑟发抖面完两个小时后通知过了1.算法题三道(1)leetcode124 二叉树中最大路径和hard题 因为不久前才刷过撕出来了,又来了一道(2)leetcode 300 最长递增子序列变种除了递增之外还加了一个权重因素,但是思路没变,dp就行(3)寻找词汇库里符合固定长度前缀的匹配单词应该是他们自己题库的题。给了一串单词列表,然后又给了一个单词,一个下标,根据这个下标的前缀去单词列表里面找到所有匹配的单词再返回思路是创建一个单词前缀树,然后根据树找,但是可能是构件树数有问题没撕出来2.全方位项目拷打基本没有问八股,全部都是项目企业场景题,哎哟我操,完全不会。我就纯八股战士,结果没想到一道八股都没问反正尽可能把企业场景往八股上引吧。。1. 微服务多点部署其中一个宕机了怎么办2. 要是mq占据大量CPU该怎么排查?MySQL占据大量CPU该怎么排查?3. 假如说让你实现视频点赞功能,你打算怎么设计?讲讲思路(我知道多级缓存,但是碰巧没背……寄)4. Redis延迟双删是什么,分布式锁,哨兵模式5. MySQL到es同步的延迟该怎么优化6. Rabbit mq的队列是怎么实现的?(这个完全没整明白,可能是队列的底层结构? 反正我硬扯的讲了一下rabbit mq的架构)还扯了很多,但是往后完全就慌了),记住的是这些
不知道怎么取名字_:2小时确实有压力,持续性的脑力劳动啊
查看9道真题和解析
点赞 评论 收藏
分享
评论
1
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务