orion_intervew
后端面试题
🟢 一、NestJS
Q1: NestJS 依赖注入(DI)如何实现?相比 Express 有什么优势?
参考答案要点:
- 基于 TypeScript 的 reflect-metadata 实现 IOC 容器
- 通过 @Injectable() 装饰器注册 provider,自动管理实例生命周期
- 优势:解耦业务逻辑,利于测试和模块化,天然支持 TypeScript
Q2: Guard、Interceptor、Middleware、Pipe、Filter 的区别和适用场景?
参考答案要点: | 组件 | 执行时机 | 适用场景 | |------|----------|----------| | Middleware | 路由前 | 日志、CORS、请求解析 | | Pipe | 路由处理前 | 参数验证、数据转换 | | Guard | 路由处理前(Pipe 之后) | 权限校验、认证 | | Interceptor | 路由调用前后 | 响应格式化、缓存、超时控制 | | Filter(Exception Filter) | 异常捕获时 | 全局异常处理、错误格式化 |
Q3: NestJS 全局异常处理方案?
参考答案要点:
- @Catch() 自定义异常过滤器
- APP_FILTER 注册全局过滤器
- 统一错误响应格式(HTTP 状态码 + 业务错误码 + 消息)
- 生产环境隐藏堆栈信息
Q4: NestJS 模块化设计最佳实践?
参考答案要点:
- 按业务领域拆分模块(UserModule、OrderModule 等)
- forRoot() / forFeature() 动态模块模式
- 共享模块(SharedModule)封装通用组件
- 使用 @nestjs/config 管理环境变量
- 依赖注入层次清晰,避免循环依赖
🟢 二、Node.js 运行时
Q1: Event Loop 机制?v11 前后差异?阻塞场景及解决方案?
参考答案要点:
- 六个阶段:Timers → Pending → Idle/Prepare → Poll(I/O)→ Check → Close
- 执行优先级:process.nextTick > Promise.then > setTimeout > setImmediate
- v11 差异:v11 前每阶段结束后执行微任务;v11+ 每宏任务后执行微任务(与浏览器对齐)
- 阻塞场景:同步大计算、fs.readFileSync、复杂 JSON.stringify、正则回溯
- 解决方案:Worker Threads(CPU 密集型)、Stream(大文件)、子进程
Q2: 内存泄漏定位与修复?
参考答案要点:
- 常见原因:全局变量、闭包引用、缓存无限制、事件监听器未解绑、Stream 未关闭
- 定位工具:heapdump、Chrome DevTools Memory、clinic.js
- 修复:WeakMap、LRU 缓存、事件解绑、Stream 正确处理
Q3: 高并发服务设计?
参考答案要点: - 集群模式(cluster / PM2)利用多核 - 连接池(数据库、Redis) - 多级缓存(本地 + Redis) - 限流降级(express-rate-limit / Opossum) - 异步日志(pino / winston)
🟢 三、Koa2
Q1: Koa2 中间件洋葱模型原理?
参考答案要点:
- 基于 async/await + compose 函数实现
- 请求从外层进入中间件链,经过所有中间件后从外层返回
- await next() 之前是请求处理阶段,之后是响应处理阶段
- 与 Express 的线性模型不同,Koa2 中间件可以感知响应
Q2: Koa2 vs Express 对比?
参考答案要点: | 维度 | Koa2 | Express | |------|------|---------| | 异步模型 | async/await | callback | | 中间件模型 | 洋葱模型 | 线性模型 | | 内置功能 | 极简(仅核心) | 丰富(路由、模板等) | | 错误处理 | try/catch | 中间件捕获 | | 适用场景 | 需要精细控制的场景 | 快速开发、传统项目 |
Q3: Koa2 错误处理最佳实践?
参考答案要点: - 全局 error 事件监听 - 中间件层 try/catch 统一捕获 - 自定义错误类(HttpError)区分业务/系统错误 - 结构化日志记录
🟢 四、MongoDB
Q1: MongoDB 与关系型数据库相比,适合什么场景?
参考答案要点: - 适合:文档型数据、快速迭代、非结构化/半结构化数据、横向扩展 - 不适合:复杂事务、强一致性要求、多表 JOIN 频繁
Q2: MongoDB 地理位置搜索如何实现?
参考答案要点:
- 2dsphere 索引支持 GeoJSON 格式
- $near / $geoWithin / $geoIntersects 查询
- 按范围(如地铁口 N 公里内)、多边形区域搜索
Q3: 多条件检索性能优化?
参考答案要点: - 复合索引(价格区间 + 标签 + 面积) - 覆盖查询(投影所需字段,避免全文档返回) - 聚合管道优化($match 前置、$project 精简)
🟢 五、Redis
Q1: Redis 常见数据结构及使用场景?
参考答案要点: | 数据结构 | 场景 | |----------|------| | String | 缓存 token / 计数 / 分布式锁 | | Hash | 用户对象 / 商品详情 | | List | 消息队列 / 最近浏览 | | Set | 去重 / 共同关注 | | SortedSet | 排行榜 / 延迟队列 | | Bitmap | 签到统计 / 在线状态 | | HyperLogLog | UV 统计 |
Q2: Redis 缓存过期策略?
参考答案要点: - 惰性删除:访问时检查过期,CPU 友好但可能内存泄漏 - 定期删除:每 100ms 随机抽查 20 个 Key,过期 Key 占比 > 25% 则重复 - 内存淘汰:volatile-lru / allkeys-lru / volatile-ttl 等策略 - 持久化关联:RDB 过滤过期 Key,AOF 追加 DEL 命令 - 最佳实践:差异化过期时间、加随机偏移防雪崩、避免永不过期 Key
Q3: Redis 分布式锁实现?
参考答案要点:
- 基础:SET key value NX EX seconds
- 进阶:RedLock 算法(多 Redis 实例)
- 注意事项:锁续期(看门狗)、死锁预防、锁释放原子性(Lua 脚本)
Q4: Redis 优化 RAG 检索或 LLM 请求性能?
参考答案要点: - 缓存高频查询的 Embedding 结果 - 缓存 LLM 回复(相同 prompt 直接返回) - 会话状态管理(用户上下文、对话历史)
🟢 六、Elasticsearch
Q1: ES 核心概念?倒排索引原理?
参考答案要点: - 核心概念:Index(索引)→ Type(类型,7.x 废弃)→ Document(文档)→ Field(字段) - 倒排索引:将文档分词后建立"词项→文档ID"的映射,支持快速全文检索 - Analyzer:分词器(标准分词、IK 中文分词、自定义分词)
Q2: ES 查询优化?
参考答案要点:
- 优先使用 Filter(缓存结果)而非 Query
- 避免深度分页(使用 search_after / scroll)
- 合理设置分片和副本数量
- 使用 _source 过滤返回字段
- 批量写入(Bulk API)替代单条写入
Q3: ES 在业务中的应用场景?
参考答案要点: - 全文搜索(商品搜索、文档检索) - 日志分析(ELK Stack) - 聚合统计(用户行为分析、销售数据报表) - 地理位置搜索(附近的人/房源)
🟢 七、RabbitMQ
Q1: RabbitMQ 核心概念?消息模型?
参考答案要点: - 核心概念:Producer → Exchange → Queue → Consumer - Exchange 类型:Direct(精确路由)、Fanout(广播)、Topic(模式匹配)、Headers - 消息确认:Publisher Confirm(发布确认)、Consumer Ack(消费确认)
Q2: 消息可靠性保证?
参考答案要点: - 生产者端:Publisher Confirm + Return 机制 - MQ 端:消息持久化(Exchange + Queue + Message 都声明为 durable) - 消费者端:手动 Ack(处理成功后确认),失败重试 + 死信队列 - 幂等性:消息 ID 去重、业务唯一标识
Q3: 常见应用场景?
参考答案要点: - 异步解耦(订单创建 → 发邮件/发短信) - 流量削峰(秒杀、批量导入) - 任务队列(异步处理耗时任务) - 事件驱动(微服务间事件通知)
🟢 八、MySQL
Q1: 索引原理?B+ 树 vs Hash 索引?
参考答案要点: - B+ 树:范围查询友好,支持排序,叶子节点链表连接,InnoDB 默认索引 - Hash 索引:等值查询 O(1),不支持范围/排序,Memory 引擎使用 - 聚集索引(主键):叶子节点存储完整行数据 - 二级索引:叶子节点存储主键值,需要回表
Q2: 事务隔离级别?MVCC 原理?
参考答案要点: | 隔离级别 | 脏读 | 不可重复读 | 幻读 | |----------|------|-----------|------| | Read Uncommitted | ✅ | ✅ | ✅ | | Read Committed | ❌ | ✅ | ✅ | | Repeatable Read | ❌ | ❌ | ✅(InnoDB 通过 MVCC + Gap Lock 解决) | | Serializable | ❌ | ❌ | ❌ |
- MVCC:通过 Undo Log + Read View 实现,每行数据有隐藏字段(事务 ID、回滚指针)
Q3: SQL 优化思路?
参考答案要点:
- EXPLAIN 分析执行计划(type、key、rows、Extra)
- 避免全表扫描(加索引、避免 SELECT *)
- 避免索引失效(函数、隐式转换、前缀通配符 %)
- 分页优化(延迟 JOIN、游标分页)
- 慢查询日志定位瓶颈
🟢 九、MQTT
Q1: MQTT 协议核心概念?
参考答案要点: - 发布/订阅模型:Publisher → Broker → Subscriber - QoS 级别: - QoS 0:最多一次(不保证送达) - QoS 1:至少一次(保证送达,可能重复) - QoS 2:恰好一次(保证送达且不重复) - 保留消息(Retained):新订阅者立即收到最后一条消息 - 遗嘱消息(Last Will):客户端异常断开时自动发布
Q2: MQTT 在 IoT / 实时通信中的应用?
参考答案要点: - IoT 设备状态上报与控制 - 实时消息推送(比 WebSocket 更轻量) - 边缘计算与云端通信 - 智能家居、车联网场景
🟢 十、事务
Q1: 本地事务 vs 分布式事务?
参考答案要点:
- 本地事务:单数据库 ACID 保证,BEGIN → COMMIT/ROLLBACK
- 分布式事务:跨服务/跨数据库,一致性保证困难
Q2: 分布式事务方案?
参考答案要点: | 方案 | 原理 | 适用场景 | |------|------|----------| | 2PC(两阶段提交) | 协调者 + 参与者,prepare → commit | 强一致性,性能差 | | TCC | Try → Confirm → Cancel,业务层面补偿 | 高可用,开发成本高 | | 本地消息表 | 业务 + 消息同事务写入,异步发送 | 最终一致性 | | Saga | 长事务拆分为子事务,失败时反向补偿 | 微服务场景 | | 可靠消息最终一致性 | MQ 保证消息必达,消费者幂等处理 | 异步解耦场景 |
Q3: 补偿机制设计?
参考答案要点: - 正向操作与补偿操作成对设计 - 补偿接口幂等性保证 - 补偿失败重试 + 告警 - 人工介入兜底
🟢 十一、幂等
Q1: 什么是幂等?为什么需要幂等?
参考答案要点: - 定义:同一操作执行多次与执行一次效果相同 - 场景:网络重试、前端重复提交、消息重复消费、定时任务重复执行
Q2: 幂等实现方案?
参考答案要点: | 方案 | 原理 | 适用场景 | |------|------|----------| | 唯一索引 | 数据库约束,重复插入报错 | 插入操作 | | Token 机制 | 提交前获取一次性 Token,验证后删除 | 表单提交 | | 状态机 | 基于状态变更判断(仅允许特定状态转换) | 订单状态更新 | | 乐观锁 | 版本号 / 时间戳控制 | 更新操作 | | Redis 去重 | SETNX + 过期时间,请求 ID 去重 | 分布式场景 | | 业务唯一标识 | 订单号、流水号等天然幂等键 | 支付、退款 |
🟢 十二、编程思想
详细设计模式表格已移至独立文档,以下为核心考察点。
Q1: 创建型模式(单例、工厂、建造者)
- 单例:全局配置、日志、连接池
- 工厂:对象创建解耦,扩展新产品无需修改原有逻辑
- 建造者:复杂对象分步构建,避免参数爆炸
Q2: 结构型模式(适配器、装饰器、代理、外观)
- 适配器:接口不兼容时转换(支付 SDK 统一接口)
- 装饰器:动态添加职责(NestJS 的 @UseGuards / @UseInterceptors 就是装饰器)
- 代理:控制访问(权限、延迟、远程调用)
- 外观:简化复杂子系统调用(网关封装多个微服务)
Q3: 行为型模式(观察者、策略、责任链、模板方法)
- 观察者:事件驱动(Kafka / RabbitMQ 发布订阅)
- 策略:算法可切换(支付方式、优惠券计算)
- 责任链:请求沿处理链传递(HTTP 拦截器、审批流)
- 模板方法:固定流程 + 可变步骤(框架设计)
Q4: SOLID 原则?
参考答案要点: - S 单一职责:一个类只做一件事 - O 开闭原则:对扩展开放,对修改关闭 - L 里氏替换:子类可替换父类 - I 接口隔离:接口尽量小而专一 - D 依赖倒置:依赖抽象而非具体实现
🟢 十三、文件处理
Q1: Node.js 文件流(Stream)?
参考答案要点:
- 四种类型:Readable、Writable、Duplex、Transform
- 管道操作:readable.pipe(writable) 自动处理背压
- 优势:处理大文件时内存占用恒定(vs 全量读取)
Q2: 文件上传方案?
参考答案要点: - 小文件:直接上传(multipart/form-data) - 大文件:分片上传 + 断点续传(MD5 校验 + 分片编号) - 存储:本地磁盘 → 对象存储(OSS/S3)→ CDN 加速 - 安全:文件类型校验(Magic Number,非仅扩展名)、大小限制、病毒扫描
Q3: 文件下载优化?
参考答案要点: - 流式下载(避免全量加载到内存) - Range 请求支持(断点续传) - 压缩传输(gzip/brotli)
🟢 十四、Docker
Q1: Docker 核心概念?
参考答案要点: - 镜像(Image):只读模板,分层存储 - 容器(Container):镜像的运行实例 - 仓库(Registry):镜像存储和分发中心 - Dockerfile:镜像构建脚本 - Volume:数据持久化 - Network:容器间通信(bridge / host / overlay)
Q2: Docker 最佳实践?
参考答案要点:
- 多阶段构建减小镜像体积
- 非 root 用户运行容器
- .dockerignore 排除不必要文件
- 健康检查(HEALTHCHECK)
- 资源限制(--memory, --cpus)
- 日志驱动(json-file / syslog / fluentd)
Q3: Docker Compose vs Kubernetes?
参考答案要点: - Docker Compose:单机编排,适合开发和测试 - Kubernetes:集群编排,自动扩缩容、服务发现、负载均衡、自愈,适合生产
🟢 十五、CI/CD
Q1: CI/CD 流程设计?
参考答案要点: - CI(持续集成):代码提交 → 自动构建 → 单元测试 → 代码扫描 → 合并 - CD(持续交付/部署):构建产物 → 测试环境 → 自动化测试 → 生产环境 - 工具链:GitHub Actions / GitLab CI / Jenkins
Q2: 部署策略?
参考答案要点: | 策略 | 说明 | 适用场景 | |------|------|----------| | 蓝绿部署 | 两套环境交替切换 | 低风险、资源充足 | | 滚动更新 | 逐台替换,逐步放量 | 生产环境常用 | | 金丝雀发布 | 小流量验证 → 逐步扩大 | 高风险变更 | | 功能开关(Feature Flag) | 代码部署但功能未激活 | 灰度验证 |
Q3: 构建优化?
参考答案要点: - 缓存依赖(node_modules 缓存) - 并行构建(多 Job 并行) - 按需构建(仅变更模块触发构建) - 增量构建
🟢 十六、Python / Flask / FastAPI
Q1: Flask vs FastAPI 对比?
参考答案要点: | 维度 | Flask | FastAPI | |------|-------|---------| | 异步支持 | 原生不支持(需第三方) | 原生 async/await | | 类型检查 | 无 | 基于 Pydantic 自动校验 | | 文档 | 需手动配置 | 自动生成 OpenAPI/Swagger | | 性能 | 一般 | 高(Starlette + Uvicorn) | | 适用场景 | 简单 API、原型开发 | 高性能 API、ML 服务 |
Q2: Python 异步编程?
参考答案要点:
- asyncio 事件循环 + async/await
- aiohttp 异步 HTTP 请求
- GIL(全局解释器锁)限制:CPU 密集型用多进程,I/O 密集型用异步
Q3: Flask/FastAPI 中间件 / 依赖注入?
参考答案要点:
- Flask:before_request / after_request 钩子
- FastAPI:Depends() 依赖注入,支持嵌套和全局依赖
🟢 十七、自动化高阶爬虫
Q1: 爬虫架构设计?
参考答案要点: - 调度器:URL 队列管理、优先级调度、去重(Bloom Filter / Redis Set) - 下载器:并发控制、代理池、请求重试 - 解析器:HTML 解析(BeautifulSoup/lxml)、动态页面渲染(Playwright/Selenium) - 存储层:结构化存储(MySQL/MongoDB)、原始数据存档
Q2: 反爬策略应对?
参考答案要点: - IP 封禁:代理池轮换 - 验证码:打码平台 / OCR 识别 / 人工标注 - 动态渲染:Headless Browser(Playwright) - 指纹检测:浏览器指纹伪装 - 请求频率:合理间隔 + 随机延迟
Q3: 分布式爬虫?
参考答案要点: - Scrapy-Redis:分布式调度 + 去重 - URL 去重:Redis Bloom Filter - 任务分配:Master-Worker 架构 - 数据汇总:消息队列 → 消费者 → 数据库
Q4: 法律与合规?
参考答案要点: - robots.txt 遵守 - 数据采集频率控制(避免影响目标服务) - 个人隐私数据不采集 - 遵守《数据安全法》和《个人信息保护法》
🟢 十八、TTS(语音合成)
Q1: TTS 技术方案?
参考答案要点: - 传统方案:拼接式(录制语音片段拼接)、参数式(HMM 生成) - 深度学习方案: - Tacotron 2 + WaveNet:端到端,质量高 - FastSpeech 2:非自回归,速度快 - VITS:端到端变分推理,质量与速度兼顾 - 开源工具:Coqui TTS、Edge TTS、PaddleSpeech - 商用 API:Azure TTS、阿里云 TTS、讯飞 TTS
Q2: TTS 优化方向?
参考答案要点: - 流式合成(首包延迟降低) - 多语言 / 方言支持 - 情感控制(喜怒哀乐语气) - SSML 标记语言(语速、停顿、音调控制)
🟢 十九、ASR(语音识别)
Q1: ASR 技术方案?
参考答案要点: - 传统方案:GMM-HMM、DNN-HMM - 端到端方案: - CTC(Connectionist Temporal Classification) - RNN-T(Transducer,流式友好) - Whisper(多语言、零样本能力强) - Paraformer(阿里达摩院,中文效果好) - 开源工具:Whisper、FunASR、Kaldi
Q2: ASR 实际应用优化?
参考答案要点: - 领域语言模型适配(专有词汇识别率提升) - 说话人识别(区分不同说话者) - 流式识别 vs 非流式识别 - 实时性优化(VAD 语音检测 → 分段识别)
🟢 二十、单元测试
Q1: 单元测试核心原则?
参考答案要点: - FIRST 原则:Fast(快速)、Independent(独立)、Repeatable(可重复)、Self-validating(自验证)、Timely(及时编写) - AAA 模式:Arrange(准备)→ Act(执行)→ Assert(断言) - 覆盖率:行覆盖率、分支覆盖率、条件覆盖率
Q2: 测试框架与工具?
参考答案要点: - Node.js:Jest(断言 + Mock + 覆盖率一体)、Vitest(Vite 生态)、Mocha + Chai + Sinon - Python:pytest、unittest - Mock:隔离外部依赖(数据库、API、文件系统) - 集成测试:Testcontainers(真实数据库容器)
Q3: TDD(测试驱动开发)流程?
参考答案要点: 1. 编写失败的测试(Red) 2. 编写最小代码使测试通过(Green) 3. 重构代码(Refactor) 4. 循环迭代
🟢 附录:Redis 缓存过期策略(完整参考)
Redis 缓存过期是控制内存占用、保证数据时效性的核心机制。采用「惰性删除 + 定期删除」结合策略:
- 惰性删除:访问时检查过期,CPU 友好,但大量未访问过期 Key 会占用内存
- 定期删除:每 100ms 随机抽查 20 个 Key,过期占比 > 25% 重复扫描
- 内存淘汰:volatile-lru / allkeys-lru / volatile-ttl 等策略兜底
- 持久化关联:RDB 过滤过期 Key,AOF 追加 DEL 命令
- 最佳实践:差异化过期时间 + 随机偏移防雪崩、避免永不过期 Key
Page Source