
Java大厂面试实录谢飞机的奇幻面试之旅场景设定某互联网大厂会议室严肃的面试官对面坐着略显紧张的程序员谢飞机。今天面试的岗位是高级Java开发工程师主要面向电商与内容社区业务。第一轮基础夯实与业务理解面试官谢飞机你好欢迎参加今天的面试。我们先从基础开始。假设我们正在构建一个电商平台的商品详情页日PV达到千万级别。问题1你会如何设计商品缓存方案请说明选择的技术栈和理由。谢飞机清了清嗓子这个简单用Redis啊商品数据读多写少放Redis里查询快。设置个过期时间比如30分钟过期了就重新从数据库加载。Service public class ProductService { Autowired private RedisTemplateString, Object redisTemplate; Autowired private ProductMapper productMapper; public Product getProductById(Long productId) { String key product: productId; Product product (Product) redisTemplate.opsForValue().get(key); if (product null) { // 缓存未命中查询数据库 product productMapper.selectById(productId); if (product ! null) { // 设置过期时间30分钟添加随机值防止缓存雪崩 redisTemplate.opsForValue().set(key, product, 30 new Random().nextInt(10), TimeUnit.MINUTES); } } return product; } }面试官点头不错提到了缓存雪崩的预防。那如果商品库存需要实时扣减你如何处理缓存与数据库的一致性谢飞机稍显犹豫嗯...先更新数据库再删除缓存或者用...用那个消息队列异步更新面试官微笑方向是对的。我们继续。问题2在内容社区场景下用户发布的内容需要敏感词过滤。你会如何实现考虑性能和高并发。谢飞机来了精神这个我熟用DFA算法确定有限自动机把敏感词建成树结构匹配速度快。可以放在本地缓存如Caffeine避免每次都查Redis。Component public class SensitiveWordFilter { private final TrieNode root new TrieNode(); private final LoadingCacheString, Boolean wordCache CacheBuilder.newBuilder() .maximumSize(10000) .expireAfterWrite(10, TimeUnit.MINUTES) .build(new CacheLoaderString, Boolean() { Override public Boolean load(String word) { return isSensitive(word); } }); public boolean containsSensitiveWord(String text) { TrieNode current root; for (int i 0; i text.length(); i) { char ch text.charAt(i); if (current.children.containsKey(ch)) { current current.children.get(ch); if (current.isEnd) { return true; } } else { current root; } } return false; } }面试官赞许DFA算法确实高效。那如果敏感词库有上万个词如何动态更新而不影响线上服务谢飞机挠头这个...可以双缓冲或者...热加载面试官记录笔记好我们进入下一个问题。问题3电商大促期间秒杀系统如何防止超卖请从数据库锁、分布式锁、队列等角度说明。谢飞机自信满满这个经典可以用数据库乐观锁Update(UPDATE product_stock SET stock stock - 1 WHERE product_id #{productId} AND stock 0) int deductStock(Param(productId) Long productId);或者用Redis分布式锁public boolean seckill(Long productId, Long userId) { String lockKey seckill:lock: productId; RLock lock redissonClient.getLock(lockKey); if (lock.tryLock(0, 10, TimeUnit.SECONDS)) { try { // 检查库存、下单等逻辑 return orderService.createOrder(productId, userId); } finally { lock.unlock(); } } return false; }还可以用消息队列削峰填谷...面试官打断停你说到了关键点。但Redis分布式锁和数据库锁各自适用什么场景谢飞机含糊呃...看情况数据一致性要求高的用数据库锁性能要求高的用Redis面试官微笑行第一轮先到这里。第二轮微服务架构与高可用面试官现在我们聊聊微服务。假设我们的电商平台拆分成用户、商品、订单、支付等多个服务。问题4服务间调用如何保证可靠性如果订单服务调用支付服务超时了怎么办谢飞机稍微紧张用...用Feign加熔断器Resilience4j或者HystrixService public class OrderService { Autowired private PaymentClient paymentClient; CircuitBreaker(name paymentService, fallbackMethod paymentFallback) TimeLimiter(name paymentService) public CompletableFuturePaymentResponse processPayment(Order order) { return CompletableFuture.supplyAsync(() - paymentClient.pay(order.getPaymentRequest()) ); } public CompletableFuturePaymentResponse paymentFallback(Order order, Throwable t) { // 降级逻辑记录日志发送告警返回默认结果 log.error(支付服务调用失败, t); return CompletableFuture.completedFuture(new PaymentResponse(false, 支付服务繁忙请稍后重试)); } }配置熔断参数...超时时间...面试官点头Resilience4j的配置参数有哪些熔断器状态如何转换谢飞机眼神飘忽有...有失败率阈值、等待时间、滑动窗口...状态是关闭、打开、半开面试官记录大致正确。继续。问题5分布式事务如何处理比如下单后需要扣减库存、创建订单、增加积分这三个操作如何保证一致性谢飞机开始冒汗这个...可以用Seata的AT模式或者...消息队列的最终一致性// TCC模式示例 TwoPhaseCommitTxn public class InventoryService { Prepare public void tryDeduct(Long productId, Integer count) { // 预留库存 inventoryMapper.freezeStock(productId, count); } Commit public void confirmDeduct(Long productId, Integer count) { // 确认扣减 inventoryMapper.deductStock(productId, count); } Rollback public void cancelDeduct(Long productId, Integer count) { // 回滚预留 inventoryMapper.unfreezeStock(productId, count); } }或者用本地消息表定时任务...面试官追问Seata的AT模式和TCC模式有什么区别各自适用什么场景谢飞机支支吾吾AT是...自动的TCC要手动写三个阶段AT适合...简单的TCC适合...复杂的面试官不置可否行下一个问题。问题6系统监控如何做如何快速定位线上问题谢飞机放松了些这个我用过PrometheusGrafana监控指标ELK收集日志SkyWalking或者Zipkin做链路追踪。# application.yml management: endpoints: web: exposure: include: health,metrics,prometheus metrics: export: prometheus: enabled: true自定义业务指标Component public class CustomMetrics { private final MeterRegistry meterRegistry; private final Counter orderCounter; public CustomMetrics(MeterRegistry meterRegistry) { this.meterRegistry meterRegistry; this.orderCounter Counter.builder(order.created) .description(订单创建数量) .register(meterRegistry); } public void recordOrder() { orderCounter.increment(); } }面试官如果某个接口响应时间突然变慢你如何排查谢飞机不太确定看...看链路追踪找耗时长的环节然后看日志面试官微笑思路对。第二轮结束。第三轮云原生与前沿技术面试官最后一轮聊聊云原生和新技术。问题7我们的服务要部署到KubernetesDockerfile和K8s配置需要注意什么谢飞机努力回忆Dockerfile要用多阶段构建减小镜像大小。K8s要配置资源限制、健康检查...# 多阶段构建 FROM maven:3.8-openjdk-17 AS build COPY . /app RUN mvn package -DskipTests FROM openjdk:17-slim COPY --frombuild /app/target/*.jar /app/app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, /app/app.jar]# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: order-service spec: replicas: 3 template: spec: containers: - name: order-service image: order-service:latest resources: limits: memory: 512Mi cpu: 500m livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 10面试官点头HPA自动扩缩容如何配置谢飞机含糊根据...CPU和内存使用率设置阈值...面试官继续。问题8现在AIGC很火如果要在内容社区集成AI生成内容技术架构如何设计谢飞机眼睛一亮这个我研究过可以调用大模型API或者自己部署模型。需要异步处理用消息队列...Service public class AIGCService { Autowired private KafkaTemplateString, String kafkaTemplate; public String generateContent(String prompt) { // 发送请求到消息队列 kafkaTemplate.send(aigc-request, prompt); // 异步获取结果 return 内容生成中请稍后查看; } KafkaListener(topics aigc-response) public void handleResponse(String result) { // 处理生成结果通知用户 notifyUser(result); } }还要做内容审核、限流...面试官追问如何控制AI生成内容的成本如何保证生成质量谢飞机开始胡扯成本...可以缓存相似请求的结果质量...可以人工审核或者...用另一个AI来审核面试官挑眉最后一个问题。问题9如果让你设计一个支持千万并发的直播弹幕系统你会如何架构谢飞机彻底懵了千万并发...用...用WebSocket消息队列...Redis发布订阅...分片...ServerEndpoint(/danmaku/{roomId}) public class DanmakuEndpoint { private static final ConcurrentHashMapString, SetSession roomSessions new ConcurrentHashMap(); OnOpen public void onOpen(Session session, PathParam(roomId) String roomId) { roomSessions.computeIfAbsent(roomId, k - ConcurrentHashMap.newKeySet()) .add(session); } OnMessage public void onMessage(String message, PathParam(roomId) String roomId) { // 广播给同房间所有用户 roomSessions.get(roomId).forEach(session - { try { session.getBasicRemote().sendText(message); } catch (IOException e) { log.error(发送弹幕失败, e); } }); } }但是千万并发...可能需要...分层架构边缘节点面试官合上笔记本好了今天就到这里。面试官谢飞机你的基础还不错对一些常用技术有实践经验。但在分布式事务、系统深度优化等方面还需要加强。我们会综合评估后在3个工作日内通知你面试结果。请保持手机畅通。谢飞机起身好的好的谢谢面试官技术详解与答案解析问题1商品缓存方案业务场景电商商品详情页日PV千万级读多写少需要高性能读取。技术要点Redis选择理由内存存储读取速度快微秒级支持丰富数据结构支持持久化和集群缓存策略Cache-Aside模式先查缓存未命中再查数据库设置随机过期时间防止缓存雪崩热点数据可以永不过期缓存一致性方案先更新数据库再删除缓存保证最终一致性延迟双删更新数据库后立即删缓存延迟500ms再删一次消息队列异步更新数据库变更后发送消息消费者更新缓存Canal监听binlog实时同步数据库变更到缓存// 延迟双删实现 Transactional public void updateProduct(Product product) { productMapper.update(product); redisTemplate.delete(product: product.getId()); // 延迟双删 CompletableFuture.runAsync(() - { try { Thread.sleep(500); redisTemplate.delete(product: product.getId()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); }问题2敏感词过滤业务场景内容社区用户生成内容(UGC)需要实时过滤敏感词。技术要点DFA算法优势时间复杂度O(n)与敏感词数量无关适合大量敏感词场景性能优化本地缓存Caffeine减少网络开销敏感词库分版本支持热更新布隆过滤器预判断是否存在敏感词动态更新方案双缓冲机制准备新词库原子切换引用配置中心推送变更通知定时任务定期拉取最新词库// 双缓冲实现 public class SensitiveWordManager { private volatile TrieNode currentTrie; private final ReadWriteLock lock new ReentrantReadWriteLock(); public void updateWordList(ListString newWords) { TrieNode newTrie buildTrie(newWords); lock.writeLock().lock(); try { this.currentTrie newTrie; } finally { lock.writeLock().unlock(); } } public boolean filter(String text) { lock.readLock().lock(); try { return containsSensitiveWord(text, currentTrie); } finally { lock.readLock().unlock(); } } }问题3秒杀防超卖业务场景电商大促秒杀高并发下保证库存准确。技术要点数据库乐观锁适用并发冲突较少场景优点实现简单无死锁缺点冲突高时大量重试分布式锁Redis锁性能好适合高并发Redisson支持看门狗自动续期ZooKeeper锁强一致性但性能较低队列削峰秒杀请求入队异步处理控制并发处理速度用户轮询或推送结果最佳实践组合Redis预扣减库存高性能数据库最终扣减数据准确消息队列异步下单削峰问题4服务调用可靠性业务场景微服务架构下服务间调用需要容错和降级。技术要点Resilience4j核心组件CircuitBreaker熔断器防止雪崩TimeLimiter超时控制Retry重试机制RateLimiter限流Bulkhead舱壁隔离熔断器状态转换CLOSED正常状态请求正常通过OPEN熔断状态直接拒绝请求HALF_OPEN半开状态允许部分请求测试超时处理策略设置合理超时时间通常200-500ms超时后快速失败配合重试机制指数退避问题5分布式事务业务场景跨多个服务的业务操作需要保证数据一致性。技术要点Seata AT模式基于两阶段提交的改进自动解析SQL生成回滚日志适用大多数业务场景TCC模式Try-Confirm-Cancel三个阶段需要手动实现三个接口适用对一致性要求高、业务复杂的场景消息队列最终一致性本地事务消息表定时任务扫描未发送消息消费者幂等处理选型建议简单场景AT模式复杂业务TCC模式允许延迟消息队列问题6系统监控业务场景线上系统需要实时监控和快速问题定位。技术要点监控体系三层指标监控PrometheusGrafanaCPU、内存、QPS等日志收集ELK Stack集中日志分析链路追踪SkyWalking/Zipkin请求链路分析问题排查流程查看告警确定问题范围链路追踪定位耗时环节日志分析具体错误信息指标对比发现异常波动自定义业务指标订单量、支付成功率等业务指标慢查询统计缓存命中率问题7Kubernetes部署业务场景微服务容器化部署到K8s集群。技术要点Dockerfile优化多阶段构建减小镜像体积使用Alpine或Distroless基础镜像分层缓存优化构建速度K8s配置要点资源限制防止单个容器占用过多资源健康检查livenessProbe和readinessProbeHPA根据指标自动扩缩容HPA配置示例apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: order-service-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: order-service minReplicas: 3 maxReplicas: 20 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70问题8AIGC集成业务场景内容社区集成AI生成内容功能。技术要点架构设计异步处理避免阻塞用户请求消息队列解耦和削峰结果缓存减少重复生成成本控制请求去重相似prompt返回缓存结果限流控制并发请求数模型选择根据场景选择不同成本模型质量保证内容审核敏感词AI审核人工抽检定期抽样检查用户反馈举报和评分机制问题9直播弹幕系统业务场景千万并发下的实时弹幕推送。技术要点架构设计接入层WebSocket长连接负载均衡消息层Kafka/RocketMQ消息队列推送层Redis Pub/Sub或自研推送服务存储层HBase/Cassandra存储历史弹幕千万并发方案分层架构边缘节点就近接入连接复用单服务器维护10万连接消息合并批量推送减少网络开销降级策略高峰期丢弃部分弹幕关键技术Netty高性能网络框架房间分片避免单点热点弹幕限速防止刷屏离线消息存储和补发总结本次面试涵盖了Java工程师在大型互联网企业需要掌握的核心技术栈缓存与数据库Redis缓存策略、一致性保障高并发处理锁机制、队列削峰、限流降级微服务架构服务治理、分布式事务、容错机制监控运维可观测性体系建设云原生容器化部署、自动扩缩容前沿技术AIGC集成、实时系统架构对于求职者来说不仅要掌握技术原理更要理解业务场景能够将技术方案与实际业务需求相结合。面试中展现出的思考过程和解决问题的能力往往比标准答案更重要。文章完作者注本文通过面试对话形式生动展示了Java技术栈在真实业务场景中的应用。谢飞机虽然有些问题回答不够深入但展现了对常用技术的实践经验。希望读者能从中学习到技术选型思路和解决方案设计方法。