写在前面
工作中积累的场景题解决方案梳理,以「场景 → 方案 → 工具/特点」的表格形式组织,方便快速检索。
内容涵盖:高并发与限流、缓存设计、MySQL/ES/HBase、分布式核心、系统架构、业务设计模式、性能优化、微服务、算法、DDD 等主题,共 11 大类、30+ 子章节、200+ 具体场景。
不是逐一讲原理的教程,每个方案只写核心关键词和适用特点,侧重「在什么场景下选什么方案、有哪些主流工具」。适合面试复习、技术方案选型时快速翻阅。
一、高并发与流量控制
限流
| 场景 | 方案 | 特点 / 工具 |
|---|
| 单机限流 | 令牌桶(Guava RateLimiter) | 允许突发流量,简单够用 |
| 单机限流 | 漏桶算法 | 匀速输出,保护下游,不允许突发 |
| 单机限流 | 固定/滑动窗口计数 | 固定窗口有边界突刺;滑动窗口更平滑 |
| 分布式限流 | Redis + Lua 原子脚本 | 多实例共享计数,滑动窗口用 ZSet 实现 |
| 分布式限流 | Sentinel | 阿里开源,支持 QPS/并发/热点参数限流,可视化控制台 |
| 网关层限流 | Nginx limit_req | leaky bucket 实现,接入层第一道防线 |
| 用户级限流 | Redis ZSet 滑动窗口 | score=时间戳,范围删除+计数,精确控制每用户频率 |
| 接口注解限流 | @SentinelResource | 与 Spring 深度集成,支持降级/熔断联动 |
秒杀系统
| 场景 | 方案 | 特点 / 工具 |
|---|
| 流量入口削峰 | CDN 静态化 + Nginx 限流 | 拦截 90%+ 流量,减少后端压力 |
| 机器人过滤 | 答题验证码 / 滑块验证 | 人机识别,防刷单 |
| 用户资格校验 | Redis SET 预热白名单 | 活动前写入,O(1) 查询 |
| 防超卖(第一重) | Redis Lua 原子扣减库存 | DECR 原子操作,判断+扣减在同一 Lua 脚本 |
| 防超卖(第二重) | DB UPDATE WHERE stock > 0 | affected rows=0 则失败,行锁保证并发安全 |
| 防超卖(第三重) | 用户+商品唯一索引 | INSERT 唯一索引物理兜底,防重复下单 |
| 异步下单 | Redis 扣减成功后发 MQ,异步落库 | Kafka/RocketMQ,快速返回"排队中" |
| 超时取消回滚 | Redisson DelayedQueue / RocketMQ 延迟消息 | 15 分钟未支付,回滚 Redis + DB 库存 |
| 用户限购 | Redis SETNX 用户+商品唯一标记 | 一次性锁,防止同一用户多次下单 |
| 结果查询 | 前端轮询 / WebSocket 推送 | 异步下单后通知用户最终结果 |
| 极热场景库存 | 本地缓存(Caffeine)预扣 + Redis 兜底 | 减少 Redis 访问,本地预扣库存 |
| 防刷风控 | 同 IP/用户请求频率限制 + 黑名单 | Sentinel 热点参数限流,黑名单机制 |
缓存穿透 / 击穿 / 雪崩速查
| 问题 | 触发条件 | 核心方案 |
|---|
| 穿透 | 查询不存在的数据,缓存和 DB 都没有 | 布隆过滤器拦截 / 缓存空值+短TTL |
| 击穿 | 单个热点 key 过期,大量并发打 DB | Redisson 互斥锁重建 / 逻辑过期不设 TTL |
| 雪崩(key集中过期) | 大量 key 同时过期 | TTL 加随机抖动 base + random(0, 300s) |
| 雪崩(Redis 宕机) | Redis 整体不可用 | 主从哨兵/Cluster 高可用 + Caffeine 本地缓存兜底 |
二、缓存设计
缓存通用方案
| 场景 | 方案 | 特点 / 工具 |
|---|
| 热点数据缓存 | Redis String/Hash 存储 | 最常见,TTL + 主动刷新 |
| 本地缓存 | Caffeine | JVM 内缓存,访问最快,不跨实例共享 |
| 多级缓存 | Caffeine(L1)+ Redis(L2)+ DB(L3) | 命中率高,需处理各级一致性 |
| 热点 key 倾斜 | key 分桶(加 _0 ~ _N 后缀随机读) | 拆散热点,降低单 key 压力 |
| 大 value | 压缩(Snappy/Gzip)+ 存 Redis | 超大对象存 OSS,Redis 只存引用 |
| 缓存预热 | 启动时批量加载 / 定时预热 | 避免冷启动大量穿透 |
| 缓存淘汰策略 | LRU / LFU / TTL | Redis 支持多种策略,按业务特点选 |
缓存一致性
| 场景 | 方案 | 特点 / 工具 |
|---|
| 更新 DB 后同步缓存 | 延迟双删(更新前删+更新后延迟再删) | 简单,有短暂不一致窗口 |
| 更新 DB 后同步缓存 | Canal 监听 binlog 异步删除/更新缓存 | 解耦,最终一致,推荐生产使用 |
| 先写缓存还是先写 DB | 先写 DB,再删缓存(Cache Aside) | 主流模式,删比更新更安全 |
| 读多写少强一致 | 分布式锁保护读写 | 性能差,慎用,极少场景才需要 |
| 写多场景 | Write Through(写缓存同步写DB) | 一致性好,写性能下降 |
| 允许异步 | Write Behind(写缓存,异步刷DB) | 写性能极好,有丢失风险 |
三、数据存储层
存储技术选型
按数据模型选型
| 数据模型 | 推荐存储 | 典型场景 |
|---|
| 结构化数据,强事务 | MySQL / PostgreSQL | 订单、用户、账户、支付 |
| 海量 KV 读写 | Redis | 缓存、Session、计数器、排行榜 |
| 文档型/半结构化 | MongoDB | 商品详情(属性不固定)、日志、内容管理 |
| 全文搜索 / 复杂查询 | Elasticsearch | 搜索引擎、日志分析、聚合统计 |
| 海量时序 / 宽表 | HBase | 用户行为日志、监控时序、消息历史 |
| 时序指标数据 | InfluxDB / Prometheus | 机器监控、业务指标、IoT 数据 |
| 图关系数据 | Neo4j / JanusGraph | 社交关系、知识图谱、风控关系链 |
| 地理位置 | Redis GEO / PostGIS | 附近的人、地图检索、配送范围 |
| 列式分析 / 大宽表 | ClickHouse | 实时 OLAP、报表、用户画像分析 |
| 对象/文件存储 | OSS / MinIO / S3 | 图片、视频、大文件、导出文件 |
| 消息流 / 事件流 | Kafka | 日志采集、事件总线、流式计算数据源 |
按业务场景选型
| 业务场景 | 主存储 | 辅助存储 | 说明 |
|---|
| 电商订单 | MySQL | Redis(缓存)+ ES(搜索) | 强事务,订单状态机 |
| 商品搜索 | ES | MySQL(写入源)+ Redis(热词) | 全文检索 + 聚合过滤 |
| 用户 Session | Redis | - | TTL 自动过期,高频读写 |
| 消息/IM | HBase / MongoDB | Redis(未读数) | 海量历史消息,按会话 RowKey |
| 实时排行榜 | Redis ZSet | MySQL(持久化) | ZSet O(log N) 更新 |
| 活动优惠券 | Redis | MySQL | 预热库存到 Redis,写后落库 |
| 用户行为日志 | Kafka → HBase / ClickHouse | - | Kafka 缓冲,HBase 存储,ClickHouse 分析 |
| 风控规则 | Redis(实时特征)+ MySQL(规则) | - | 毫秒级规则匹配 |
| 监控指标 | Prometheus / InfluxDB | Grafana(展示) | 时序数据,自动过期 |
| 地理围栏 / 附近 | Redis GEO | MySQL(基础数据) | GEORADIUS 范围查询 |
| 社交关系链 | MySQL(小规模)/ Neo4j(复杂) | Redis(热点关注列表) | 关系深度查询用图数据库 |
| 内容管理(富文本) | MongoDB | MySQL(元数据)+ OSS(图片) | schema 灵活,字段随意扩展 |
| 报表 / 数仓 | ClickHouse / Hive | - | 列式存储,聚合查询极快 |
选型关键维度
| 维度 | 关注点 |
|---|
| 一致性要求 | 强一致选 MySQL;最终一致可用 Redis/HBase/MQ |
| 查询维度 | 单维度点查用 KV;多维度复杂查询用 MySQL/ES |
| 数据量级 | < 千万行 MySQL 足够;亿级考虑分库分表或 HBase |
| 写入频率 | 极高频写入(>10W TPS)考虑 Redis/Kafka/HBase |
| 读写比例 | 读多写少加 Redis 缓存;写多读少考虑 LSM 存储引擎 |
| 时效性 | 实时查询用 Redis/ES;离线分析用 Hive/ClickHouse |
| 是否需要事务 | 跨行/跨表事务必须 MySQL;单行原子操作 Redis 够用 |
| 运维成本 | MySQL/Redis 成熟;HBase/ClickHouse 运维复杂 |
MySQL 深度场景
| 场景 | 方案 | 特点 / 工具 |
|---|
| 大表加字段/索引(不锁表) | pt-online-schema-change | 创建影子表,增量同步,原子切换 |
| 大表加字段/索引(不锁表) | gh-ost | 基于 binlog 同步,GitHub 出品,更安全 |
| 大表加字段/索引(不锁表) | MySQL 8.0 Online DDL INPLACE | 部分操作原生支持 LOCK=NONE |
| 热点行高并发更新 | 库存分桶(多行拆分) | 将 1 行库存拆成 N 桶,随机选桶扣减 |
| 热点行高并发更新 | Redis 预扣库存,异步落库 | 彻底绕开 DB 行锁,配合 MQ 异步写库 |
| 主从延迟 | 并行复制 slave_parallel_workers | MySQL 5.7+ 多线程回放 binlog |
| 主从延迟 | 写后读强制走主库 | ShardingSphere 路由,避免读到旧数据 |
| 深度分页慢 | 游标分页(WHERE id > lastId) | 避免大 offset 全表扫,性能稳定 |
| 深度分页慢 | 子查询定位 + LIMIT | SELECT * WHERE id >= (子查询) LIMIT n |
| 死锁 | 统一加锁顺序 + 缩短事务 | 批量操作先 ORDER BY id |
| 死锁排查 | SHOW ENGINE INNODB STATUS | Found deadlock 定位 |
| 慢查询定位 | EXPLAIN 分析执行计划 | 关注 type/key/rows/Extra 字段 |
| 慢查询定位 | slow_query_log + pt-query-digest | 分析高频慢 SQL |
| 索引失效 | 避免对索引列做函数/运算/类型转换 | WHERE YEAR(col)= → WHERE col BETWEEN |
| 索引失效 | 避免左模糊 LIKE '%xxx' | 改用 ES 全文检索 |
| 大事务 | 拆分事务,查询移到事务外 | 只在事务内做写操作,减少持锁时间 |
| 历史数据归档 | 分区表按时间分区 + 老分区 DROP | PARTITION BY RANGE |
| 历史数据归档 | pt-archiver 低峰期批量迁移 | 平滑迁移,不影响线上 |
Elasticsearch
| 场景 | 方案 | 特点 / 工具 |
|---|
| 全文搜索 | IK 分词器 + text 类型 | ik_max_word 建索引,ik_smart 搜索 |
| 精确过滤 | keyword 类型 + term 查询 | 不分词,适合状态/标签/ID 过滤 |
| MySQL → ES 同步 | Canal + MQ + ES Consumer | 监听 binlog,解耦,最终一致,推荐 |
| MySQL → ES 同步 | Logstash JDBC 定时轮询 | 延迟大,适合数据量小/实时性低场景 |
| 深分页 | Search After(游标) | 基于上页最后一条,性能稳定,推荐 |
| 大批量导出 | Scroll API | 游标翻页,适合全量导出 |
| Mapping 字段类型错误 | Reindex 到新索引 | 字段类型不能修改,只能重建 |
| 写入性能优化 | _bulk 批量写 + 临时关闭 refresh | refresh_interval=-1,副本数=0,写完恢复 |
| 冷热数据分层 | Hot-Warm 架构 | 近期数据 SSD,历史数据 HDD |
| 自动过期清理 | ILM 索引生命周期管理 | 按时间自动 Rollover → Warm → Delete |
| 聚合统计 | Aggregation(terms/date_histogram) | 类似 GROUP BY,内存消耗大 |
| 自动补全 | Completion Suggester | 专用数据结构,毫秒级响应 |
| 拼音搜索 | pinyin 分词插件 | 支持拼音全拼/首字母搜索 |
HBase
| 场景 | 方案 | 特点 / 工具 |
|---|
| RowKey 热点 | 盐值前缀(hash % N 前缀) | 写入均匀分散到各 Region |
| RowKey 热点 | 时间戳取反 | 最新数据在前,避免写入集中 |
| 非 RowKey 查询 | ES + HBase 组合 | ES 存索引查 RowKey,HBase 查完整数据 |
| 非 RowKey 查询 | Phoenix 二级索引 | SQL on HBase,CREATE INDEX,使用方便 |
| 非 RowKey 查询 | 自建倒排索引表 | 维护一张 HBase 表作为索引,需维护一致性 |
| 海量时序数据 | RowKey = deviceId + reverse(ts) | 同设备数据聚合,时间倒序 |
| 写入优化 | 批量 put + 关闭 WAL | 允许少量丢失时跳过 WAL,性能提升显著 |
| 读取优化 | 指定 CF + Scan startRow/stopRow + Filter | 减少扫描范围和网络传输 |
| 预分区 | 建表时指定 SplitKeys | 避免初始只有一个 Region,写入热点 |
| 数据过期 | 设置列族级别 TTL | HBase 原生支持,自动清理过期 Cell |
分库分表
| 场景 | 方案 | 特点 / 工具 |
|---|
| 单表过大 | 垂直分表(按列拆分大字段) | 分离不常用/大字段,减少 IO |
| 单表过大 | 水平分表(按 hash/range 分片) | ShardingSphere / MyCat |
| 分片键选择 | 按 userId 分片 | 用户维度查询集中,数据均匀 |
| 分片键选择 | 按时间 range 分片 | 适合时序数据,冷热分离,但写入热点 |
| 跨分片查询 | 广播查询 + 应用层汇总 | 性能差,尽量避免,设计时就要规避 |
| 跨分片分页 | 各分片查 TOP N,应用层归并排序 | 分片数多时性能下降 |
| 历史数据归档 | 归档库(按年/月建库) | 主库保持小体量,冷数据独立存储 |
分布式 ID
| 场景 | 方案 | 特点 / 工具 |
|---|
| 唯一 ID 生成 | Snowflake | 64位,趋势递增,高性能,时钟回拨问题 |
| 唯一 ID 生成 | 数据库号段(Leaf-segment) | 批量申请 ID 段,美团 Leaf 开源 |
| 唯一 ID 生成 | Leaf-snowflake | Zookeeper 分配机器 ID,美团开源 |
| 唯一 ID 生成 | UidGenerator | 百度开源,解决时钟回拨 |
| 唯一 ID 生成 | Redis incr | 简单,需持久化保障,Redis 故障有风险 |
| 时钟回拨处理 | 等待时钟追上 / 借位序列号 | Snowflake 改进版常见策略 |
四、分布式核心
分布式锁
| 场景 | 方案 | 特点 / 工具 |
|---|
| 防并发重复执行 | Redis SET key val EX nx | 简单,注意原子性 |
| 防并发重复执行 | Redisson RLock | 看门狗自动续期,支持可重入,推荐 |
| 防并发重复执行 | Zookeeper 临时顺序节点 | 强一致,性能比 Redis 差 |
| 数据库级别防并发 | SELECT FOR UPDATE(悲观锁) | 锁住行,事务结束释放,并发低时可用 |
| 数据库级别防并发 | 乐观锁 version 字段 | UPDATE WHERE version=?,适合冲突少场景 |
| 定时任务防重复 | XXL-JOB 调度框架层面保证 | 框架保证只有一台机器执行 |
| 锁超时问题 | Redisson WatchDog | 默认 30s,每 10s 续期 |
| 主从切换锁丢失 | RedLock(了解即可) | 向多数节点加锁,争议较大,生产慎用 |
消息队列
| 场景 | 方案 | 特点 / 工具 |
|---|
| 消息不丢失(生产者) | 开启 confirm / acks=all + 重试 | RabbitMQ confirm;Kafka acks=all |
| 消息不丢失(Broker) | 消息持久化 + 多副本 | Kafka replication.factor≥3 |
| 消息不丢失(消费者) | 手动 ACK,成功后再确认 | 避免自动 ACK 导致消费失败但已确认 |
| 消息重复消费幂等 | 消息 ID + Redis SETNX | 消费前 set nx,成功则处理,失败则跳过 |
| 消息重复消费幂等 | 数据库唯一索引兜底 | INSERT IGNORE,重复则查已有结果返回 |
| 消息积压 | 扩容消费者实例 | 消费能力与实例数成正比 |
| 消息积压 | 新建临时 topic 批量迁移消费 | 积压严重时快速扩容消费 |
| 延迟消息 | RocketMQ 延迟消息 | 原生支持 18 个延迟级别 |
| 延迟消息 | RabbitMQ 死信队列 + TTL | 消息过期进死信队列,触发消费 |
| 延迟消息 | Redis ZSet(score=执行时间) | 轻量,Redisson DelayedQueue 封装 |
| 延迟消息 | 定时任务扫库 | 兜底方案,延迟精度低但稳定可靠 |
| 顺序消息 | 同一 key 路由到同一队列/分区 | Kafka partition key;RocketMQ MessageQueueSelector |
| 消息事务 | RocketMQ 事务消息 | half 消息 + 本地事务 + 回查机制 |
分布式事务
| 场景 | 方案 | 特点 / 工具 |
|---|
| 跨库/跨服务最终一致 | 本地消息表 + MQ | 简单可靠,最终一致,业界最常用 |
| 跨库/跨服务最终一致 | MQ 事务消息 | RocketMQ 原生支持,比本地消息表更简洁 |
| 同构数据库跨库 | Seata AT 模式 | 自动生成 undo_log,业务代码侵入极低 |
| 高并发金融场景 | TCC(Try-Confirm-Cancel) | 性能最好,业务侵入性强 |
| 长流程多服务编排 | SAGA 模式 | 每步有补偿操作,适合跨多服务长事务 |
| 强一致场景 | XA 协议(两阶段提交) | 强一致,性能差,有锁等待,不推荐大量使用 |
幂等性
| 场景 | 方案 | 特点 / 工具 |
|---|
| 防表单重复提交 | Token 机制(前端申请+后端 Lua 原子校验删除) | 一次性 token,天然防重 |
| 接口重复调用 | 业务唯一流水号 + DB 唯一索引 | DuplicateKeyException 捕获后返回已有结果 |
| 接口重复调用 | Redis SETNX 幂等锁 | key=业务ID,设过期时间,业务失败需释放 |
| 更新操作幂等 | 乐观锁 version 版本号 | UPDATE WHERE version=? 影响行数=0 则幂等 |
| 更新操作幂等 | 状态机校验(当前状态是否允许操作) | 防止重复状态流转 |
| MQ 消费幂等 | 消息 ID + Redis/DB 去重 | 消费前标记,成功后持久化标记 |
| 支付场景 | out_trade_no 全局唯一 + 查重 | 重复请求返回第一次结果 |
五、系统架构设计
调用模式(同步 / 异步 / 回调 / 事件)
| 场景 | 方案 | 特点 |
|---|
| 强依赖结果,实时返回 | 同步调用(HTTP / RPC) | 简单,调用方阻塞等待,耦合度高 |
| 不依赖下游结果,解耦 | 异步调用(MQ 发消息) | 解耦,削峰,响应快,结果不即时 |
| 需要最终拿到结果 | 异步 + 回调(Callback / Webhook) | 下游处理完后主动通知上游,常见于支付回调 |
| 需要最终拿到结果 | 异步 + 轮询查询结果 | 前端轮询接口,适合用户可等待场景 |
| 服务内多任务并行 | CompletableFuture 并行编排 | 无 MQ 依赖,JVM 内并行,任务有先后依赖时用 thenCompose |
| 业务事件解耦 | 事件驱动(Spring ApplicationEvent / Guava EventBus) | 同进程内发布订阅,解耦业务模块 |
| 跨服务事件 | MQ 消息(Kafka / RocketMQ) | 异步、持久化、可重放 |
| 需要响应结果的异步 | RPC 异步调用(Future 模式) | Dubbo/gRPC 均支持异步 Future |
| 实时双向通信 | WebSocket / SSE | 服务端主动推送,适合实时通知/进度 |
定时任务
| 场景 | 方案 | 特点 / 工具 |
|---|
| 单机简单定时 | Spring @Scheduled | 无分布式支持,多实例会重复执行 |
| 分布式定时任务 | XXL-JOB | 可视化调度,分片执行,推荐 |
| 分布式定时任务 | Elastic-Job | 动态分片,弹性扩缩容,当当开源 |
| 复杂调度规则 | Quartz Cluster 模式 | DB 存储调度信息,多节点竞争执行 |
| 防多实例重复执行 | 分布式锁(Redis SETNX)+ 任务标记 | 任务开始抢锁,执行完释放 |
| 海量数据分片处理 | XXL-JOB 分片参数(shardIndex/shardTotal) | 每个实例只处理属于自己的数据分片 |
| 延迟执行一次性任务 | Redisson DelayedQueue / RocketMQ 延迟消息 | 比定时扫库更实时 |
| 任务失败重试 | 框架内置重试 + 失败告警 | 记录失败任务,支持手动重试 |
| 任务幂等 | 任务执行状态标记 + 唯一业务 key | 防止任务重启后重复处理 |
可用性与心跳检测
| 场景 | 方案 | 特点 / 工具 |
|---|
| 服务健康检测 | HTTP 心跳探针(/actuator/health) | Spring Boot Actuator 内置,注册中心定期探测 |
| 服务健康检测 | TCP 连接探测 | 比 HTTP 轻量,适合非 HTTP 协议服务 |
| 服务自动摘除 | 注册中心心跳超时自动下线 | Nacos/Eureka 服务续约,超时则摘除 |
| 进程级存活检测 | 操作系统进程守护(Supervisor / systemd) | 进程挂掉自动重启 |
| 依赖组件检测 | 定时探测 DB/Redis/MQ 连通性 | 连接池 testOnBorrow / 心跳 SQL |
| 数据库主库故障切换 | MySQL MHA / Orchestrator | 自动检测主库宕机,提升从库为主库 |
| 多节点选主 | Zookeeper 临时节点抢占 / Raft 协议 | etcd/ZK 实现分布式选主,主节点负责执行 |
| 接口可用率监控 | 错误率超阈值触发熔断 | Sentinel 异常比例策略,自动熔断 |
| 全链路健康大盘 | Prometheus + Grafana | 采集各服务指标,可视化,告警配置 |
高可用与熔断降级
| 场景 | 方案 | 特点 / 工具 |
|---|
| 依赖服务超时/不可用 | 熔断降级(Sentinel / Resilience4j) | 熔断器状态机:关闭→开启→半开 |
| 兜底数据 | fallback 返回默认值/缓存旧数据 | 降级时不返回错误,返回合理兜底 |
| 超时控制 | 所有 RPC 设置合理超时 | Feign/RestTemplate/gRPC 均要设置 |
| 重试 | 幂等接口 + 指数退避重试 | Spring Retry / Resilience4j Retry |
| 服务单点 | 多实例部署 + 负载均衡 | Nginx / SLB / LoadBalancer |
| 机房级故障 | 异地多活 | 流量就近访问,机房故障自动切换 |
| 全链路超时传递 | 通过 Header 传递剩余超时时间 | 避免上游超时后下游还在无效执行 |
| 舱壁隔离 | 不同业务使用独立线程池 | 一个业务卡死不拖垮其他业务 |
架构设计场景
| 场景 | 方案 | 特点 / 工具 |
|---|
| 短链系统 | 发号器(自增ID转62进制)+ Redis 缓存 + 302 重定向 | 简单唯一,点击统计异步 MQ |
| 消息推送系统 | 渠道路由(Push/SMS/邮件)+ 频率控制 + 状态机 | 极光/信鸽/阿里云短信,送达回调 |
| 评论系统(楼中楼) | parent_id + root_id 存储,分页查根评论 | 按 root_id 批量查子评论,减少 N+1 |
| 排行榜 | Redis ZSet(score=积分) | O(log N) 更新,O(log N+K) 查 Top K |
| 积分系统 | 积分明细流水表 + Redis 计数 | 明细表支持对账,Redis 高频更新 |
| 搜索系统 | ES + 同义词/拼音分词 + function_score 相关性排序 | IK + pinyin 插件 |
| 风控系统 | 规则引擎(Drools)+ 实时特征(Redis)+ 离线模型 | 实时规则 + ML 模型双保险 |
| 灰度发布 | 流量染色 + Header 路由 + 网关规则 | 金丝雀发布,小比例流量验证 |
| 全链路压测 | 压测流量染色(Header 标记)+ 影子库 | 不影响生产数据,真实评估容量 |
| 链路追踪 | SkyWalking(Java Agent 无侵入) | TraceId 串联全链路,性能分析,告警 |
六、业务设计模式
参数传递方案
| 场景 | 方案 | 特点 / 适用 |
|---|
| 简单值传递,调用链短 | 直接方法参数传递 | 最清晰,推荐优先使用,但参数多时签名臃肿 |
| 参数多且层层透传 | 封装 Context 对象传递 | RequestContext/BizContext,聚合相关参数,便于扩展 |
| 同线程内跨层访问(如登录信息) | ThreadLocal | 无需显式传参,需注意线程池复用时清理 |
| 链路追踪、日志上下文 | MDC(Mapped Diagnostic Context) | SLF4J MDC,日志自动带 traceId/userId |
| 异步线程间传递上下文 | InheritableThreadLocal / TTL(TransmittableThreadLocal) | 阿里 TTL 解决线程池场景的上下文传递 |
| 微服务跨进程传递上下文 | HTTP Header 传递(X-User-Id / X-Trace-Id) | 网关注入,服务间通过 Feign 拦截器透传 |
| 微服务跨进程传递上下文 | gRPC Metadata | gRPC 原生上下文传递机制 |
| 配置/全局参数 | Spring Environment / 配置中心 | 不适合请求级别,适合全局静态配置 |
领域驱动设计 DDD
| 场景 | 方案 | 特点 |
|---|
| 微服务边界如何划分 | 按限界上下文划分,一个 BC 对应一个服务 | 避免按技术层切,应按业务能力切 |
| 服务内部代码臃肿 | 引入聚合根,业务逻辑收敛到领域对象 | 告别贫血模型,OrderItem 自己计算总价 |
| 跨聚合操作如何处理 | 领域事件 + 最终一致,不跨聚合直接操作 | 订单支付→发领域事件→库存聚合消费 |
| 跨限界上下文调用 | 防腐层(ACL)隔离,转换为本 BC 的模型 | 防止外部模型变化侵入内部领域 |
| 贫血模型 vs 充血模型 | DDD 推荐充血模型,行为和数据放一起 | Order.pay() 而不是 OrderService.pay(order) |
| 复杂对象创建 | 工厂方法 / 工厂类封装创建逻辑 | OrderFactory.createFromCommand(cmd) |
| 数据库与领域模型不一致 | 仓储层做 DO ↔ Domain Object 转换 | 领域对象不依赖 ORM 注解,保持纯洁 |
| 业务规则频繁变更 | 规则外置到领域服务 / 规则引擎(Drools) | 核心规则封装在领域层,不散落在业务流程里 |
| 历史系统重构引入 DDD | 修缮者模式(Strangler Fig) | 防腐层包裹老系统,逐步替换,不一次性大改 |
| 事件溯源(Event Sourcing) | 存储领域事件序列,状态由事件重放计算 | Axon Framework,适合审计要求高的场景 |
| CQRS(读写分离) | 写走领域模型,读走独立查询模型(ES/视图) | 读模型按查询需求定制,性能好,复杂度高 |
业务流程设计
| 场景 | 方案 | 特点 / 工具 |
|---|
| 多分支 if-else 替换 | 策略模式(Map<type, Strategy>) | 开闭原则,新增类型不改原代码 |
| 审批流 / 多步骤处理 | 责任链模式 | 每个节点只做一件事,可动态组合 |
| 状态变更管理 | 状态机(Spring Statemachine / 自实现) | 明确定义状态和流转,防止非法转换 |
| 复杂业务编排 | 流程引擎(Activiti / Flowable) | 可配置流程,适合审批/工单场景 |
| 规则频繁变更 | 规则引擎(Drools / Easy Rules) | 业务规则外置,不改代码 |
| 接口参数扩展 | 扩展字段用 Map/JSON 存储 | 避免频繁加字段,牺牲可读性 |
| 新老逻辑切换 | 功能开关(Feature Flag)+ 配置中心 | 灰度控制,随时开关,不用发布 |
| 数据组装(多服务聚合) | BFF 层(Backend For Frontend)聚合 | 网关后一层,专门做数据裁剪和聚合 |
| 非核心逻辑解耦 | 领域事件 + 观察者/MQ | 核心流程完成后发事件,其他模块自行响应 |
数据完整性
| 场景 | 方案 | 特点 / 工具 |
|---|
| 同库多表操作 | 本地事务 @Transactional | 简单,ACID 保证 |
| 跨库/跨服务操作 | 本地消息表 + MQ | 最终一致,最常用 |
| 跨服务强一致 | TCC 模式 | 性能好,侵入强,需实现 try/confirm/cancel |
| 长流程补偿 | SAGA 补偿模式 | 每步有回滚逻辑,适合跨多服务长流程 |
| 库存超卖防护 | 预占库存模型(locked_stock + sold_stock) | 预占,支付确认后转 sold_stock |
| 对账补偿 | T+1 全量对账 + 差异补偿表 | 定时拉取双方流水比对,差异自动/人工修复 |
| 支付防重复扣款 | out_trade_no 唯一 + 查重逻辑 | 支付前查记录,幂等处理 |
| 数据最终校验 | 定时对账任务 + 告警 | 核心链路必备,发现异常及时处理 |
面向对象六大原则(SOLID + LoD)
| 原则 | 核心思想 | 违反时的表现 | 实现方案 | 典型代码/工具 |
|---|
| S 单一职责原则(SRP) | 一个类只做一件事,只有一个引起变化的原因 | 一个 Service 方法几百行,又查又改又发通知 | 按职责拆分类:OrderQueryService / OrderCommandService / OrderNotifyService | 按业务维度拆包,避免万能 Utils 类 |
| O 开闭原则(OCP) | 对扩展开放,对修改关闭;加新功能不改老代码 | 新增支付方式要改 if-else,新增渠道要改 switch | 策略模式:定义接口,新增实现类而不改调用方 | Map<String, PayStrategy>,Spring @Component 自动注册 |
| L 里氏替换原则(LSP) | 子类可以替换父类出现的任何地方,不改变程序行为 | 子类重写父类方法后抛出父类不抛的异常,或缩窄了前置条件 | 子类只扩展行为,不收窄契约;优先组合而非继承 | 接口 + 组合替代深层继承,避免重写核心逻辑 |
| I 接口隔离原则(ISP) | 不应强迫客户端依赖它不使用的方法;接口要小而专 | 一个大接口十几个方法,实现类一半都是空方法或抛 UnsupportedOperationException | 按角色拆分接口:Readable / Writable / Queryable | Java 8 default 方法提供默认实现;Spring 各种细粒度接口 |
| D 依赖倒置原则(DIP) | 高层模块不依赖低层模块,都依赖抽象;面向接口编程 | Service 直接 new Dao 实现类,换数据库就要改 Service | 依赖注入(DI):高层依赖 Repository 接口,底层实现注入 | Spring IoC 容器,@Autowired 接口而非实现类 |
| LoD 迪米特法则(最少知识) | 一个对象应尽量少了解其他对象的内部;只和直接朋友通信 | 链式调用 a.getB().getC().doSomething(),耦合深 | 封装委托:在直接对象上提供方法,隐藏内部结构 | 外观模式(Facade)统一入口;避免跨层直接访问 |
六大原则记忆口诀: 单开里接依迪(SRP-OCP-LSP-ISP-DIP-LoD)
原则间联动场景:
| 场景 | 涉及原则 | 方案 |
|---|
| 新增支付渠道不改代码 | OCP + DIP | 策略接口 + Spring 注入,Map 路由 |
| Service 方法越来越长 | SRP | 按查询/命令/事件拆分,或提取领域服务 |
| 子类频繁重写父类逻辑 | LSP | 改用组合,将可变行为提取为策略对象 |
| 实现接口发现很多方法用不上 | ISP | 拆分细粒度接口,按角色实现 |
| 单元测试难以 mock 依赖 | DIP | 依赖注入接口,测试时注入 mock 实现 |
| 调用链过深,改动一处影响多处 | LoD | 引入 Facade 层,封装内部调用细节 |
设计模式应用场景
| 模式 | 典型应用场景 | 代表框架/用法 |
|---|
| 单例 | 连接池、配置对象、注册表 | Spring Bean 默认单例 |
| 工厂 / 抽象工厂 | 多类型对象创建(支付方式、通知渠道) | 策略 Map 替代 if-else |
| 策略 | 替换 if-else,算法族可替换 | Map<type, Strategy>,Spring 注入 |
| 模板方法 | 固定流程,子类实现步骤(导入/导出) | AbstractClass + Hook 方法 |
| 观察者 | 事件驱动解耦 | Spring ApplicationEvent,Guava EventBus |
| 责任链 | 审批流、过滤器链、拦截器 | Servlet Filter,Spring Interceptor |
| 装饰器 | 功能增强,不修改原类 | Java IO 流,Spring AOP |
| 代理 | AOP、事务、日志、权限切面 | JDK 动态代理,CGLib,Spring AOP |
| 建造者 | 复杂对象构建,参数多 | Lombok @Builder |
| 适配器 | 接口不兼容的对象协作 | Spring MVC HandlerAdapter |
七、性能优化
接口性能优化
| 场景 | 方案 | 特点 / 工具 |
|---|
| 串行查询变并行 | CompletableFuture.allOf | 总耗时=最慢那个,无 MQ 依赖 |
| 减少 DB 查询 | Redis 缓存热点数据 | 命中率高则效果显著 |
| 减少网络 IO | 批量接口合并请求 | 将 N 次 RPC 合并为 1 次 |
| 非核心逻辑 | 异步处理(MQ / @Async) | 日志、通知、积分不阻塞主流程 |
| SQL 慢 | 索引优化 / 覆盖索引 / 避免回表 | EXPLAIN 分析 |
| 大量小请求 | 批量合并(Batch)处理 | DB 批量 insert,Redis pipeline |
| 序列化性能 | 换序列化框架 | Protobuf / Kryo 比 JSON 快,体积小 |
| 连接池不够 | 调整连接池参数 | HikariCP maximumPoolSize,Redis 连接池 |
| 热点方法耗时 | Arthas trace 命令在线诊断 | 不重启,实时定位方法耗时 |
线程池
| 场景 | 方案 | 特点 / 工具 |
|---|
| CPU 密集型 | coreSize = CPU核数 + 1 | 减少线程切换开销 |
| IO 密集型 | coreSize = CPU核数 * 2(或更大) | IO 等待时 CPU 可处理其他线程 |
| 任务队列满了 | CallerRunsPolicy(调用方线程执行) | 自动限流效果,不丢任务 |
| 隔离不同业务 | 多个独立线程池(舱壁隔离) | 防止一个业务拖垮全部 |
| 线程池监控 | Micrometer + Prometheus + Grafana | 监控队列积压、活跃线程、拒绝次数 |
| 动态调整参数 | Hippo4j 动态线程池 | 不重启调整参数,美团/阿里均有实现 |
| 异步编排 | CompletableFuture 链式调用 | thenApply/thenCompose/allOf 组合 |
大数据量处理
| 场景 | 方案 | 特点 / 工具 |
|---|
| 百万级数据导出 | EasyExcel 流式写入 + 分页查询 | 低内存,阿里开源 |
| 百万级数据导出 | 异步导出 + OSS 存储 + 通知下载 | 提交任务→后台处理→发链接 |
| 大批量数据导入 | 分批次 batch insert(每批 500-1000) | 避免单次大事务,可断点续传 |
| 大批量数据导入 | MQ 异步消费入库 | 解耦,消费速度可控 |
| 实时流式数据处理 | Flink / Spark Streaming | 实时计算,状态管理,精确一次语义 |
| 大文件上传 | 分片上传 + 断点续传 | 前端切片,后端合并,OSS 原生支持 |
| 海量数据统计 | 预聚合(定时汇总写 DB) | 以空间换时间,查询直接读聚合结果 |
| 近似基数统计(UV) | HyperLogLog | Redis PFADD/PFCOUNT,误差 0.8%,空间极小 |
| 海量数据去重 | 布隆过滤器 | 空间小,有误判,不支持删除 |
| 海量整数去重/签到 | BitMap | Redis SETBIT,1 bit 表示一个整数 |
JVM & 性能排查
| 场景 | 方案 | 特点 / 工具 |
|---|
| CPU 飙高 | top -Hp pid 找线程 → jstack 看堆栈 | 找死循环/长时间运行的线程 |
| 内存泄漏 | jmap dump → MAT / VisualVM 分析 | 找 GC Root 引用链,定位泄漏对象 |
| 频繁 Full GC | jstat -gc 监控 → 调整堆参数 | 老年代增长过快,可能有内存泄漏 |
| OOM 自动 dump | -XX:+HeapDumpOnOutOfMemoryError | OOM 时自动生成 hprof,事后分析 |
| 在线诊断 | Arthas | watch/trace/ognl/dashboard,不重启诊断 |
| GC 选型 | G1GC(JDK 9+ 默认)/ ZGC(低延迟) | 低延迟场景用 ZGC,停顿 < 10ms |
| 线程死锁 | jstack 看 BLOCKED 线程 | Found deadlock 关键字定位 |
八、微服务与基础设施
微服务场景
| 场景 | 方案 | 特点 / 工具 |
|---|
| 服务注册发现 | Nacos(推荐)/ Eureka / Consul | Nacos 兼顾注册中心+配置中心 |
| 服务间调用 | OpenFeign + LoadBalancer | 声明式 HTTP 客户端,集成负载均衡 |
| 服务间调用 | gRPC | 高性能,Protobuf 序列化,适合内部高频调用 |
| 熔断降级 | Sentinel(推荐)/ Resilience4j | Hystrix 已停维,Sentinel 功能更丰富 |
| 分布式配置 | Nacos Config / Apollo | 动态配置,实时推送,支持命名空间隔离 |
| API 网关 | Spring Cloud Gateway / Kong / APISIX | 统一入口,鉴权、限流、路由 |
| 服务间鉴权 | JWT / OAuth2 / mTLS | 网关统一鉴权,内部服务可内网互信 |
| 多环境隔离 | Nacos 命名空间 + 标签路由 | 开发/测试/生产环境隔离 |
安全场景
| 场景 | 方案 | 特点 / 工具 |
|---|
| 接口鉴权 | JWT Token(无状态)/ Session(有状态) | JWT 适合微服务,Session 需 Redis 共享 |
| 第三方授权 | OAuth2 / OIDC 授权码模式 | 第三方登录,最安全的授权方式 |
| 防重放攻击 | 请求携带时间戳 + nonce,服务端校验 | 时间戳超 5 分钟拒绝,nonce 存 Redis 去重 |
| 接口防篡改 | 参数排序 + HMAC-SHA256 签名 | 密钥不在请求中传输 |
| SQL 注入 | MyBatis #{} 占位符,禁用 ${} | PreparedStatement 预编译 |
| XSS 防护 | 输出编码,CSP 策略 | OWASP Java HTML Sanitizer |
| CSRF 防护 | CSRF Token / SameSite Cookie | Spring Security 内置 |
| 敏感数据脱敏 | 手机号/身份证正则替换,日志脱敏 | 展示层脱敏,日志框架级别过滤 |
| 权限控制 | RBAC 角色权限模型 | Spring Security,菜单/按钮/数据行级权限 |
九、算法与数据结构
算法场景
| 场景 | 方案 | 特点 |
|---|
| Top K 问题 | 小顶堆(PriorityQueue,容量 K) | O(N log K),在线处理,内存友好 |
| Top K(海量数据) | 分片 + 各片小顶堆 + 合并 | 先 hash 分文件,各文件取 Top K,再合并 |
| 快速找第 K 大 | 快速选择算法(partition) | 平均 O(N),不需要完全排序 |
| 分布式路由均衡 | 一致性哈希 + 虚拟节点 | 增删节点只影响相邻区间,虚拟节点解决倾斜 |
| 限流 / 滑动统计 | 滑动窗口(ZSet + score=时间戳) | 精确控制窗口内请求数 |
| 定时任务调度 | 时间轮算法 | Netty HashedWheelTimer,Kafka 延迟队列底层 |
| 延迟任务 | 最小堆(按执行时间排序) | JDK DelayQueue 底层实现 |
| 海量 URL 判存 | 布隆过滤器 | 位数组 + 多 hash 函数,有误判率 |
| 海量整数去重 | BitMap | 10 亿整数仅需 128MB |
| 近似基数统计(UV) | HyperLogLog | Redis PFADD/PFCOUNT,误差 0.8% |
| LRU 缓存淘汰 | LinkedHashMap(accessOrder=true) | JDK 原生,重写 removeEldestEntry |
| LFU 缓存淘汰 | 双 HashMap + 双向链表 | 按访问频次淘汰,实现复杂 |
| 数据流中位数 | 大顶堆 + 小顶堆 | 大顶堆存较小一半,小顶堆存较大一半 |
十、理论速查
CAP / 一致性模式
| 模式 | 典型系统 | 说明 |
|---|
| CP(强一致,牺牲可用) | Zookeeper、etcd | 选主期间不可用,保证数据一致 |
| AP(高可用,弱一致) | Eureka、Cassandra | 节点宕机仍可用,数据短暂不一致 |
| 最终一致 | 本地消息表、MQ 事务消息 | 经过延迟后数据趋于一致 |
| 强一致 | 本地事务、XA | 单机或同库,最简单 |
| BASE 理论 | 分布式系统常态 | 基本可用 + 软状态 + 最终一致,对 ACID 的妥协 |
最后
场景题没有标准答案,面试时的加分项在于:
- 主动说明为什么选这个方案,而不只是"我知道这个方案"
- 能说出方案的取舍和边界(什么时候用,什么时候不适合)
- 结合实际项目举例,哪怕数据编一下也比纯理论好
- 主动延伸到监控、告警、降级、回滚等工程保障环节
持续更新中,欢迎评论补充~