用途
该技能用于优化事件流设计,核心目标是:通过校验流边界、估算增长量,并基于设计质量而非单纯体积来决定是否需要快照,从而保持事件流大小合理、避免不必要的快照,并在性能与简洁之间取得平衡。
适用领域:任何领域,如电商、银行、SaaS、市场平台、医疗等。
使用时机:
- 在领域分析中定义事件流之后
- 当担心流长度或性能时
- 在实现之前校验流设计
- 在性能规划期间确定快照策略
- 为可扩展性重新设计流时
主要能力
- 分析事件流设计,检查事件组织是否合理
- 估算流随时间的增长量
- 识别何时真正需要快照,何时是设计问题
- 推荐最优的流身份边界
- 在性能优化与复杂度之间取得平衡
- 提供不过度工程的快照策略
核心原则:设计优先,快照其次。
黄金法则:如果你发现因为流太长而需要快照,先问:“我的流身份错了吗?”通常答案是肯定的。快照是性能优化,不是设计问题。良好的流设计(正确的身份边界)往往能完全消除对快照的需求。
使用方式
访谈阶段(可选)
何时跳过访谈:如果用户已指定预期事件频率、流生命周期和增长模式。 何时访谈:当存在流长度担忧但增长估算不明确时。
访谈策略:在推荐快照之前,先建立增长预期和性能要求。大多数快照提议源于流边界设计不佳,而非真实体量——先呈现估算,以区分真实性能问题与设计问题。
关键问题:
-
增长估算(影响:决定是否需要快照,或是否应改变流设计) 问题:“估算事件:(A) 每实体每天,(B) 生命周期总量,(C) 多年增长。例如:每订单 5-10 个事件,每年 1-10 百万订单?” 为何重要:增长估算揭示流是否真的会过长,还是设计有误。 后续触发:如果估算超过每流生命周期 300 个事件 → 问“流身份正确吗?这个流能否按更窄的业务实体拆分?”
-
性能 SLA(影响:决定可接受的延迟和快照决策) 问题:“性能要求?(A) <100ms 读延迟,(B) <1s 可接受,(C) 最终一致性可接受?” 为何重要:严格 SLA 可能需要快照;宽松 SLA 通常不需要。 后续触发:如果选 (A) → 问“哪些命令具体需要亚 100ms 重放?这些命令是从读模型读取还是直接重放流?”
访谈流程:
条件入口: 如果用户已提供:
- 事件频率估算(每实体每天或每事务)
- 且流生命周期估算(月或年)
- 且读延迟 SLA(或确认最终一致性可接受) 则:跳过访谈,直接进行流分析 否则:进行访谈
阶段 1:增长估算(问题 1)
- 建立每实体事件量
- 使用估算公式预测生命周期流长度
- 确定是否需要重新设计或快照分析
阶段 2:SLA 要求(问题 2)
- 识别每个命令的读延迟要求
- 确定读模型或直接流重放是否满足 SLA
- 确定快照是否仅由 SLA 证明合理
记录访谈发现: 将发现追加到项目的事件建模文件: 文件:.trogonai/interviews/[project-name]/EVENTMODELING.md 使用 Write 工具添加/更新此部分:
Optimizing Stream Design (eventmodeling-optimizing-stream-design)
Growth Estimates
[From Q1: Events per entity per day, lifetime total, annual growth]
Performance SLAs
[From Q2: Latency requirements per command or view]
Optimization Decisions
- Streams requiring redesign: [list or "None"]
- Streams where snapshotting is justified: [list or "None"]
- Streams within acceptable bounds: [list]
更新访谈轨迹:
| Optimization | eventmodeling-optimizing-stream-design | Done | Stream growth estimates, SLA review, snapshotting decisions |
流设计优化框架
- 估算流增长
公式:
Estimated Stream Length (total events/instance) = Events Per Aggregate Instance Per Year (events/instance/year) × Lifetime of Instance (years) × Annual Growth Factor (dimensionless year-over-year multiplier ≥ 1.0)
快速示例:
- 电商订单:8 事件/年 × 1.5 年生命周期 = 8-16 事件 → 不需要
- 银行账户:100-200 事件/年 × 10 年 = 1000-2000 事件 → 1000+ 时考虑
- 订单处理:100+ 事件/年 × 5 年 = 300-500+ 事件 → 可能需要
- SaaS 用户:12-60 事件/年 × 5 年 = 60-300 事件 → 很少需要
- 识别流长度类别
| 长度 | 状态 | 行动 | 快照 | | < 50 事件 | 理想 | 保持原样 | 不需要 | | 50-100 事件 | 良好 | 监控增长 | 不需要 | | 100-300 事件 | 可接受 | 审查边界 | 若重放则考虑 | | 300-1000 事件 | 过长 | 先重新设计 | 仅最后手段 | | 1000+ 事件 | 严重 | 必须重新设计 | 无济于事 |
快速决策矩阵:
| 流长度 | 读取模式 | 频率 | 行动 | | < 50 | 任意 | 任意 | 理想 - 保持原样 | | 50-100 | 任意 | 任意 | 良好 - 监控 | | 100-300 | 从模型 | 任意 | 可以 - 无快照 | | 100-300 | 流重放 | 低 | 可以 - 监控 | | 100-300 | 流重放 | 高 | 重新设计 | | 300-1000 | 从模型 | 任意 | 可以 - 无快照 | | 300-1000 | 流重放 | 任意 | 重新设计 | | 1000+ | 任意 | 任意 | 严重 - 重新设计 |
参考文件
聚合边界设计:见 patterns.md,包含:
- 5 种聚合模式(单实体、复合、集合、事件日志、历史)
- 流大小决策树
- 表明需要重新设计的红旗
- 最优流设计技巧
快照策略:见 snapshotting.md,包含:
- 真正需要快照的标准
- 基于上下文的决策阈值
- 快照频率、版本管理和清理策略
- 成本效益分析
领域特定指导:见 domain-patterns.md,包含:
- 电商模式(订单、购物车、账户)
- 银行模式(账户、交易、贷款)
- SaaS 模式(订阅、工作区、数据集合)
- 实现检查清单
关键洞察
为什么快照通常不是答案: 在实现快照之前,问:
- 我能把这个聚合拆成更小的吗? → 能:就那样做。更简单、更好的设计。
- 我能降低事件粒度吗? → 能:批量事件或创建更粗的状态变化。
- 我为这个聚合使用读模型了吗? → 没有:创建读模型(缓存投影)。流大小变得无关紧要。
- 我测量过实际重放延迟吗? → 没有:先测量。大多数系统超出预期。
如果以上任何一项为“是”,先做那件事,再考虑快照。只有在穷尽设计改进之后,才考虑快照。
快照的权衡: 快照复杂度 ≈ 更好设计的 2-3 倍复杂度
快照前:50 行代码,简单,可测试 使用快照:150+ 行,版本管理、恢复逻辑、测试矩阵
更好的做法是重新设计并保持流 < 300 事件。
质量检查清单
- 每个流由业务实体身份(如 orderId)标识,而非类别或类型
- 没有流在没有设计理由的情况下无界增长——已估算事件频率和流生命周期
- 低于 1000 事件的流无需快照理由
- 如果提议快照,所有更简单的替代方案(拆分流、更短生命周期)已先被排除
- 命令处理程序状态从流事件重建——流外不存储持久状态
- 每个流可独立版本化和重放,不影响其他流
适用场景
- 在领域分析中定义事件流之后,校验流设计
- 担心流长度或性能时,评估是否需要快照
- 在实现之前,验证流身份边界是否合理
- 在性能规划期间,确定快照策略
- 为可扩展性重新设计流时
限制
- 该技能为设计指导性质,不包含具体代码实现
- 需要用户提供或通过访谈获得事件频率、流生命周期、读延迟 SLA 等输入
- 快照策略的具体阈值和实现细节需参考配套文件(patterns.md、snapshotting.md、domain-patterns.md),这些文件内容在资料中未完整提供
- 不涉及具体技术栈或框架的绑定