2. 领域驱动设计(DDD)基础:实体、值对象、聚合、聚合根、领域事件、限界上下文在对象存储建模中的映射
在对象存储领域建模中,DDD 的战术模式(Tactical Patterns)为我们将复杂的存储语义(桶、对象、版本、分片、元数据)映射为可维护的软件模型提供了精确的“语言”。本节将逐一拆解六大核心概念,并给出它们在对象存储场景中的具体映射。
2.1 实体(Entity):拥有唯一标识的存储对象
实体是具有唯一标识且会经历生命周期变化的对象。在对象存储中,桶(Bucket)和对象(Object)是最典型的实体。
| 实体 | 唯一标识 | 生命周期行为 |
|---|---|---|
| Bucket | 全局唯一的桶名称(如 my-photos-2024) |
创建、设置版本控制、配置生命周期策略、删除 |
| Object | 桶内唯一的对象键(如 /images/logo.png) |
上传、覆盖、追加、删除、恢复历史版本 |
| UploadTask | 分片上传任务 ID(如 upload-xxx) |
初始化、上传分片、完成/取消 |
建模要点:实体的 equals() 方法必须基于 ID 判断,而非属性值。两个不同时间点的同一个 Object,即使元数据不同,只要对象键相同,就是同一个实体。
2.2 值对象(Value Object):描述存储属性的不可变值
值对象通过属性值来定义,没有唯一标识,且通常是不可变的。在对象存储中,以下概念应建模为值对象:
- ObjectMetadata:Content-Type、ETag、Content-Length、自定义元数据键值对。
- ACL(访问控制列表):一组授权规则,如
public-read、private。 - StorageClass:标准、低频、归档等存储等级。
- Checksum:MD5、SHA256 等完整性校验值。
- VersionId:版本控制场景下的版本标识符。
DDD 实践:值对象可以包含业务逻辑。例如
ObjectMetadata 可以提供一个 isImage() 方法,通过检查 Content-Type 是否以 image/ 开头来判断。
2.3 聚合(Aggregate)与聚合根(Aggregate Root)
聚合是一组强一致性的实体和值对象的集合,聚合根是外部访问聚合的唯一入口。在对象存储中,Bucket 是天然的聚合根,它管理着其内部的所有对象。
事务边界:聚合内部保证强一致性。例如,当您在一个 Bucket 中上传一个对象时,Bucket 的存储用量统计必须与对象大小保持实时一致。跨聚合的操作(如跨桶复制)只能保证最终一致性。
2.4 领域事件(Domain Event):存储状态变更的“痕迹”
领域事件记录了聚合中发生的重要状态变更。在对象存储中,以下事件具有明确的业务价值:
- ObjectUploaded:对象上传完成,触发后续处理(如图片缩略图生成)。
- ObjectDeleted:对象被删除,触发回收站清理或审计日志记录。
- BucketCreated / BucketDeleted:桶的生命周期变更。
- LifecycleTransitionExecuted:对象从标准存储自动转为归档存储。
PostgreSQL 集成:领域事件可以持久化到
domain_events 表中,使用 event_type、aggregate_id、payload (JSONB) 和 occurred_at 字段。这为事件溯源(Event Sourcing)和异步处理提供了基础。
2.5 限界上下文(Bounded Context):划分存储服务的“边界”
限界上下文是 DDD 中最重要的战略设计模式。在对象存储领域,我们不应将所有功能塞进一个巨大的“存储服务”中,而应拆分为多个独立的限界上下文,每个上下文拥有自己的通用语言和模型。
| 限界上下文 | 核心职责 | 聚合根 | 领域事件 |
|---|---|---|---|
| 数据平面(Data Plane) | 对象的上传、下载、删除、分片 | Bucket, Object | ObjectUploaded, ObjectDeleted |
| 元数据管理(Metadata) | 对象索引、自定义属性、标签搜索 | MetadataIndex | MetadataUpdated |
| 生命周期管理(Lifecycle) | 过期策略、存储类转换、自动清理 | LifecyclePolicy | LifecycleTransitionExecuted |
| 访问控制(IAM) | 用户认证、策略评估、签名验证 | Policy, User | PolicyChanged |
| 审计与计量(Audit) | 操作日志、存储用量统计、计费 | AuditLog | StorageUsageUpdated |
2.6 映射总结:从 DDD 概念到 PostgreSQL 表结构
将 DDD 概念映射到 PostgreSQL 时,我们遵循以下原则:
- 聚合根对应一张主表,如
buckets表,主键为聚合根 ID。 - 实体对应子表,如
objects表,外键引用聚合根。 - 值对象通常内嵌为 JSONB 列或拆分为独立的关联表(取决于查询模式)。
- 领域事件存储在
domain_events表中,使用 JSONB 存储事件载荷。
示例:在 PostgreSQL 中,
buckets 表存储聚合根,objects 表存储实体,object_metadata 作为值对象可以内嵌为 objects 表的 metadata JSONB 列,或者单独建表以支持更高效的索引查询。
通过以上映射,我们不仅获得了清晰的领域模型,还为后续的 PostgreSQL 集成(如使用 JSONB 存储值对象、使用外键约束保证聚合一致性、使用触发器记录领域事件)奠定了坚实的基础。