想从已将存储库从关系数据库迁移到 NoSQL 的任何人那里寻求任何建议吗?
我们目前正在使用 Postgres 数据库和 ORM (SQLAlchemy) 构建应用程序。但是,日后我们可能需要将应用程序迁移到当前仅支持几个 NoSQL 解决方案的环境。
考虑到这一点,我们正在遵循 Vaughn Vernon 的实现领域驱动设计中涵盖的以持久性为导向的存储库方法。这导致以下 API:
save(aggregate)
save_all(aggregates)
remove(aggregate)
get_by_...
无需详细说明,ORM 特定代码已隐藏在存储库本身中。 Session 仅用于检索或更新数据的短时间跨度,然后立即提交并关闭(在 repos 方法中)。这意味着大量合并保存,而不是最有效地使用 session 。
def save(aggregate):
try:
session.merge(aggregate)
commit
except:
rollback
def get():
try:
aggregate = session.query_by(id)
session.expunge
commit
except:
rollback
return aggregate
等等等等
优点:
- 我们将自己限制在每个用例更新单个聚合,因此在应用程序服务中充分利用 UOW 事务控制的情况很少(性能除外)。在写入聚合时,在存储库中启用事务控制,以确保完整的聚合被持久化。
- 没有 ORM 特定代码泄漏到存储库之外,无论如何在切换到 NoSQL 数据库时都需要重新编码。
因此,如果我们确实必须切换到 NoSQL 数据库,我们应该做最少的工作。
但是,我所读到的几乎所有内容都鼓励事务行为存在于应用程序服务层中。尽管我认为业务事务和数据库事务之间存在区别。
同样,我们正在处理性能问题,因为我们在每次调用存储库时都向 session 工厂请求一个 session 。大多数服务包含大约 3 次左右的存储库调用。
那么,对于从关系数据库迁移到 NoSQL 数据库的任何人来说,这个问题是什么?
工作单元/ session 的概念在 NoSQL 世界中有意义吗?
同时我们是否应该完全接受 ORM,并将 UOW/Session 从 Repository 移到 Application Service 中?
如果我们这样做,如果我们最终需要迁移到 NoSQL 解决方案,重新设计应用程序服务的努力程度如何。 (在任何情况下都需要重写存储库)。
最后,有人有丰富的编写与实现无关的存储库的经验吗?
附言。了解我们可以完全放弃 ORM 并同时使用纯 SQL,但我们被要求确保我们使用的是 ORM。
最佳答案
编辑:在这个答案中,我根据问题标题关注文档数据库。当然,存在具有截然不同特征的其他 NoSQL 存储(例如图形数据库、使用事件源等)。
这应该不是问题。
在文档数据库中,您的整个聚合应该是一个文档。通过这种方式,您可以获得与事务一致性所需的完全相同的保证。无论聚合中有多少实体发生变化,您仍然在存储文档。您将需要确保执行某种形式的乐观并发(通过 etag 或版本或类似方式),而不是工作单元模式,但在此之后您的事务需求得到满足。
我无法真正评论您现在是否完全接受 UoW 模式,与依赖 ORM 实现等相比。这在很大程度上取决于您的当前情况和实现细节。不过我可以说的是,您很可能不需要一次性从普通格式 (SQL) 迁移到文档。从一个简单的开始,这样您就可以了解哪些适合您,哪些不适合您。
我不知道是否存在与实现无关的存储库,但这对我来说意义不大。存储库的全部要点是封装持久性,因此您不能将其抽象化:不会分配给它们任何其他责任。此外,您不能假设存储库需要将不同的模型组合到聚合模型中:这是特定于平台的,所以它不是不可知的。
另一个最后的评论:我在你的问题中看到,对于你编写的文档,save_all(aggregates)
。我不确定你指的是什么,但至少,每个聚合保存都应该包装在它自己的事务中,否则这个操作违反了聚合的事务边界特性。
关于数据库:具有 NoSQL/文档数据库 (DDD) 的存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51583000/