预测:多云

使用 SQL Azure 实现分支节点同步

Joseph Fultz


在我加入 Microsoft 之前和之后的几年里,我的工作主要与零售行业相关。有趣的是,在此期间,我曾“多次”看到分支节点同步问题随着科技的进步而得到解决。

我目前的工作与石油和天然气 (O&G) 行业有着相当广泛的联系,因而发现这个行业也面临在节点之间同步数据的问题。和连锁零售业类似,O&G 公司也拥有为数众多的设备,而且在连通方面也面临着挑战。无论是海洋石油平台上不为人察觉的卫星连接,还是油田中的工程师,都要求获得及时、准确的数据。

因此,综合零售业和 O&G 行业的情况,我准备再次接受这一挑战,但这次会借助 SQL Azure 和 Sync Framework 的一臂之力。我将论述云如何帮助解决在数据中心(公司)、分支(例如店面、钻井架、集散中心等)以及各种设备(手持设备、共享终端、特殊设备等)之间移动数据的问题。

这个月,我将重点更多地放在一般性的体系结构上,不会过多涉及具体的实施问题。不过我还是会给出几段示例代码,用于设置节点和 SQL Azure 之间的同步,并采用过滤内容的方式来减少同步所需的流量和时间。在下个月的专栏中,我将探讨使用基于服务的同步方法来提供可扩展的同步解决方案,不再局限于根据内容或地理分布在 SQL Azure 数据库中分散数据。

核心问题其实一直未变,改变的是由于技术进步而导致的其他要求。因此我们一开始并不去解决在节点之间移动数据的简单问题,而是添加我们希望拥有的内容,例如增加数据量以获得更多细节,涵盖多种多样的设备以收集和显示数据,以及几乎实时的源。

现实就是,我们拥有的越多,需要的也就越多。在大多数情况下,十年前就可以轻松地解决数据流问题,但在今天,这样的解决方案仅仅是为更可靠的解决方案提供了基础而已。零售业的数据流可能相当简单:采用向下推送目录类数据(菜单、仓库等)并向上回传交易记录的形式;也可能相当复杂:从分支到公司以及在分支之间经常更新库存水平、进行实时防损分析以及手工产品录入。大体上,O&G 公司也具有相同的模式,但是所用设备的操作、评估和调整使得复杂程度有所增加。我按以下几种方式考虑同步,从而对复杂程度有了一个大致的概念(实施和支持的复杂程度是逐步递增的):

  1. 从公司到分支以及再向下推送只读数据。
  2. 两次单向推送不同的数据:一次从公司到分支(例如目录),一次从分支到公司(例如交易记录和库存)。这包括分支到分支的推送,但重点是这基本上是两次或多次单向同步。
  3. 公司与节点之间双向数据同步(例如手动产品录入或员工信息)。
  4. 分支之间以及分支和公司之间的对等同步。

第 4 种类型是迄今为止最复杂的问题,通常会导致很多冲突。因此,我尽量避免使用此模式,而必须采用此模式的两项标准就是:需要在节点之间实时更新;如果公司数据存储不能访问,要求能够同步各个分支。因为在很多节点之间实时或准实时更新通常会导致过大的流量,所以通常不是合理的解决方案,而我真正需要注意的标准就是在没有主存储的情况下进行同步的能力。在某些情况下,节点之间需要实时信息,但数据同步通常并不需要实时信息。相反,它是一个事件通知方案,采用不同的方法来解决需求。

定义解决方案的体系结构

一般来说,我看到的最常见模式是从公司主数据库(通过某种类型的分发程序)将数据直接向下推送到分支的服务器以及移动用户。到工作站、销售点 (POS) 终端和其他此类设备的数据分发通常是在分支处的服务器(通常称为“后台服务器”)完成,而与移动用户(例如笔记本电脑)之间的同步则是通过客户端发起的同步进程直接从公司到机器之间完成(请参见图 1)。

图 1 数据分发的典型体系结构

某些组织通过关系数据库管理系统 (RDBMS) 内置的复制功能实现数据的分发,另外一些组织则构建相关的过程来处理数据的分发和收集。我将采用这种模式,但会使用 SQL Azure 实例替代分发程序,使用支持 SQL Azure 的 Sync Framework 替代复制功能。因此,我只需在分发程序和分支之间添加一层(请参见图 2)。

图 2 使用 SQL Azure 和 Sync Framework 的基本体系结构

插入 SQL Azure 有什么好处呢?分支节点方案的部分优势包括:

  1. 扩展数据服务而无需扩大数据中心。
  2. 无需额外的成本和工作,即可确保数据的高可用性。
  3. 减小潜在的安全隐忧,因为它不是主数据存储。

在第一种方案中,如果公司连接或数据存储宕机,所有客户端都必须暂停交易。如前文所述,如果等待连接时找不到设备或设备上的空间不足以存储交易,则这种方案很容易导致数据丢失。此外,如果分支拥有公用数据(例如仓库的库存数据),它们将一直使用旧数据工作,直到公司恢复正常。尽管并不存在完美的解决方案,SQL Azure 通过自动复制数据并提供自动的故障转移,足以应对这种情况。而且,通过将数据流分散到多个 SQL Azure 数据库,我可以减小宕机的风险。因为不仅可以使用独立的实例,还可以使用不同的数据中心,还能进一步减小负载压力。

从设计角度而言,我必须考虑从分支或从服务器开始同步的影响。如果将应用程序设计为从主存储或分发程序到节点进行同步,我得到的好处就是减少管理和支持工作;而不好的地方就在于会给实施带来一些限制,要求:

  1. 了解端点。
  2. 了解每个目标的合理范围。
  3. 为了使多个节点的同步能够并行发生,同步过程有一定的复杂度;API 语义一次只能有一对端点和一个范围。

通过从目标(例如节点或分支)开始同步,同步代码的复杂度降低了,因为这样:

  • 可以集中在应用程序/设备的范围。
  • 更容易处理偶尔连通的情况。
  • 只需了解和管理少数要同步分发数据的端点。

但是,这会给目标设备上的应用程序增加一定的复杂度,而且可能因必须调试每台设备上的同步过程或代理而使支持和维护变得更加复杂。理想情况下,如果必须在不同的应用程序之间同步数据,应该创建一个独立的过程,根据配置文件管理同步。配置文件中应该定义范围、频率和连接字符串,以便同步代理在运行时使用。此同步代理应该存在于应用程序(设备上的数据使用者)外部,尽管该过程可以让特定的应用程序启动其数据的同步。这样做的优势在于可以从节点启动同步,而且还减少了支持和维护工作,因为它最终会形成一个过程。

使用 Sync Framework,我倾向于采用混合同步模型,即从主数据存储启动与 SQL Azure 的同步,然后从节点启动 SQL Azure 与节点之间的同步。换言之,可以看作从主存储推出数据,从分支拉出数据,这样一来 SQL Azure 就成为主存储与分支之间一个高度可用的中心集散地。根据解决方案的需求和限制,我考虑了将同步过程控制权从一个点移动到链条中的另一个点(例如,设备到云或公司到云)所需要的成本以及各种优势。只有几个问题需要考虑,例如:

  • 主存储是否有地方放置该过程? 
  • 将同步过程放在 SQL Azure 中是否会与安全政策冲突?
  • 每个层级有多少节点要同步?
  • 目标设备能够实际支持同步过程吗?
  • 关于数据同步的时效性,有哪些要求?

更重要的是,这些问题都需要从多个层次去考虑,设计可能的解决方案时必须审视每个问题。虽然不存在普适的设计,我还是要从前面介绍的模型开始着手,或者执行多个单向同步以实现类似于双向数据同步的效果,或者在设备/公司数据库与 SQL Azure 之间使用双向同步。之后,我将考虑那些无效的方案,对设计进行修改。一般来说,我唯一需要避免的同步模式就是对等同步。

设置同步

使用 Sync Framework 2.1 设置同步的方法有两种:云中的同步客户端和本地机器上的同步客户端。目前我将主要介绍后者。简而言之,设置同步关系的步骤如下所示:

  1. 找出要同步的数据和数据流的方向。这在定义同步数据的范围 (SqlSyncScopeProvisioning) 时要用到。
  2. 下载并安装 Sync Framework 2.1 (bit.ly/gKQODZ)。注意:如果目标平台是 x64,则需要添加针对 x64 的生成目标,否则 SyncOrchestrator 无法解析其依赖关系。
  3. 配置要同步的数据库和表;可以配置整个数据库,也可以配置特定的表,或者限定为特定的列。
  4. 添加必要的过滤器。如果希望水平分割数据或以其他方式过滤数据,可以使用过滤器。
  5. 创建和运行同步过程。

我会详细解释这个示例,因为它有助于说明问题。我假设两端的数据库已经存在。我创建一个到本地数据库的连接,检索要同步的表的定义 (DbSyncTableDescription),并将这个表添加到范围 (DbSyncScopeDescription) 中。此外,我将指定某些列,但如果只是要同步整个表,则无需指定列。将同步关系限定到具体的列是优化带宽使用和加快处理速度的有效方法(请参见图 3)。

图 3 创建同步范围

SqlConnection azureConn = new SqlConnection(AzureConnectionString);
SqlConnection onPremiseConn = new SqlConnection(LocalConnectionString);

// List of columns to include
Collection<string> columnsToInclude = new Collection<string>();
columnsToInclude.Add("au_id");
columnsToInclude.Add("au_lname");
columnsToInclude.Add("au_fname");
columnsToInclude.Add("phone");
columnsToInclude.Add("address");
columnsToInclude.Add("city");
columnsToInclude.Add("state");
columnsToInclude.Add("zip");
columnsToInclude.Add("contact");

// Definition for authors from local DB
DbSyncTableDescription authorsDescription =
  SqlSyncDescriptionBuilder.GetDescriptionForTable("authors", 
  columnsToInclude, onPremiseConn);

// Create a scope and add tables to it
DbSyncScopeDescription authorScopeDesc = new DbSyncScopeDescription(ScopeName);

// Add the authors table to the sync scope
authorsScopeDesc.Tables.Add(authorsDescription);

对于每个要同步的结构,需要增加一点代码以进行说明;之后您必须将其添加到范围中。 下一步是获取范围配置对象,并使用该对象配置每个数据库(如果该数据库中尚不存在范围),如图 4 所示。

图 4 配置范围

// Create a provisioning object for "customers" and 
// apply it to the on-premises database
SqlSyncScopeProvisioning onPremScopeConfig = 
  new SqlSyncScopeProvisioning(onPremiseConn, authorsScopeDesc);
if (!(onPremScopeConfig.ScopeExists(authorsScopeDesc.ScopeName)))
{
  onPremScopeConfig.Apply():
}
// Provision the SQL Azure database from the on-premises SQL Server database
SqlSyncScopeProvisioning azureScopeConfig = 
  new SqlSyncScopeProvisioning(azureConn, authorsScopeDesc);
if (!(azureScopeConfig.ScopeExists(authorsScopeDesc.ScopeName)))
{
  azureScopeConfig.Apply();
}

因为这是第一次在数据库中配置范围,所以会有一些新的表用于存储范围信息,还有一个表专门用于跟踪数据库中配置的 Authors 范围。Sync Framework 团队的博客 bit.ly/dCt6T0 上提供了一个非常好的控制台应用程序示例,用于配置或同步本地与 SQL Azure 数据库。

边栏:SQL Azure 数据同步

SQL Azure 数据同步是 Windows Azure 中提供的一项基于云的服务,使用它可以在 SQL Server 和 SQL Azure 之间同步整个数据库或特定的表。在 2010 年 Microsoft 专业开发者大会期间,我们宣布推出该服务的更新SQL Azure 数据同步社区技术预览 (CTP) 2。各个组织可以利用此更新,将本地的 SQL Server 数据库扩展到云中,从而分阶段将应用程序迁移到云中。利用 SQL Azure 数据同步构建的解决方案可让用户继续访问本地数据,并在发生更改时将更改无缝同步到 SQL Azure。与此类似,应用程序对 SQL Azure 的更改也可以同步回本地的 SQL Server。

数据始终同步

SQL Azure 数据同步可为所有同步关系提供一个集中的基于云的管理系统。管理员可以从任意浏览器连接到该公共服务,管理和监控各种数据库端点。此外,SQL Azure 数据同步还提供一项计划服务,可使同步的频率高达每五分钟一次;也可以将首选项设置为在非高峰期执行同步,降低频率。

在最近的 SQL Azure 数据同步 CTP 2 更新中,我们还引入一个新组件,名为 SQL Azure数据同步代理。此代理是一项 Windows 服务,安装在客户内部,通过安全的出站 HTTPS 连接将本地 SQL Server 数据库链接到 SQL Azure 数据同步。因此从防火墙或安全配置角度而言,无需任何要求,就能快速完成设置工作。该代理的工作是监控和记录任务,并从 SQL Azure 数据同步启动同步请求。

新方案

使用 SQL Azure 数据同步,SQL Server 和 SQL Azure 数据库之间的同步能够提供大量新的方案,这些方案在过去都是很难构建的。假设您希望与分支办事处或零售店的数据库共享数据。使用 SQL Azure 数据同步,这将变得很容易,因为管理员可以创建“同步组”,用来定义要在数据库之间共享的数据。这些同步组可以包含公司的 SQL Server,该 SQL Server 将数据同步到中心的 SQL Azure“数据集散地”。然后,所有远程或区域性的 SQL Server 数据库可以从这个数据集散地同步数据更改,将数据带给用户,从而大幅减少带宽以及对虚拟专用网络 (VPN) 的需求。

此外,还可以在多个 SQL Azure 数据中心之间同步数据,因此更容易将负载扩展到多个地理区域。假设您每个季度都需要报告,而这会给 SQL Server 数据库施加巨大的周期性负载。为什么不在需要时将部分数据同步到遍布全世界的 SQL Azure 数据库呢?这样一来,用户就可以访问离他们最近的数据,同时减少对本地 SQL Server 的可伸缩性要求。

有关 CTP 2 的更多信息以及注册使用信息,请访问 microsoft.com/en-us/sqlazure/datasync.aspx

—SQL Azure 数据同步高级项目经理 Liam Cavanagh

同步数据

正确配置数据库之后,同步数据就很容易了。您需要为每个指定了范围的活动端创建 SqlSyncProvider。这需要使用 SyncOrchestrator 对象,它的作用就是找出更改,并在活动端之间移动更改。其代码如下所示:

SqlConnection LocalConnection = new SqlConnection(LocalConnectionString);
SqlConnection AzureConnection = new SqlConnection(AzureConnectionString);

SqlSyncProvider LocalProvider = new SqlSyncProvider(ScopeName, LocalConnection);
SqlSyncProvider AzureProvider = new SqlSyncProvider(ScopeName, AzureConnection);

SyncOrchestrator orch= new SynOrchestrator();
orch.LocalProvider = new SqlSyncProvider(ScopeName, LocalConnection);
orch.RemoteProvider = new SqlSyncProvder(ScopeName, AzureConnection);
orch.Direction = SyncDirectionOrder.DownloadAndUpload;
orch.Synchronize();

数据和地理位置分散

处理简单的数据复制之后,我就能集中精力优化部署体系结构和数据流。使用 Sync Framework,我可以指定过滤器。过滤器与 SQL Azure 结合,可以为分支节点体系结构带来巨大的益处。通过综合利用这两者,只需同步对某个区域或数据群体很重要的数据,我就可以让数据离最终使用者更近,优化带宽利用率(以及由此产生的费用)。无需在不同的地理位置使用数据服务器,数据可以同步到该地理区域中的 SQL Azure 实例,然后该地区的客户端再进行同步即可。

通过将数据分散到各个地理位置,并指定特定数据同步时的范围和频率,我们就可以精细控制传输的数据流内容、如何传输、何时传输以及传输多少,从而改善用户体验,因为用户体验与数据可用性和新鲜度直接相关。此外,对于要在各个地点之间穿梭的最终用户来说,能够了解所处位置是非常不错的,同步代理可以自行定位,以获得针对当前位置的同步数据。很多在制造/工厂环境中移动办公的工人获得的最新统计信息或报警信息,以及零售连锁业的区域经理获得的当日销售记录就是这一领域中很好的例证(请参见图 5)。

图 5 使用过滤器同步数据

启用过滤器并不比配置同步范围困难。因此,可以指定多个范围,使用不同的过滤器,或者不使用过滤器。对于每个要添加的过滤器,所需的改变只是添加两行代码:第一行向表中添加过滤器列,第二行添加过滤器子句,基本上是“where”条件。在我的示例中,我添加了一个州过滤器,以便只同步犹他州 (UT) 的数据更改,如下所示:

onPremScopeConfig.Tables["authors"].AddFilterColumn("state");
onPremScopeConfig.Tables["authors"].FilterClause = "[authors].[state] = 'UT'";

如果我希望根据过滤器进行双向同步,则需要添加两个范围,因为需要在两端配置范围。

更进一步以及散发数据

向体系结构中添加 SQL Azure(无论是单个实例还是多个数据库),即添加日益重要的间接层,可以在同步节点时真正增强数据可用性,改善整体性能。因为 SQL Azure 无需设计、配置和管理基础设施等工作,即可获得性能、可扩展性和可靠性。在下个月的专栏中,我将介绍具体的实施方法,演示如何使用十月份最新发布的 Sync Framework 4.0 CTP (bit.ly/dpyMP8) 将 Windows Azure 加入同步体系结构中。

Joseph Fultz 是达拉斯 Microsoft 技术中心的架构师,协助企业客户和 ISV 设计和制作软件解决方案以满足商业和市场需求。他在 Tech·Ed 及类似的内部培训活动中做过讲座。

衷心感谢以下技术专家对本文的审阅:David Browne