用途
本技能用于设计与实现事件溯源(event sourcing)系统中的事件存储,帮助在构建事件溯源基础设施、选择事件存储技术、实现自定义事件存储、优化事件存储与检索、设置事件存储模式、规划事件存储扩展等任务中给出结构化做法。当任务与事件存储设计无关,或需要本范围之外的领域或工具时,不应使用本技能。
主要能力
核心概念
-
事件存储架构:事件存储由多个流(Stream,对应聚合 Aggregate)组成,每个流内包含按顺序排列的事件;同时维护全局位置(Global Position)顺序,例如 1 → 2 → 3 → 4 → 5 → 6 → …。
-
事件存储需求:
- Append-only:事件不可变,只允许追加。
- Ordered:具备每流顺序与全局顺序。
- Versioned:支持乐观并发控制。
- Subscriptions:提供实时事件通知。
- Idempotent:安全处理重复写入。
技术选型对比
- EventStoreDB:适合纯事件溯源,属于单一用途。
- PostgreSQL:适合已有 Postgres 技术栈,但需手动实现。
- Kafka:适合高吞吐流式处理,但不适合按流查询。
- DynamoDB:适合无服务器、AWS 原生场景,存在查询限制。
- Marten:适合 .NET 生态,与 .NET 绑定。
使用方式(代码模板)
资料提供了四类可直接参照的模板,使用时应保持代码内容不变:
模板 1:PostgreSQL 事件存储模式
包含 events 表(字段含 id、stream_id、stream_type、event_type、event_data、metadata、version、global_position、created_at,并有 unique_stream_version 唯一约束)、snapshots 表、subscription_checkpoints 表,以及针对流查询、全局订阅、事件类型查询、时间查询的索引。
模板 2:Python 事件存储实现
使用 dataclass 定义 Event,EventStore 类基于 asyncpg 连接池提供 append_events(含乐观并发校验与版本分配)、read_stream、read_all、subscribe(基于订阅检查点轮询并更新检查点)等方法,并定义 ConcurrencyError 异常。
模板 3:EventStoreDB 用法
使用 esdbclient 的 EventStoreDBClient 连接,封装 append_events(根据 expected_revision 选择 StreamState.ANY、StreamState.NO_STREAM 或具体版本)、read_stream、subscribe_to_all,以及通过 $ce-{category} 读取类别投影。
模板 4:DynamoDB 事件存储
DynamoEventStore 类使用 boto3,通过 PK=STREAM#{stream_id}、SK=VERSION#{version} 组织数据,并以 GSI1PK、GSI1SK 支持全局顺序;append_events 使用 batch_writer,read_stream 使用 KeyConditionExpression 查询。表定义说明 PK、SK 为字符串,GSI1PK、GSI1SK 用于全局排序,容量可选按需或预置。
适用场景
- 设计事件溯源基础设施。
- 在事件存储技术之间做选择。
- 实现自定义事件存储。
- 优化事件存储与检索。
- 设置事件存储模式。
- 规划事件存储的扩展。
最佳实践
建议做法:
- 流 ID 包含聚合类型,例如 Order-{uuid}。
- 包含 correlation/causation ID,便于追踪。
- 从第一天起为事件设置版本,为模式演进做准备。
- 实现幂等性,使用事件 ID 去重。
- 针对查询模式建立合适索引。
不建议做法:
- 不要更新或删除事件,它们是不可变事实。
- 不要存储大体积负载,保持事件小巧。
- 不要跳过乐观并发控制,以避免数据损坏。
- 不要忽略背压,应处理慢速消费者。
限制
资料未说明本技能的具体收费、价格、平台限制、实际效果或逐步使用流程;相关内容暂未提供。本技能仅提供设计与实现层面的指导与代码模板。