当前位置: 首页 > news >正文

互联网大厂Java面试实战:Spring Boot、Redis、Kafka、微服务、JWT、Elasticsearch与Kubernetes全栈技术

互联网大厂Java面试实战:Spring Boot、Redis、Kafka、微服务、JWT、Elasticsearch与Kubernetes全栈技术

面试官:请进,坐吧。先介绍一下你做过的最有代表性的项目。

谢飞机:老师好,我叫谢飞机,三年Java开发。我做了一个宠物内容社区“喵次元”,用户可以发猫咪图片、短视频,也能点赞评论关注。我主要负责后端,技术栈用了Spring Boot、MyBatis、MySQL、Redis、Kafka,搜索用的Elasticsearch,部署在Docker上。

面试官:你们用了Spring Boot,那你说说Spring Boot自动配置的原理?

谢飞机:(搓手)呃……自动配置就是“约定大于配置”嘛。Spring Boot启动的时候,会读一个叫spring.factories的文件,里面有一堆带@Configuration的类。比如引入了Redis,就会自动配一个RedisTemplate。但是……具体怎么根据classpath判断的,我当时没细看,反正用起来挺香。

面试官:Kafka和RabbitMQ的区别是什么?

谢飞机:Kafka是高吞吐,RabbitMQ是低延迟?我觉得Kafka像瀑布,RabbitMQ像水库。嗯……Kafka有partition,可以横向扩展,RabbitMQ有exchange和routing key,做路由很灵活。别的我一下子想不全。

面试官:在“喵次元”里,用户上传一个视频,怎么保证接口不卡死?

谢飞机:我们用了异步转码。上传后马上返回“处理中”,视频转码的消息丢到Kafka,有个消费程序慢慢转。客户等转好了,会收到WebSocket通知。这样接口很快,不会卡死。

面试官:好,第二轮。内容表数据量大了,你怎么优化?

谢飞机:先加索引,再上Redis缓存。如果超过千万,就分库分表。不过分库分表我只懂个大概,用ShardingSphere配置过逻辑表,真正的分布式事务没碰过。

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

谢飞机:这个我熟!穿透就缓存空值或布隆过滤器;击穿就是热点key过期,用互斥锁;雪崩就是大量key同时过期,给过期时间加随机数。这个问题我面试前刚背过。

面试官:背得挺熟练。那Redis有哪些数据结构?在社区里怎么用?

谢飞机:String、List、Hash、Set、ZSet我都用过。String存验证码,Hash存帖子内容,Set存粉丝列表,ZSet存热门排行榜,List存关注人的动态流。

面试官:怎么用Elasticsearch实现对文章和视频标题的搜索?倒排索引知道吗?

谢飞机:就是先建索引,然后搜索。倒排索引……我听腾讯课的讲师讲过,就是“单词->文档列表”的映射。但是和MySQL的索引区别我有点说不清。

面试官:第三轮。你们的服务怎么拆分的?服务发现用的什么?

谢飞机:按业务拆的,用户、内容、评论、消息、审核。服务发现用了Nacos,之前也用Eureka,Nacos还管配置。

面试官:服务A调用服务B,如果B挂了,A怎么避免雪崩?

谢飞机:使用Resilience4j做熔断限流,也加了Fallback方法。B挂了,A就直接返回缓存或提示“稍后重试”,不让线程一直等。

面试官:JWT和Session有什么区别?

谢飞机:Session存在服务器,JWT存在客户端。JWT是base64编码的三段,最后是签名,服务端验签就行。但是JWT不能强制下线,所以我们用Redis黑名单解决。

面试官:线上如何监控?Kafka消息积压了怎么办?

谢飞机:我们有Prometheus和Grafana,JVM、CPU、QPS都监控。日志用的ELK。毫秒级的链路追踪,用了Jaeger。积压的话……可以看Kafka的Lag指标,我们设了阈值,超过就报警。但具体命令有点忘了,好像是“kafka-consumer-groups.sh”吧。

面试官:很好。最后一个,你们CI/CD怎么设计的?

谢飞机:(眼睛一亮)这个我会!我们用GitLab CI,代码合并到main自动触发。流水线包括:maven打包、跑单测、docker build、推镜像、然后helm部署到K8s集群。K8s里用Deployment管理副本,滚动升级,可以自动回滚。

面试官:(点点头)好,我这边基本清楚了。你回去等通知吧。

谢飞机:好的,谢谢老师!


答案解析

第一轮

问题1:请介绍一个最有代表性的项目,它的整体架构和技术栈是什么?

这是一道典型的“项目自我介绍”题。面试官想看你的项目经验、技术深度和表达逻辑。回答时要按照“背景 → 架构 → 角色 → 亮点”来展开。

以“宠物内容社区”为例:

  • 背景:一个UGC平台,用户能发图文、视频,可以点赞、评论、关注、搜索。
  • 架构:前端App/H5 → Nginx → Spring Boot微服务集群(用户服务、内容服务、评论服务、消息服务、审核服务) → MySQL(主从/分片) + Redis(缓存) + Kafka(异步消息) + Elasticsearch(搜索) + OSS(文件存储) + WebSocket(消息推送)。
  • 职责:负责内容发布链路和消息服务,设计了视频异步转码流程。
  • 亮点:用Kafka削峰,用Redis缓存热点榜单,用Elasticsearch解决全文检索,用JWT做无状态登录。

给面试官讲项目时,不要只报技术名词,也要说清楚为什么选这个技术、解决了什么问题。

问题2:解释Spring Boot自动配置的原理。

Spring Boot自动配置的核心是@EnableAutoConfiguration注解。这个注解会通过@Import(AutoConfigurationImportSelector.class)导入一批“自动配置类”。

Spring Boot会在项目所有依赖的jar包中扫描META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件(Spring Boot 2.7之前叫spring.factories),拿到所有候选的自动配置类。

每个自动配置类上都有条件注解,例如:

  • @ConditionalOnClass(RedisOperations.class):只有当classpath中有这个类时,才配置Redis。
  • @ConditionalOnProperty(prefix = "spring.redis", name = "enabled", havingValue = "true"):需要指定配置项。
  • @ConditionalOnMissingBean:如果用户已经自己定义了Bean,默认配置就不再生效。

比如RedisAutoConfiguration,它检测到项目中有Redis相关类时,会创建一个RedisTemplate的Bean。如果用户自己写了RedisTemplate,就自动跳过默认配置。

简单说:自动配置 = 配置类扫描 + 条件注解 + 默认Bean装配。排查问题可以使用--debug启动查看自动配置报告。

问题3:Kafka和RabbitMQ在消息队列设计上有哪些核心区别?

它们都是成熟的消息中间件,但设计理念不同:

  • 模型不同:RabbitMQ基于AMQP协议,有Exchange交换机、Queue队列、RoutingKey路由。Kafka是分布式流平台,有Topic、Partition分区、Consumer Group消费组。
  • 消费方式不同:RabbitMQ是push推模型,消息到达队列后主动推给消费者;Kafka是pull拉模型,消费者自己从分区拉取消息,可以控制速率和offset重放。
  • 消息确认不同:RabbitMQ依赖ACK确认,消费者处理完返回ACK,否则重新投递;Kafka通过提交offset表示已经消费,可能重复消费,需要业务幂等。
  • 能力侧重不同:RabbitMQ功能强大,支持延迟队列、死信队列、优先级队列,适合复杂路由和低延迟任务;Kafka吞吐量高,天然持久化,适合日志采集、埋点数据、用户行为流、削峰填谷。
  • 可靠性实现不同:Kafka通过分区副本(Replica)和ISR机制保证高可用,生产端设置acks=all可以保证不丢消息;RabbitMQ支持镜像队列或Quorum Queue。

在UGC场景中,如果只是“发视频后通知转码”这种异步任务,RabbitMQ足够;但如果是海量日志、用户行为流、大数据管道,Kafka更合适。

问题4:在UGC音视频场景中,如何设计一个上传后异步转码的流程?

核心思路是“同步接口只接收,异步任务做重活”。

流程如下:

  1. 客户端请求后端获取“预签名上传地址”,然后直接上传到OSS对象存储。
  2. 上传完成后,客户端调用后端接口POST /videos,传入文件URL、标题、大小等元数据。
  3. 后端创建视频记录,状态设为“待处理”,同时向Kafka的video-transcodetopic发送一条消息,包含视频ID和源文件URL。
  4. 接口立刻返回,用户前端看到“处理中”。
  5. 后台转码服务订阅Kafka,收到消息后调用FFmpeg进行转码,同时抽帧生成封面。
  6. 转码完成后更新数据库状态为“已发布”,并通过WebSocket通知用户。
  7. 如果转码失败,把消息投递到死信队列,方便人工补偿。

用Kafka的好处是削峰填谷:用户同时上传大量视频,生产者写入很快,消费者根据自己的能力慢慢消费,不会瞬间压垮转码服务。即使转码服务宕机,Kafka也能保存一段时间消息,服务恢复后可以继续消费。

第二轮

问题5:内容表数据量达到千万级,如何优化数据库?分库分表怎么做?

数据库优化顺序是:索引 → SQL优化 → 缓存 → 读写分离 → 分库分表。

  • 索引优化:对查询条件中常用的user_id + created_at建联合索引。避免在索引列上做函数操作,遵循最左前缀原则。
  • 缓存优化:把热点内容存入Redis,比如首页Feed流可以直接缓存文章摘要列表,减少MySQL压力。
  • 读写分离:把写请求打到主库,读请求打到从库,用ShardingSphere或MyCat实现主从数据源切换。

分库分表有两种拆法:

  • 垂直拆分:把一个宽表拆成多个表,比如把文章正文、图片URL等大字段拆到单独表,主表只留核心字段。
  • 水平拆分:按某个分片键,如content_iduser_id,通过哈希/取模分布到多个库表中。例如拆成4个库,每个库8张表,总共32张表。

分库分表后要注意:

  • 全局唯一ID:用雪花算法生成,不能在多个表之间重复。
  • 跨库join:不允许,要改成查两次,或者冗余数据。
  • 分布式事务:跨库写操作需要引入Seata等分布式事务框架。
  • 全局搜索:分表后MySQL不适合搜索了,引入Elasticsearch。

社区项目通常按content_id分片,同时用ES解决全文搜索,用Redis解决热点缓存,这样MySQL的压力就能降下来。

问题6:缓存穿透、击穿、雪崩分别是什么?如何解决?
  • 缓存穿透:查询一个数据库也不存在的key,请求绕过缓存直接打数据库,恶意攻击时会导致数据库压力巨大。

    • 解决1:缓存空值,即使查询结果是null,也写入缓存并设置较短过期时间。
    • 解决2:使用布隆过滤器(Bloom Filter),在缓存前判断key是否存在,不存在直接返回。
    • 解决3:接口层对请求参数做合法性校验。
  • 缓存击穿:一个热点key在过期的瞬间,大量并发请求同时访问数据库。

    • 解决1:互斥锁。只允许一个请求去查数据库,其他请求等待重试。
    • 解决2:热点key“永不过期”,后台线程定时重建缓存。
  • 缓存雪崩:大量key在同一时间集中过期,或者Redis整体不可用,导致大规模请求压垮数据库。

    • 解决1:过期时间加随机值,比如TTL = 24小时 + random(0, 5分钟)
    • 解决2:多级缓存,本地使用Caffeine,Redis作为第二级,请求先查本地再查Redis。
    • 解决3:Redis部署为Cluster高可用。
    • 解决4:开启服务降级和限流,保护下游数据库。

这三个概念一定要记牢,是Java面试高频问题。

问题7:Redis常见数据结构有哪些?在社区里分别适用什么场景?
  • String:最常用。存验证码、用户token、计数器、缓存对象。比如SET login:code:13800000000 1234 EX 300
  • Hash:适合存对象。比如用户信息HSET user:10086 name "cat" age 2。也适合点赞状态,field=用户IDvalue=1/0
  • List:有序列表。可以做关注人的动态流,发布动态时LPUSH user:timeline:10086 contentId
  • Set:去重集合。适合关注列表、粉丝列表、共同关注。比如SADD follower:10086 user1,然后SINTER求交集。
  • ZSet:有序集合。每个成员带一个score,适合排行榜。热门文章榜:ZINCRBY hot:article 100 articleId,然后ZREVRANGE hot:article 0 9 WITHSCORES
  • HyperLogLog:基数统计。统计今日UV。
  • Bitmap:位图。适合用户签到、在线状态,一个bit就能存一个用户。
  • Geo:地理位置。可以算附近的人、附近的宠物店。

在“喵次元”中,String存验证码和Token,Hash存用户资料,Set存粉丝关系,ZSet存热门排行榜,List存时间线。

问题8:如何用Elasticsearch实现全文搜索?倒排索引是什么?

关系型数据库MySQL的索引是正排索引,比如文章表有字段post_idtitlecontent,搜索LIKE '%猫%'会扫全表。ES用的是倒排索引,结构是“单词 → 文档ID列表”。

举个例子:

  • 文档1:“猫咪在吃饭”
  • 文档2:“狗狗在睡觉”

经过中文分词后,得到词语:猫咪、吃饭、狗狗、睡觉。倒排表就是:

  • 猫咪 → [文档1]
  • 吃饭 → [文档1]
  • 狗狗 → [文档2]
  • 睡觉 → [文档2]

搜索“猫咪”时,直接查倒排表得到文档1,非常快。

在实际项目中,我们会把MySQL中的文章数据同步到Elasticsearch。同步方式:

  • 业务双写:在写MySQL的同时,把数据写入ES。
  • Canal监听binlog:MySQL数据变更后,Canal读取binlog,通过Kafka发送给ES同步服务。
  • 定时任务批量同步。

在Spring Boot中集成ES,可以用Spring Data Elasticsearch:

  • 实体类上使用@Document(indexName = "content")
  • Repository接口继承ElasticsearchRepository
  • 方法上使用@Query或直接声明findByTitleLike

搜索时调用ES返回文章ID列表,然后再去Redis/MySQL查详情,减少ES压力。

第三轮

问题9:微服务如何拆分?服务发现和注册用什么?

微服务拆分要围绕“业务边界”和“团队边界”。比如一个UGC社区可以拆成:

  • 用户服务:注册、登录、用户资料。
  • 内容服务:发帖、发视频、文章查询。
  • 评论服务:评论、回复、点赞。
  • 消息服务:站内信、通知、WebSocket推送。
  • 审核服务:图片/文本/视频的内容安全审核。

拆分原则:每个服务能独立部署、独立扩展、独立维护,服务之间通过HTTP/RPC通信。

服务注册与发现常用组件:

  • Eureka:Netflix出品,Spring Cloud早期方案,已经进入维护状态。
  • Nacos:阿里出品,主打注册中心和配置中心,国内使用广泛。
  • Consul:HashiCorp出品,支持多数据中心。
  • Zookeeper:分布式协调系统,也能做服务注册中心。

以Nacos为例,服务启动后把自己注册到Nacos,消费者从Nacos拿到服务提供者列表,再通过OpenFeign或Ribbon做负载均衡调用。Nacos还支持配置中心,可以动态修改配置而不重启应用。

问题10:服务A调用服务B,如果B挂了,A怎么避免雪崩?

服务雪崩是指一个服务故障,导致调用方线程堆积,最终拖垮整个系统。防雪崩的手段有三层:

  • 超时:设置连接超时和读取超时。比如OpenFeign的connectTimeout=3sreadTimeout=5s,不能让线程无限等待。
  • 熔断:使用Resilience4j或Sentinel。例如A调用B,10秒内有50%请求失败,熔断器打开,后续请求直接返回fallback方法,不再访问B。
  • 限流:使用Sentinel控制A的最大QPS,超过直接拒绝,保护A自己不被打垮。
  • 隔离:给不同的外部依赖分配独立的线程池,比如调用B和调用C分别使用不同线程池,B卡死不会占满C的线程池。

Resilience4j的核心概念:

  • 熔断器状态:关闭 → 打开 → 半开 → 关闭。
  • 降级:@CircuitBreaker(name = "内容服务", fallbackMethod = "getContentFallback")
  • 半开时,允许少量请求试探,如果成功,熔断器关闭;如果失败,重新打开。
问题11:JWT认证和传统Session有什么区别?如何用Spring Security实现登录?

Session原理:

  • 用户登录后,服务器生成Session并保存到内存或Redis,把SessionID通过Cookie发给浏览器。
  • 后续请求带着Cookie,服务器根据SessionID查Session。
  • 可以主动销毁Session,实现强制下线,因为状态在服务端。

JWT原理:

  • JWT由三部分组成:Header(声明算法)、Payload(用户信息、过期时间)、Signature(签名)。
  • 用户登录后,服务器签名生成Token返回给客户端,客户端保存。
  • 每次请求在Authorization: Bearer <token>中携带,服务器验签后直接从Token中取用户信息。
  • 服务器不保存状态,所以天然适合分布式和微服务。
  • 缺点是Token本身不能主动失效,只能等过期时间。如果要强制下线,需要用Redis维护黑名单,把Token的jti存进去。

Spring Security + JWT登录流程:

  1. 引入spring-boot-starter-securityjjwt
  2. 配置SecurityFilterChain:关闭CSRF,设置SessionCreationPolicy.STATELESS
  3. 实现UserDetailsService从数据库加载用户信息。
  4. 登录接口中,使用AuthenticationManager校验用户名密码,成功后用Jwts.builder()生成Token。
  5. 实现一个OncePerRequestFilter,从请求头解析Token,验签后把UsernamePasswordAuthenticationToken放入SecurityContextHolder
  6. SecurityConfig中注册过滤器,并用@PreAuthorize("hasRole('USER')")控制接口权限。
问题12:线上监控怎么做?如何监控Kafka消息积压和链路追踪?

监控体系可以分为四层:

  • 指标监控:应用使用Micrometer库收集指标,暴露给Prometheus,Grafana做可视化。常见指标:JVM内存、GC次数、线程数、QPS、RT、错误率。
  • 日志监控:使用Logback输出日志,Filebeat采集日志到Logstash,再送到Elasticsearch,最后用Kibana查询。就是ELK技术栈。
  • 链路追踪:微服务调用链需要TraceId串联。使用Spring Cloud Sleuth + Zipkin或Jaeger,可以看到一次请求从网关到用户服务再到评论服务的完整耗时。
  • 告警:Prometheus的Alertmanager根据规则发送邮件、钉钉、Webhook。

Kafka消息积压监控:

  • 使用Kafka自带命令:kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group 消费组名 --describe
  • 查看每个分区的LAG(未消费消息数量)。如果Lag持续增长,说明消费者跟不上,需要扩容消费者实例或者增加分区数。
  • 可以使用Burrow工具自动监控Lag并暴露成Prometheus指标,在Grafana上设置“Lag > 阈值”的告警。

没有监控的系统是很危险的,面试中如果能说出“Prometheus + Grafana + ELK + Jaeger+Kafka Lag”这套组合,会加分不少。

问题13:CI/CD流程如何设计?Docker和Kubernetes在其中的角色?

CI是持续集成,CD是持续部署。一个完整的CI/CD流程可以考虑以下阶段:

  1. 提交代码:开发push到main分支,触发GitLab CI。
  2. 静态检查:执行mvn sonar:sonar,扫描代码质量。
  3. 单元测试:执行mvn test,使用JUnit 5、Mockito、AssertJ。
  4. 构建打包:执行mvn package -DskipTests,生成可执行Jar包。
  5. 构建镜像:编写Dockerfile,将Jar包打入镜像,比如基于eclipse-temurin:17-jre-alpine
  6. 推送镜像:将镜像推送到Harbor私有仓库。
  7. 部署:使用Helm或kubectl set image把新镜像更新到Kubernetes集群。

Docker的作用:

  • 将应用和依赖环境打包成镜像,保证“本地能跑,线上也能跑”。
  • 常见命令:docker builddocker rundocker push

Kubernetes的作用:

  • 编排容器。通过Deployment管理Pod副本数,Pod挂了自动重启。
  • Service提供负载均衡和稳定访问入口。
  • Ingress暴露HTTP/HTTPS域名路由。
  • 支持滚动更新,新Pod启动成功后再杀掉旧Pod,可以快速回滚。

数据库版本迁移可以在应用启动前使用Flyway或Liquibase执行SQL脚本,这样发布新版本不需要手动去数据库执行脚本,实现“数据库即代码”。

http://www.cnnetsun.cn/news/3931193.html

相关文章:

  • 天津水冷机组维保-欧米到家10年经验师傅30分钟极速上门检修|故障检修 | 定期保养 | 配件更换 | 清洗维护| 报价公开透明一站式服务
  • 宜宾网站建设多少钱?揭秘2024年真实价格内幕,别再被坑了!
  • 字体资源管理实战:从版权合规到高效应用,构建你的“字魂”武器库
  • 企业级驱动解决方案:深度解析Windows系统兼容性架构设计
  • Unity中使用DoTween Pro实现高性能照片墙动画与交互设计
  • 国土资源网站建设方案:打造高效透明的自然资源管理数字化平台
  • 马赛克技术原理与安全实践:从像素化到高斯模糊的隐私保护
  • A-59U:AEC 100dB与ENC 45dB的成因差异
  • Mac彻底卸载软件及清理残留文件全攻略
  • SpringBoot3+Vue3+MySQL图书借还管理系统源码 前后端分离实战
  • 谷歌TPU诞生记:从AI计算瓶颈到专用芯片革命
  • 网络绿化网站建设哪家权威,揭秘行业内幕,为您筛选靠谱合作伙伴指南
  • AI绘画本地部署实战:从Stable Diffusion到定制化图像生成
  • 考研数学高效复习:张宇基础三十讲与强化三十六讲结合使用指南
  • 短剧系统开发:功能设计与技术挑战解析
  • 终极Wand增强指南:如何通过开源工具解锁完整游戏修改体验
  • 3步实现Wallpaper Engine创意工坊壁纸高效下载的终极指南
  • 终极B站视频下载指南:如何使用BilibiliDown免费保存高清视频
  • Java+Vue企业工资管理系统开发实践与优化
  • 揭秘邯郸网站建设taigew背后的逻辑:不拼流量拼留存,小企业如何靠专业建站实现低成本逆袭
  • 深度解析金华市住房建设局网站如何赋能市民安居梦想与城市高质量发展
  • 电脑故障维修BIOS
  • HisToSGE:基于病理大模型与图像特征的高分辨率空间转录组预测
  • 90度转角LED显示应用指南
  • Poppins字体终极指南:3个理由让多语言设计变得简单高效
  • 5分钟免费解锁Wand专业版:终极游戏增强完整指南
  • Y型M8分支器与T型头的拓扑组合方案:复杂传感器网络的最佳布线实践
  • 揭秘胶州网站建设哪家好:本地企业如何在众多服务商中脱颖而出找到最优解
  • 零编程基础也能掌握:MATLAB脑网络分析终极指南
  • Intel Texture Works插件:如何在Photoshop中让游戏纹理“瘦身“80%?