预测:多云

强大的 Windows Azure

Joseph Fultz

 

Joseph Fultz就个人而言,我爱的东西周期的方法。我总是似乎每个对象或机制的演变表示二元性目的的进展和重述了过去的立场。技术是好地方看到这一点,因为,在其中更改已进行的步伐很容易在短时间内看到很多的演变。

对我来说,NoSQL 运动是只是这种演变。起初我们的文档,,我们让他们在文件中并在文件柜中,并最终在文件共享中。这是一个正常的事务状态。自然的问题是规模我们真的能环绕我们围绕着它的大脑。所以我们合理化内容选择合理化和规范化的数据模型,将帮助我们可以预见的是占用空间、 存储数据、 索引数据和能够找到它。理性模型的问题是因为他们不自然。

请输入 NoSQL,似乎混合的自然和关系模型。NoSQL 是一种优化的存储和检索大量数据的数据库管理系统。这是让我们保持文档样式的数据,仍可利用在日常生活的关系数据库管理系统 (RDBMSes) 中找到一些功能的方法。

NoSQL 的主要工具之一是从 10gen Inc.,面向文档的开源 NoSQL 数据库系统中,MongoDB,这个月我要去关注对 Windows Azure 环境中使用 MongoDB 的设计和实施方面的一些。我假设你知道一些有关 NoSQL 和 MongoDB。如果不是,您可能希望看一看朱莉列尔曼 2011 年 11 月的数据点的列,"什么到底是文献数据库吗?"(msdn.microsoft.com/magazine/hh547103),和.java 的可能 2010年工作程序员列中,"去 NoSQL 与 MongoDB"(msdn.microsoft.com/magazine/ee310029)。

要事第一

如果你正想尝试新的 MongoDB,或考虑它作为 Windows Azure SQL 数据库或 Windows Azure 表的替代方法,您需要注意的几个问题的设计与规划侧、 一些相关的基础设施和一些发展。

部署体系结构

一般情况下,返回的数据最终需要可用和持久。要用 MongoDB,可以做到这一点,请使用复制的一组。复制集提供故障切换和复制,使用一点点的人工智能 (AI) 以解决任何领带中选出主节点的集合。这意味着您的 Windows Azure 角色是您需要三个实例设置一个最小的复制集,再加上您可以为每个角色映射到一个驱动器的存储位置。请注意由于在虚拟机 (Vm) 中的差异,您可能要有至少中型 Vm 供任何重大部署。否则,该内存或 CPU 可以迅速成为瓶颈。

图 1 描述了典型的体系结构,向公众部署最少的 MongoDB ReplicaSet 不公开的。您可以将其公开的数据存储在外部,转换,但它是更好的办法,通过服务层。MongoDB 可以帮助其内置功能,通过地址的问题之一是设计和部署一个分布式的数据的体系结构。MongoDB 有一个完整的功能设置为支持尽可能 ; 与 ReplicaSets 结合该功能,Windows Azure 计算和你有的是高度可扩展的、 分布式的、 可靠的数据存储区。为了帮助您入门,10gen,提供了一个示例解决方案,设置最小的 ReplicaSet。你会发现在信息 bit.ly/NZROWJ ,你可以抓住文件从 GitHub 在 bit.ly/L6cqMF

Windows Azure MongoDB Deployment
图 1 Windows 天青 MongoDB 部署

数据架构

正在在 DB 架构设计的专家可能实际上阻碍你设计的 NoSQL 方法时。更像是对象建模与集成设计用于消息传递基础设施所需的技能。这有两个原因:

  1. 数据被看作是一个文档,并有时包含嵌套的对象或文档。
  2. 有最少支持联接,所以你要平衡的嵌套和调用客户端有必须要走的单一视图的数量的影响对数据的存储格式。

从一个关系的心态转移到 MongoDB 文档看的第一次活动之一重新设计的数据架构。对于某些独立关系模型中的对象,被保持分离。例如,产品和订单仍将单独的架构,在 MongoDB,和您仍将使用外键做两者之间的查找。简化了一点,这两个对象与另一个重新设计大多是通俗易懂的如中所示图 2

Direct Schema Translation
图 2 直接架构翻译

但是,它可能不一样容易当您使用分隔在概念上,尽管他们可能很容易和显然分隔关系模型中并不是那样干净的架构。例如,客户和 CustomerAddresses 都可能会合并这些客户将包含关联的地址的集合的实体 (请参见图 3)。

Converting Relational Schema to Nested Object Schema
图 3 转换为嵌套对象架构的关系架构

你需要仔细看看你的关系模型,并考虑每个外键关系,如何将会得到表示作为实体关系图中它翻译到 NoSQL 模型。

数据交互

同时查询行为和缓存行为是很重要的一个关联的系统,但它缓存在这里仍然是最重要的行为。多同 Windows Azure 表一样,很容易放进 MongoDB 的对象。并与 Windows Azure 表和更像是 Windows Azure SQL 数据库,不同的任何字段可以编制索引,允许单个对象的更好的查询性能。然而,缺乏的联接 (和普遍缺乏的查询表现力) 变成一次可能是同一个查询或多个联接厚实的数据返回到后端数据存储区的多个调用,以获取相同的数据。这可能有点令人生畏,如果你想要获取对象的集合,然后获取相关的集合的第一个集合中的每一项。因此,使用我的关系 pubs 数据库,我也许会写类似于以下操作,以获取所有作者姓氏和来自每个作者的所有书名的 SQL 查询:

    Select authors.au_lname, authors.au_id,
      titles.title_id, titles.title
    From authors inner join titleauthor
      on authors.au_id = titleauthor.au_id
      inner join titles on
      titles.title_id = titleauthor.title_id
    Order By authors.au_lname

与此相反,若要获取使用的 C# 驱动程序与 MongoDB 相同的数据,代码看起来像所示图 4

图 4 加入到 MongoDB 集合

MongoDatabase mongoPubs = _mongoServer.GetDatabase("Pubs");
MongoCollection<BsonDocument> authorsCollection =
  mongoPubs.GetCollection("Authors");
MongoCursor<BsonDocument> authors = authorsCollection.FindAll();
string auIdQueryString = default(string);           
Dictionary<string,BsonDocument> authorTitles =
  new Dictionary<string,BsonDocument>();
// Build string for "In" comparison
// Build list of author documents, add titles next
foreach (BsonDocument bsonAuthor in authors)
{
  auIdQueryString = bsonAuthor["au_id"].ToString() + ",";
  authorTitles.Add(bsonAuthor["au_id"].ToString(), 
    new BsonDocument{{"au_id",
    bsonAuthor["au_id"].ToString()},
   {"au_lname", bsonAuthor["au_lname"]}});
   authorTitles.Add("titles",
   new BsonDocument(new Dictionary<string,object>()));
}
// Adjust last character
auIdQueryString = auIdQueryString.Remove(auIdQueryString.Length-1,1);
// Create query
QueryComplete titleByAu_idQuery = Query.In("au_id", auIdQueryString);
Dictionary<string, BsonDocument> bsonTitlesToAdd =
  new Dictionary<string,BsonDocument>();
// Execute query, coalesce authors and titles
foreach (BsonDocument bsonTitle in 
  authorsCollection.Find(titleByAu_idQuery))
{
  Debug.WriteLine(bsonTitle.ToJson());
  // Add to author BsonDocument
  BsonDocument authorTitlesDoc = 
    authorTitles[bsonTitle["au_id"].ToString()];
  ((IDictionary<string, object>) authorTitlesDoc["titles"]).Add(bsonTitle["title_id"].ToString(), 
      bsonTitle);
}

有你可能优化这通过代码和结构,但不要错过虽然 MongoDB 是适合甚至对嵌套对象直接查询,更复杂的查询,需要跨实体集是一个好一点点的点的方法 … … 嗯,让我们只是说更多的手册。 我们大多数人使用 LINQ 帮助桥对象-关系的世界。 与 MongoDB 有趣的事是要将这座桥,但相反的原因 — — 你会错过的关系的功能。

你也可能会错过参照约束,尤其是外键约束。 因为确实可以添加任何 MongoDB 集合中,项目可能有也可能不正确的数据以使其与其他实体相关。 虽然这看起来像一个失败的平台如果你是一个顽固的 RDBMS 风扇,它不是。 事实上,它是在哲学中的离境。 一般情况下,对于 NoSQL 数据库想法是移动系统不数据存储区中的情报,让上读取和写入数据的存储集中的数据。 因此,如果你觉得需要显式强制使用外键约束像 MongoDB 实现中的东西,你会做通过业务或服务层,坐在前面的数据存储。

迁移

一旦你已经重新设计的数据架构和考虑查询行为的要求是要获取一些数据,在云计算以便使用它的时候。

坏消息是有没有向导,您可以指向您的 Windows Azure SQL 数据库实例和您的 MongoDB 实例并单击迁移。 您将需要编写一些脚本,在外壳程序中或在代码中。 幸运的是,如果 MongoDB 侧方程的代码构造很好,你会能够重用部分好它正常运行时运行的解决方案。

第一步引用的 MongoDB.Bson 和蒙戈­DB。驱动程序库和使用添加的语句:

using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Bson.Serialization.IdGenerators;
using MongoDB.Bson.Serialization.Options;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver.Builders;
using MongoDB.Driver.GridFS;
using MongoDB.Driver.Wrappers;

对象然后将显示一些新的方法,对他们都非常有用,当你试图从常规.net 对象移动到与 MongoDB 一起使用的 Bson 对象。 作为图 5 所示,这变得很明显,从数据库读取到 BsonDocument 将保存到 MongoDB 转换的输出行的函数中。

图 5 数据迁移与 LINQ 和 MongoDB

pubsEntities myPubsEntities = new pubsEntities();
var pubsAuthors = from row in myPubsEntities.authors
  select row;
MongoDatabase mongoPubs = _mongoServer.GetDatabase("Pubs");
mongoPubs.CreateCollection("Authors");
MongoCollection<BsonDocument> authorsCollection =
  mongoPubs.GetCollection("Authors");
BsonDocument bsonAuthor;
foreach (author pubAuthor in pubsAuthors)
{
  bsonAuthor = pubAuthor.ToBsonDocument();
    authorsCollection.Insert(bsonAuthor);
}

中的简单示例图 5 将直接使用 MongoDB 扩展方法的数据转换。 不过,你必须小心,尤其是与 LINQ,当执行此操作的类型。 例如,如果我尝试直接为标题相同的操作,Titles 表中的实体模型中的对象图的深度将导致 MongoDB 驱动程序产生一个堆栈溢出错误。 在这种情况下,转换会稍微详细在代码中,如中所示图 6

图 6 转换值的单独

pubsEntities myPubsEntities = new pubsEntities();
var pubsTitles = from row in myPubsEntities.titles
  select row;
MongoDatabase mongoPubs = _mongoServer.GetDatabase("Pubs");
MongoCollection<BsonDocument> titlesCollection =
  mongoPubs.GetCollection("Titles");
BsonDocument bsonTitle;
foreach (title pubTitle in pubsTitles)
{
  bsonTitle = new BsonDocument{ {"titleId", pubTitle.title_id},
     {"pub_id", pubTitle.pub_id},
     {"publisher", pubTitle.publisher.pub_name},
     {"price", pubTitle.price.ToString()},
     {"title1", pubTitle.title1}};
  titlesCollection.Insert(bsonTitle);
}

要转换保持尽可能简单,最好的办法是编写 SQL 查询,以返回可以更轻松地添加到适当的 MongoDB 集合的单个实体。 有子文档集合的 BsonDocuments,它将采取多步的方法来创建父 BsonDocument,将儿童 BsonDocuments 添加到父 BsonDocument,然后添加到集合的父级。

你需要如果从 Windows Azure SQL 数据库移动到 MongoDB 执行转换的明显位是代码的所有生活在存储过程、 视图和触发器。 在许多情况下,代码会更简单一些,因为您会将处理同一个 BsonDocument 你坚持下去的儿童而不必跨多个表的关系约束工作整体。 此外,而不是编写 TSQL,你可以使用您喜欢的.net 语言,Visual Studio IDE 的所有支持。 可能不最初占的代码是你要创建,以便能够跨文档做交易。 在某种意义上,它是疼痛,不得不将所有的平台功能的 Windows Azure SQL 数据库移动到应用程序代码。 另一方面,一旦你完成你得非常快速和可扩展的数据的后端,因为它只重点数据穿梭。 您还可以通过移动的所有以前被困在 RDMBS 到适当的中间层,逻辑的高度可扩展的中间层。

最后一点要注意一些意义的是由于数据存储区的性质,数据大小将有可能增加。 这是因为每个文档已持有架构和数据。 虽然这可能不是最大,因为低成本的空间在 Windows Azure 表中非常重要的它仍需要必须在设计中考虑的东西。

最后的思考

一旦在 MongoDB 中可用的数据,则使用它会,在许多方面,感觉熟悉。

到 C# (当前的 1.5.0.4566) 驱动 1.4 LINQ 支持大大增加,因此,编写的代码不会感到完全陌生。 因此,如果您的项目或解决方案可能会像 MongoDB NoSQL 数据存储区中的受益,不要让吓唬你的语法,因为调整将会最小。 但是请记住,有一个成熟的、 稳健的 RDBMS 平台之间的一些重要差异 — — 例如 Windows Azure SQL 数据库 — — 和 MongoDB。 例如,健康和监测将需要更多的手动工作。 而不是监测只有一些 Windows Azure SQL 数据库实例的数目,你要监视主机工作者角色、 Windows Azure Blob 存储主机的数据库文件和日志文件的 MongoDB 本身。

NoSQL 解决方案提供卓越的性能,某些数据库操作和一些有用的、 有趣的功能,真的可以给一个解决方案开发团队带来的好处。 如果您有大量的数据,并且你在有限的预算,Windows Azure 选项 MongoDB 可能是您的解决方案体系结构的一大补充。

Joseph Fultz 是 Hewlett-Packard Co. 的软件架构师,参与 HP.com 全球 IT 小组的工作。 以前他是 Microsoft 的软件架构师,协助 Microsoft 顶层企业和 ISV 客户定义体系结构和设计解决方案。

衷心感谢以下技术专家对本文的审阅:温明叶