北京明光云振铎数据科技Java面经

Nacos、OpenFeign、Gateway 三个组件的作用及协作流程

首先:

  • Nacos 主要负责服务注册发现和配置中心
  • Gateway 作为统一网关入口,负责路由、鉴权、限流
  • OpenFeign 负责服务之间的远程调用

用户请求先进入 Gateway

Gateway 会先做 JWT 鉴权,比如校验 token 是否合法,然后解析 userId,通过 Header 透传给后面的微服务。之后 Gateway 会根据路由规则,把请求转发到对应服务。

这个时候 Gateway 并不是写死 IP,而是通过 Nacos 获取服务实例列表,实现动态服务发现和负载均衡。

比如:

复制代码
/api/order/**
→ cloud-service-order

真正调用时:

Gateway 会从 Nacos 拿到 order-service 的实例。

后面如果 order-service 需要调用 user-service:

就会通过 OpenFeign 发起 RPC 调用。

OpenFeign 底层同样会从 Nacos 获取 user-service 的实例地址,然后通过 LoadBalancer 做负载均衡。所以整体链路是:

复制代码
Client
→ Gateway
→ Nacos 服务发现
→ OrderService
→ OpenFeign
→ UserService

这样整个系统就具备:

  • 服务解耦
  • 统一入口治理
  • 配置动态管理

MySQL 慢查询如何分析?索引优化有哪些?

1.查看慢查询日志

2.explain对应的sql查询语句

3. 分析是否命中索引
4. 分析索引是否失效
5. 分析是否存在回表 ( filesort / temporary)

6.判断是否需要分库分表优化
7.查看是不是数据库连接池满了导致的偶尔慢查询

Redis 缓存穿透、击穿、雪崩的区别及解决方案

缓存穿透:是查询一个不存在的数据。

因为缓存和数据库都没有,请求会直接打到数据库。

解决方案一般是:

  • 缓存空值(redis缓存空值)
  • 布隆过滤器

缓存击穿:是某个热点 key 突然失效。

大量请求同时访问数据库,这个是高并发场景最危险的。

解决方案:

  • Redis 分布式锁(setnx + expire+Lua 保证原子性)
  • 热点数据永不过期

缓存雪崩:是大量 key 同时过期,导致数据库瞬间压力暴增。

解决方案:

  • 过期时间随机化
  • 多级缓存
  • 熔断降级
  • 限流保护

定时任务的实现方式;如何避免集群环境下任务重复执行?如何防止任务堆积?

我项目里定时任务用的是 XXL-JOB。

调度中心统一触发任务 ,业务服务作为 执行器 Executor 注册到调度中心。

这样在集群环境下,调度中心会根据路由策略选择某个执行器节点执行任务,不会让每个节点都各自执行一遍。

比如我会配置:

复制代码
路由策略:第一个 / 轮询 / 一致性 Hash / 分片广播
阻塞处理策略:单机串行
失败重试次数:有限次数

其中避免重复执行主要靠两点:

第一,任务不是每个节点自己触发,而是由 XXL-JOB 调度中心统一调度

第二,对于同一个任务,可以配置 单机串行,避免上一次还没执行完,下一次又重复触发。

依赖包引入导致脏数据的识别规则及自动清理实现方式

识别规则

  1. 唯一性校验

比如用户 id、手机号、业务单号不能重复。

  1. 完整性校验

必填字段不能为空,比如 userId、tenantId、status。

  1. 时间有效性校验

比如过期数据、历史版本数据不能覆盖新数据。

自动清理实现上,我一般不会直接物理删除,而是采用:

定时任务扫描

→ 按规则识别脏数据

→ 标记为 DIRTY / INVALID

→ 记录清理日志

→ 异步清理或人工复核

数据更新时,如何保证用户服务中缓存数据及时清除与更新?

用户数据更新时,我不会直接更新缓存,而是先更新数据库,再删除缓存。

因为缓存本身是派生数据,数据库才是主数据源。

具体流程是:

用户服务更新 MySQL 成功后,删除 Redis 中的缓存

如果系统有多级缓存,还会发布 MQ 消息,让其他服务或其他节点删除本地缓存


对于并发场景,可以加延迟双删,降低旧数据重新写入缓存的概率。

延迟双删是什么

"更新数据库后,删除两次缓存"

如何用Java 和 Redis 实现滑动窗口限流器

我会用 Redis 的 ZSET 实现滑动窗口限流。

ZSET 的 score 存请求时间戳,member 存请求唯一标识。

每次请求进来,先删除窗口外的旧请求,再统计当前窗口内请求数量。

如果数量超过阈值,就拒绝;如果没超过,就把当前请求写入 ZSET。

由于删除、统计、判断、写入这几个操作必须保证原子性,所以我会用 Lua 脚本在 Redis 端一次性执行,避免并发场景下限流失效。

相关推荐
keyipatience4 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
我的xiaodoujiao4 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
weixin_408099675 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
爱喝水的鱼丶5 小时前
SAP-ABAP:ALV通用封装实践——搭建可复用的ALV开发工具类,减少80%重复代码
开发语言·性能优化·sap·abap·erp·alv
科技新芯5 小时前
中坚科技亮相2026 WAIC:人形机器人ZERO首秀,重载四足机狗落地应用
科技·机器人
钱六两5 小时前
#3、SpringAI 接入deepSeek大模型(喂饭版)
java·spring boot·ai编程
脱胎换骨-军哥5 小时前
C++/Rust无缝互操作:混合系统新常态
开发语言·c++·rust
songroom6 小时前
Kimi K3:Rust封装XTP接口详细教程实践
开发语言·后端·rust
kebeiovo6 小时前
游戏服务端开发:Actor模型详解(Go语言)
开发语言·后端·golang
V_156560272196 小时前
陕南生态科创!2026年汉中市高新技术企业申报时间、条件、流程、区县奖补汇总
科技·数据