正在寻找将其存储库从关系数据库迁移到NoSQL的任何人的建议吗?
我们当前正在使用Postgres数据库和ORM(SQLAlchemy)构建应用程序。但是,有可能以后我们可能需要将App迁移到当前仅支持几种NoSQL解决方案的环境。
考虑到这一点,我们正在遵循持久化方法来处理Vaughn Vernon的《实现域驱动设计》中涵盖的存储库。这将产生以下API:
save(aggregate)
save_all(aggregates)
remove(aggregate)
get_by_...
无需详细说明,特定于ORM的代码已隐藏在存储库本身中。会话仅在检索或更新数据然后立即提交和关闭(在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
等等等
优点:
因此,如果我们必须切换到NoSQL DB,我们应该要做的工作最少。
但是,我阅读的几乎所有内容都鼓励事务性行为存在于应用程序服务层中。尽管我相信Business Transactional和DB Transactional之间存在区别。
同样,我们正在影响性能,因为我们要求会话工厂在每次调用存储库时进行一次会话。大多数服务包含大约3个对存储库的调用。
那么,对于从Relational迁移到NoSQL DB的任何人来说,这是一个问题吗?
工作单元/会话的概念在NoSQL世界中意味着什么吗?
我们是否应该同时完全接受ORM,并将UOW /会话从存储库之外移至应用程序服务中?
如果这样做的话,如果最终需要迁移到NoSQL解决方案,那么重新设计应用程序服务的工作量是多少? (在任何情况下都需要重写存储库。)
最后,有人在编写与实现无关的存储库方面有很多经验吗?
PS。理解我们可以完全删除ORM并同时使用纯SQL,但是我们被要求确保我们正在使用ORM。
答案 0 :(得分:1)
编辑:在此答案中,我重点关注基于问题标题的文档数据库。当然,存在其他NoSQL存储,它们具有截然不同的特征(例如,使用事件源等的图数据库)。
这真的不是问题。
在文档数据库中,您的整个集合应该是一个文档。这样,您就可以完全相同地保证事务一致性。无论聚合中有多少实体发生更改,您仍在存储文档。您需要确保执行某种形式的开放式并发(通过etag或版本或类似方法),而不是工作单元模式,但是在此之后,您的交易要求就可以满足了。
我现在无法真正评论您是否完全采用UoW模式,还是依赖ORM实现等。这实际上很大程度上取决于您的当前状况和实现细节。我可以说的是,您很有可能不需要一次从标准格式(SQL)迁移到文档。从一个简单的例子开始,这样您就可以看到对您有用的,对您无效的。
我不知道与实现无关的存储库是否存在,但这对我来说意义不大。存储库的重点是封装持久性,因此您不能抽象化它:不会向他们分配任何其他职责。另外,您不能假定存储库需要将不同的模型组合到聚合模型中:这是特定于平台的,因此不是不可知的。
另一个最后的评论:在您的问题中,我看到您写了save_all(aggregates)
的文档。我不确定您要指的是什么,但是至少每个聚合保存都应包装在自己的事务中,否则此操作违反了Aggregate的事务边界特性。
答案 1 :(得分:0)
工作单元/会话的概念在NoSQL中是否有意义? 世界?
是的,它仍然是一个有趣的概念。仅仅因为您正在使用NoSQL存储,并不意味着不再需要某种业务事务管理。许多NoSQL数据库都有驱动程序或第三方库来管理更改跟踪。例如,请参见RavenDB。
当然,如果您每笔交易仅加载一个汇总,并且您的NoSQL存储单元与汇总完全匹配,那么大多数工作单元功能将不再那么重要,但是您仍将面临例外规则。此外,UoW中无论如何都与之相关的部分是提交,甚至可能中止。
同时我们应该完全接受ORM并移动 存储库外部的UOW /会话进入应用程序服务?
相反,我建议在完整的课程中具体体现“工作单元”的概念:
class UnitOfWork {
void Commit()
{
// Call your ORM persistence here
}
}
应用程序服务只是工作单元的调用位置,而不是其实现的位置。
如果我们这样做,重新设计产品的工作量是多少? 应用服务,如果我们需要迁移到NoSQL解决方案中 结束。 (在任何情况下都需要重写存储库。)
这取决于许多其他参数,例如NoSQL API或第三方库对工作单元的支持,以及聚合和NoSQL存储之间的形状相似。它的范围从几乎没有工作到自己编写完整的UoW /变更跟踪实现。如果是后者,那么从存储库中将UoW逻辑提取到一个单独的类将不是最困难的工作。
最后,任何人都具有编写不可知的实现的丰富经验 存储库?
我在这里同意SKleanthous-与实现无关的存储库在IMO中没有多大意义。您已经有了存储库抽象(接口),它们当然是不可知的,但是当涉及到实现时,您必须处理特定的持久性存储。