Skip to content

模式对比矩阵

有些模式看起来相似但用途不同。本指南对比了常见的易混淆模式对,帮你选择正确的工具。

缓存 vs 对象池

维度LRU 缓存对象池
目的加速重复查询避免分配/GC 开销
淘汰最近最少使用被移除用户归还,重复使用
内容只读的缓存值可变的、可复用对象
命中率取决于访问模式100%(预分配)
示例DNS 缓存、HTTP 缓存数据库连接池、线程池
易混淆时如果你"缓存"对象来复用→ 那是对象池

Arena 分配器 vs 空闲链表

维度Arena 分配器空闲链表
分配O(1) 指针碰撞O(1) 从空闲链弹出
释放只能全部一次性释放单个 O(1) 归还
碎片化无(连续内存)可能(非连续)
生命周期阶段性(解析、渲染)逐对象
示例编译器每次查询的 arena游戏实体回收
易混淆时如果需要单独释放→ 用空闲链表

观察者 vs Actor 模型

维度观察者Actor 模型
通信同步回调异步消息
耦合共享内存,同一线程隔离状态,任意位置
扩展性单进程分布式系统
故障隔离一个坏观察者阻塞所有Actor 独立崩溃
示例DOM 事件、React 状态Erlang/OTP、Akka
易混淆时如果观察者需要隔离→ 用 Actor

跳表 vs B+ 树

维度跳表B+ 树
平衡概率性(随机层级)确定性(分裂/合并)
并发可无锁实现锁机制复杂
磁盘 I/O差(指针追踪)优秀(高扇出)
实现简单(约 100 行)复杂(500+ 行)
示例Redis 有序集、LevelDB memtableMySQL InnoDB、文件系统索引
易混淆时内存有序数据 → 跳表磁盘 → B+ 树

环形缓冲区 vs 队列 (FIFO)

维度环形缓冲区标准队列
容量固定,预分配动态,按需增长
溢出覆盖最旧(或阻塞)分配更多内存
内存O(容量),无分配O(n),可能触发 GC
场景有界缓冲、音频流无界任务队列
示例Linux io_uring、日志消息队列、BFS
易混淆时容量已知 → 环形缓冲区无界 → 队列

写时复制 vs 双缓冲

维度写时复制双缓冲
缓冲区数1(写时克隆)2(始终分配)
拷贝触发发生变更时从不(交换指针)
读成本O(1) 始终O(1) 始终
写成本O(n) 首次写入克隆O(写入量) 写后缓冲
内存O(n) 仅在写入时O(2n) 始终
示例Linux fork()、Rc<T>GPU 渲染、游戏循环
易混淆时写入稀少 → CoW持续写入 → 双缓冲

熔断器 vs 限流器

维度熔断器限流器
保护调用方免受故障下游影响服务端免受过量流量影响
触发失败次数阈值请求数量阈值
方向出站(你调用别人)入站(别人调用你)
恢复超时后自动恢复令牌随时间补充
示例微服务 → 数据库API 网关、登录限制
易混淆时保护自己 → 熔断器保护服务器 → 限流器

状态机 vs 策略/虚表

维度状态机虚表
分发依据当前状态对象类型
转换显式、有守卫不适用
状态数运行时变化编译时固定
验证"这个转换能发生吗?""调用哪个实现?"
示例TCP 连接状态Trait 对象、接口
易混淆时行为随时间变化 → 状态机随类型变化 → 虚表

布隆过滤器 vs 哈希集合

维度布隆过滤器哈希集合
假阳性有(可调节)
假阴性
内存约 10 位/元素约 50+ 字节/元素
删除不支持O(1)
场景"肯定不在集合中"的快速检查精确成员判断
示例Chrome 安全浏览、LSM 读过滤去重、已访问 URL
易混淆时如果 1% 假阳性可接受 + 内存重要→ 布隆过滤器

预写日志 vs 检查点

维度预写日志检查点
粒度每个操作周期性快照
恢复从最后一个检查点回放加载快照 + 回放剩余 WAL
磁盘无限增长(不截断时)每次快照固定大小
写成本O(1) 每次追加O(状态大小)/次
组合使用? — WAL 提供持久性检查点限制回放长度
示例PostgreSQL WAL、Redis AOFPostgreSQL 基础备份、Redis RDB

背压 vs 限流器

维度背压限流器
方向生产者 → 消费者(上游信号)外部 → 服务器(网关强制)
机制减慢/暂停生产者丢弃或排队超额请求
范围内部管道流控外部 API 边界
适应性动态(适应消费者速度)静态阈值(令牌/秒)
示例Node.js stream .pipe()、Reactive StreamsStripe API 25 req/sec、Nginx limit_req
易混淆时如果你控制生产者 → 背压如果无法控制发送方 → 限流器

墓碑 vs 脏标记

维度墓碑脏标记
标记含义"此项已删除""此项需要重新计算"
生命周期永久存在直到压缩重新计算后清除
目的延迟物理删除延迟昂贵的重算
可见性读者必须跳过墓碑项读者看到过期值直到重算
示例Cassandra tombstone、LevelDB 删除标记Chromium 布局失效、游戏变换
易混淆时标记为"已消失" → 墓碑标记为"需更新" → 脏标记

驻留 vs 享元

维度驻留享元
共享方式相同值共享同一个实例内在状态共享,外在状态不同
查找全局表(哈希映射)工厂 + 缓存
标识指针相等替代值相等对象仍按值比较
可变性不可变(必须)内在不可变,外在可变
示例Python sys.intern()、Rust Symbol、Java 字符串池字体字形、游戏瓦片精灵、CSS 规则对象
易混淆时如果所有实例完全相同 → 驻留如果实例共享部分状态 → 享元

事件循环 vs 工作窃取

维度事件循环工作窃取
线程单线程 + I/O 多路复用多线程,每线程一个双端队列
适用场景I/O 密集型、高连接数CPU 密集型、递归/并行计算
调度协作式(回调/Promise)窃取式从其他队列获取任务
延迟一个慢回调阻塞所有空闲线程窃取任务,保持均衡
示例Node.js、Nginx、RedisGo 调度器、Java ForkJoinPool、Tokio
易混淆时主要 I/O + 少量 CPU → 事件循环CPU 密集 + 多核 → 工作窃取

访问者 vs 中间件链

维度访问者中间件链
遍历方式遍历类型化节点的树/图遍历线性管道
分发按节点类型(双重分发)按注册顺序
扩展操作新访问者 = 新操作新中间件 = 新层
数据流访问者累积结果请求/响应流经管道
示例LLVM IR pass、AST 变换Express.js、Django、gRPC 拦截器
易混淆时处理异构树 → 访问者处理请求/响应管道 → 中间件

选择正确模式:决策流程图

?需要存储/检索数据?
?需要管理并发?
?需要弹性?
?需要内存效率?

基于 MIT 许可证发布。