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(聚合根) bucketName: String Object(实体) objectKey: String ObjectMetadata(值对象) contentType, etag ACL(值对象) grants: List UploadTask(实体) uploadId: String 聚合规则 • 外部只能通过 Bucket 聚合根访问其内部的对象和上传任务。 • 删除 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
对象存储限界上下文划分 数据平面 上传/下载/删除 分片上传 聚合根: Bucket, Object 元数据管理 对象索引/标签 自定义属性 聚合根: MetadataIndex 生命周期管理 过期策略 存储类转换 聚合根: LifecyclePolicy 访问控制 (IAM) 用户认证/策略评估 签名验证 聚合根: Policy, User 审计与计量 操作日志 存储用量统计 聚合根: AuditLog 上下文映射 数据平面 → 元数据管理 (通过领域事件通信) 数据平面 → 审计与计量

2.6 映射总结:从 DDD 概念到 PostgreSQL 表结构

将 DDD 概念映射到 PostgreSQL 时,我们遵循以下原则:

  1. 聚合根对应一张主表,如 buckets 表,主键为聚合根 ID。
  2. 实体对应子表,如 objects 表,外键引用聚合根。
  3. 值对象通常内嵌为 JSONB 列或拆分为独立的关联表(取决于查询模式)。
  4. 领域事件存储在 domain_events 表中,使用 JSONB 存储事件载荷。
示例:在 PostgreSQL 中,buckets 表存储聚合根,objects 表存储实体,object_metadata 作为值对象可以内嵌为 objects 表的 metadata JSONB 列,或者单独建表以支持更高效的索引查询。

通过以上映射,我们不仅获得了清晰的领域模型,还为后续的 PostgreSQL 集成(如使用 JSONB 存储值对象、使用外键约束保证聚合一致性、使用触发器记录领域事件)奠定了坚实的基础。