什么是Combo存储库和服务总线?

时间:2017-11-03 15:21:43

标签: nosql amazon-dynamodb

我正在学习更多有关NoSQL,特别是DynamoDB的知识。我最近问过这个问题:Mapping database structure from SQL Server to DynamoDB

在接受答复的评论中;答案是指服务总线和Combo存储库。

Q1)这是服务总线吗? (请参阅EventListener类):http://enterprisecraftsmanship.com/2015/05/06/combining-sql-server-and-mongodb-using-nhibernate/

Q2)什么是Combo存储库?它是一个“组合”存储库,即某些方法与多个数据库(SQL Server和DynamoDB)接口。

我经常会问回答者,但是我们开始转移到另一个问题的原始帖子 - 回答者提到了这一点。因此,我决定提出另一个问题。

1 个答案:

答案 0 :(得分:2)

  

我正在考虑使用NoSQL数据库来扩展数据库读取

好主意。听起来你正走在Command Query Responsibility Segregation(CQRS)的道路上。 NoSql数据库可以提供出色的读取存储。

您引用的link描述了要更新的技术 使用NHibernate组合SQL Server和MongoDB - 这就是我所说的'Combo'(组合)Repository。 “Combo Repository”不是标准模式。引用作者:

  

当然,理论上,我们可以将所有数据移动到某些NoSQL存储中,但如果我们不想完全摆脱我们的关系数据库呢?我们如何组合在一起?

您已使用Sql-ServerNoSql数据库标记了原始问题,因此您猜测自己位于Polyglot space

Repository Pattern是围绕数据持久性的非常常见的抽象层。

您引用的“组合”链接专门解决了多对多关系的问题(通常称为Sql中的连接表),以及存在许多此类关系时的性能影响。

从更一般的意义上讲,作为在NHibernate中提供拦截点的替代方法,您可能/可能不会通过存储库模式访问抽象数据。

这是C#中的一个超简单(非通用)存储库接口:

public interface IWidgetRepository
{
     Task<Widget> FetchWidget(string widgetKey);
     Task SaveWidget(Widget toBeSaved);
}   

假设我们已经有了一个SqlRepository:

public class SqlWidgetRepository : IWidgetRepository
{
     public async Task<Widget> FetchWidget(string widgetKey)
     {
         ... Code to use Obtain an NHibernate session and retrieve and deserialize Widget
     }
    ... Other methods here
}   

您还可以选择提供MongoDb实施

public class MongoWidgetRepository : IWidgetRepository
{
     public async Task<Widget> FetchWidget(string widgetKey)
     {
        ... Code to connect to a MongoDb secondary and Find() the 
           widget and deserialiaze into Widget
     }
    ... Other methods here
}   

为了同时维护这两个数据库,下面是这个“组合”存储库的外观示例:

public class ComboWidgetRepository : IWidgetRepository
{
     private readonly IWidgetRepository _repo1;
     private readonly IWidgetRepository _repo2;

     public ComboWidgetRepository(IWidgetRepository repo1, IWidgetRepository repo2)
     {
          repo1 = repo1;
          repo1 = repo2;
     }

     public async Task<Widget> FetchWidget(string widgetKey)
     {
          // Just need the one ... first one wins
          return await Task.WhenAny(repo1.FetchWidget(widgetKey), 
                                    repo2.FetchWidget(widgetKey));
     }

     public async Task SaveWidget(Widget toBeSaved)
     {
          // Need both to be saved
          await Task.WhenAll(repo1.SaveWidget(toBeSaved), 
                             repo2.SaveWidget(toBeSaved));
     }

上面的“组合”存储库可能很好地满足单个系统的需求(还有许多其他方法可以保持两个数据库同步)。

然而,CQRS经常在企业范围内使用(即,您有许多系统,有许多数据库)。

我对Enterprise Service Bus的评论只有在您需要在整个企业内分发数据时才有意义。

概念很简单

  • 命令在整个总线上排队到事务系统(例如“添加窗口小部件”)。
  • 您的系统处理小部件执行事务(例如,将小部件插入数据库)
  • 然后Widget系统向总线发布(广播)消息,详细说明已添加新小部件(包含所有相关小部件信息)
  • 企业中对Widgets更新感兴趣的其他系统订阅此消息并将更新他们自己的Widgets的Read Store表示(例如,更新为NoSql数据库或缓存,以及最有效的格式感觉到他们)。
  • 这样,当用户访问任何其他系统并查看有关“窗口小部件”的屏幕时,系统可以从其自己的读取存储中提供数据,而不必从Widget请求数据系统本身。