【问题标题】:Domain events and DB generated ID as a part of atomic process域事件和数据库生成的 ID 作为原子进程的一部分
【发布时间】:2017-07-24 12:48:43
【问题描述】:

我在 DDD 中使用最终一致性和域事件,但遇到了以下问题。

使用工厂创建域对象时,我可以生成 GUID,但无法获取 DB 生成的 ID 以返回有效 ID 作为响应的一部分。

在同一事务中持久化域对象并避免等待最终一致性时,是否有可能以及如何使用域事件获取数据库生成的 ID。

DB 生成的 ID 是同一聚合根和存储库的一部分。

【问题讨论】:

  • 为什么需要这些数据库 ID?
  • 例如,用户发布rest api请求以创建某种类型的对象,而在rest api响应中,用户期望该新对象的ID(以用户友好的格式,而不是guid)
  • 请参阅here 如何以人类可读的方式表示 GUID
  • 当然,但我需要整数作为 ID
  • Herehere

标签: domain-driven-design eventual-consistency domain-events


【解决方案1】:

我认为你可以有两种选择:

  1. 如果对象创建成本不高,则不必最终保持一致。在DB中创建对象并返回生成的ID。

  2. 如果代价高昂,请将对象创建分解为小单元。根对象应该简单快速地创建,以便在数据库中持久化并返回生成的 ID。让其他子对象/聚合通过事件/消息最终一致地创建。

【讨论】:

    【解决方案2】:

    我见过的似乎效果最好的方法是让 SQL db 服务器带有一个完整的 IDENTITY 列来发出 ID,这在实际创建实体之前需要执行(例如,在创建命令时)如果您也使用 CQRS)。这种方法实际上很容易实现和支持,并且只需要在您的数据库中添加一个表(甚至不需要)。这种做法并不少见,并且使您的 bc 从拥有 ID 生成逻辑的责任中解脱出来(在某些情况下,这可能非常有用)。

    注意:与我们软件世界中的所有事物一样,这需要权衡取舍:

    1. 它可以保证排序但如果某个具有一个 id 的操作失败并且您重试您的操作,则 id 的序列可能会有间隙。仅当您关心订购实体的创建时,这才重要:)
    2. 这会影响性能,因为您有一个瓶颈(老实说,您需要有非常大的流量才能成为一个明显的问题,所以我不会认为这是一个大问题)
    3. 在某些情况下,这可能是一个安全问题,具体取决于此 ID 的使用方式。

    我不得不说,以上所有观点都很小众,我不认为真的会成为问题。

    有关此实践的参考和更多信息,您可以阅读 Twitter 的 Snowflake 项目。 Snowflake 生成顺序的类似 guid 的 64 位整数 id,但很多(如果不是全部)原则仍然适用于这种情况。在很多讨论 Snowflake 的文章中有很多关于这种做法的信息和最佳做法。

    问候, 萨瓦斯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-28
      • 2014-01-27
      相关资源
      最近更新 更多