大厂Java面试实录:Spring Cloud微服务+Redis缓存+Kafka消息队列实战问答

面试场景背景

某互联网大厂技术部面试间,严肃的面试官对面坐着略显紧张的求职者谢飞机。本次面试聚焦电商场景下的微服务架构设计。


第一轮:基础架构与核心服务

面试官:谢飞机你好,请先介绍一下你在电商项目中使用的微服务架构。

谢飞机:好的领导!我们用的是Spring Cloud Alibaba,有Nacos做注册中心,Gateway做网关,Sentinel做限流...

面试官:不错,基础概念清晰。那Nacos和Eureka有什么区别?

谢飞机:呃...Nacos功能更多?支持配置中心?Eureka是Netflix的...

面试官:(点头)基本正确。Nacos确实集成了注册中心和配置中心。那你们服务间调用用什么?

谢飞机:OpenFeign!声明式接口调用,加@FeignClient注解就行!

面试官:很好。那Feign的负载均衡策略有哪些?

谢飞机:这个...轮询?随机?还有...(擦汗)

面试官:(微笑)没关系,继续。你们如何处理服务熔断?

谢飞机:Sentinel和Resilience4j都用过!可以配置降级策略!


第二轮:缓存与数据库设计

面试官:电商场景下,商品详情页QPS很高,你们怎么优化?

谢飞机:Redis缓存!热点数据放Redis,数据库压力就小了!

面试官:很好。那缓存穿透、击穿、雪崩怎么解决?

谢飞机:穿透用布隆过滤器!击穿用互斥锁!雪崩...加随机过期时间?

面试官:(赞赏)回答不错。那Redis集群方案用的什么?

谢飞机:Redis Cluster!分片存储,主从复制...

面试官:数据库层面呢?分库分表怎么做的?

谢飞机:这个...ShardingSphere?按用户ID哈希分片?

面试官:那数据迁移怎么做?

谢飞机:(犹豫)双写?灰度切换?


第三轮:消息队列与分布式事务

面试官:用户下单后,需要扣库存、发优惠券、通知物流,怎么保证一致性?

谢飞机:消息队列!Kafka解耦服务!

面试官:那消息丢失怎么处理?

谢飞机:ACK机制!生产者确认、消费者确认...

面试官:重复消费呢?

谢飞机:幂等性!数据库唯一键或者Redis记录消息ID!

面试官:分布式事务方案用的什么?

谢飞机:Seata!AT模式...TCC模式也了解...

面试官:那Seata的原理能说下吗?

谢飞机:(擦汗)全局锁...回滚日志...(声音变小)

面试官:(起身)好了,今天先到这里,回去等通知吧。

谢飞机:好的领导!感谢面试机会!


详细答案解析(小白学习专区)

第一轮答案详解

1. Nacos vs Eureka

技术点:服务注册与发现

  • Eureka:Netflix开源,AP模型(可用性优先),客户端轮询拉取服务列表
  • Nacos:阿里开源,支持AP/CP切换,集成配置中心,支持权重路由

业务场景:电商大促时,服务实例频繁扩缩容,Nacos能更快感知服务变化

2. OpenFeign负载均衡

技术点:客户端负载均衡

// 配置负载均衡策略
ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule  // 轮询
  // 或 RandomRule 随机
  // 或 BestAvailableRule 最小连接数

业务场景:订单服务调用库存服务,多实例部署时均匀分配流量

3. 服务熔断降级

技术点:Resilience4j/Sentinel

@CircuitBreaker(name = "inventoryService", fallbackMethod = "fallback")
public Inventory checkStock(Long productId) {
    return inventoryClient.getStock(productId);
}

public Inventory fallback(Long productId, Exception e) {
    return new Inventory(productId, 0); // 返回默认值
}

业务场景:库存服务故障时,订单服务不阻塞,快速返回降级结果

第二轮答案详解

1. 缓存三兄弟问题

缓存穿透:查询不存在的数据

  • 解决:布隆过滤器预判、缓存空值

缓存击穿:热点key过期瞬间大量请求

  • 解决:互斥锁、逻辑过期(不设置TTL,后台异步更新)

缓存雪崩:大量key同时过期

  • 解决:随机过期时间、多级缓存
// 布隆过滤器示例
@Autowired
private RedissonClient redissonClient;

public boolean mightExist(String key) {
    RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("productFilter");
    return bloomFilter.contains(key);
}
2. Redis Cluster方案

技术点:分片集群

  • 16384个slot,节点平分
  • 主从复制,自动故障转移
  • 客户端路由(Jedis Cluster/Lettuce)

业务场景:商品库存、用户会话等高频读写数据

3. 分库分表

技术点:ShardingSphere

sharding:
  tables:
    order:
      actualDataNodes: ds${0..1}.order${0..3}
      tableStrategy:
        standard:
          shardingColumn: user_id
          shardingAlgorithmExpression: order${user_id % 4}

业务场景:订单表数据量大,按用户ID分片,查询时带上user_id可路由到具体表

第三轮答案详解

1. 消息队列可靠性

技术点:Kafka ACK机制

# 生产者配置
acks=all  # 所有副本确认
retries=3
enable.idempotence=true  # 幂等性

# 消费者配置
enable.auto.commit=false  # 手动提交

业务场景:下单成功后,异步通知库存、优惠券、物流服务

2. 幂等性设计

技术点:防重复消费

// Redis实现幂等
public boolean tryProcess(String messageId) {
    String key = "processed:" + messageId;
    return redisTemplate.opsForValue().setIfAbsent(key, "1", 24, TimeUnit.HOURS);
}

业务场景:网络抖动导致消息重复,保证业务只执行一次

3. 分布式事务Seata

技术点:AT模式原理

  1. 一阶段:执行业务SQL,记录undo_log
  2. 二阶段提交:删除undo_log
  3. 二阶段回滚:根据undo_log反向补偿

业务场景:下单扣库存、减余额、发优惠券需保证原子性

@GlobalTransactional
public void createOrder(Order order) {
    inventoryService.deduct(order.getProductId(), order.getCount());
    accountService.deduct(order.getUserId(), order.getAmount());
    couponService.use(order.getCouponId());
}

面试总结

本次面试覆盖了微服务架构的核心技术栈:

| 技术分类 | 核心组件 | 掌握程度 | |---------|---------|---------| | 服务治理 | Nacos、OpenFeign | ⭐⭐⭐⭐ | | 缓存 | Redis Cluster | ⭐⭐⭐⭐ | | 消息队列 | Kafka | ⭐⭐⭐ | | 分布式事务 | Seata | ⭐⭐⭐ |

给小白的建议

  1. 先掌握Spring Boot基础
  2. 理解微服务拆分原则
  3. 深入1-2个中间件原理
  4. 多动手做实战项目

祝大家面试顺利!


本文纯属虚构,如有雷同,纯属巧合。谢飞机角色不代表真实求职者水平。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐