自动故障转移组概述 & Azure (最佳做法SQL 托管实例)

适用于: Azure SQL 托管实例

通过自动故障转移组功能,可以管理托管实例中所有用户数据库到另一区域的复制和故障转移。 本文重点介绍如何将自动故障转移组功能与 Azure SQL 托管实例和一些最佳做法一起使用。

若要开始,请参阅配置自动故障转移组。 有关端到端体验,请参阅自动故障转移组教程

注意

本文介绍 Azure SQL 托管实例的自动故障转移组。 有关 Azure SQL 数据库,请参阅 SQL 数据库中的自动故障转移组

概述

通过自动故障转移组功能,可以管理服务器中一组数据库或托管实例中所有用户数据库到另一区域的复制和故障转移。 它是建立在现有活动异地复制功能基础之上的声明性抽象,旨在简化异地复制的数据库的大规模部署和管理。

自动故障转移

可以手动启动故障转移,也可以基于用户定义的策略委托 Azure 服务进行故障转移。 使用后一种做法可在发生下述情况后自动恢复次要区域中的多个相关数据库:灾难性故障或其他导致主要区域中 SQL 数据库或 SQL 托管实例完全或部分丧失可用性的计划外事件。 通常无法通过内置的高可用性基础结构自动缓解这些服务中断。 异地故障转移触发器的示例包括自然灾难或因计算节点上的操作系统内核内存泄漏而导致租户或控制环关闭的事件。 有关详细信息,请参阅 Azure SQL 高可用性

卸载只读工作负载

为了减少对主数据库的流量,还可以使用故障转移组中的辅助数据库来卸载只读工作负载。 使用只读侦听器将只读流量定向到可读辅助数据库。

终结点重定向

自动故障转移组提供在异地故障转移期间保持不变的读写和只读侦听器终结点。 这意味着,在异地故障转移后无需更改应用程序的连接字符串,因为连接会自动路由到当前主副本。 无论使用手动故障转移激活还是自动故障转移激活,异地故障转移都会将组中所有的辅助数据库切换为主角色。 异地故障转移完成后,会自动更新 DNS 记录,以便将终结点重定向到新的区域。 有关异地故障转移 RPO 和 RTO 的信息,请参阅业务连续性概述

恢复应用程序

为了实现完整的业务连续性,添加区域数据库冗余只是解决方案的一部分。 在发生灾难性故障后,端对端地恢复应用程序(服务)需要恢复构成该服务的所有组件以及所有依赖服务。 这些组件的示例包括客户端软件(例如,使用自定义 JavaScript 的浏览器)、Web 前端、存储和 DNS。 所有组件必须能够弹性应对相同的故障,并在应用程序的恢复时间目标 (RTO) 值内变为可用,这一点非常关键。 因此,需要识别所有依赖服务,并了解它们提供的保证和功能。 然后,必须执行适当的步骤来确保对用户的服务所依赖的服务执行故障转移期间,用户的服务能够正常运行。

术语和功能

  • 故障转移组 (FOG)

    故障转移组允许托管实例中的每个用户数据库作为单元故障转移到另一个 Azure 区域,以防主托管实例因主要区域中断而不可用。 由于 SQL 托管实例的故障转移组包含该实例中的所有用户数据库,因此,在一个实例上只能配置一个故障转移组。

    重要

    故障转移组的名称在 .database.chinacloudapi.cn 域中必须全局唯一。

  • 主要节点

    托管故障转移组中主数据库的托管实例。

  • 辅助节点

    托管故障转移组中辅助数据库的托管实例。 辅助数据库不能与主数据库位于相同的 Azure 区域。

  • DNS 区域

    创建新 SQL 托管实例时自动生成的唯一 ID。 将为此实例预配一个多域 (SAN) 证书,以便对与同一 DNS 区域中的任何实例建立的客户端连接进行身份验证。 同一故障转移组中的两个托管实例必须共享 DNS 区域。

  • 故障转移组读写侦听器

    DNS CNAME 记录,指向当前主要数据库。 此记录是创建故障转移组时自动创建的,可让读写工作负载在故障转移发生后主节点发生更改时,以透明方式重新连接到主数据库。 在 SQL 托管实例上创建故障转移组时,侦听器 URL 的 DNS CNAME 记录格式为 <fog-name>.<zone_id>.database.chinacloudapi.cn

  • 故障转移组只读侦听器

    DNS CNAME 记录,指向当前辅助数据库。 此记录是创建故障转移组时自动创建的,可让只读 SQL 工作负载在故障转移发生后辅助节点发生更改时,以透明方式连接到辅助数据库。 在 SQL 托管实例上创建故障转移组时,侦听器 URL 的 DNS CNAME 记录格式为 <fog-name>.secondary.<zone_id>.database.chinacloudapi.cn

  • 自动故障转移策略

    默认使用自动故障转移策略配置故障转移组。 检测到失败并且宽限期到期后,系统会触发异地故障转移。 系统必须确保,因影响范围太大等,内置高可用性基础结构无法缓解服务中断。 如果要从应用程序或手动控制异地故障转移工作流,可以关闭自动故障转移策略。

    注意

    由于验证中断规模及其缓解速度涉及到人工操作,因此不能将宽限期设置为一小时以下。 此限制适用于故障转移组中的所有数据库,不管其数据同步状态如何。

  • 只读故障转移策略

    默认禁用只读侦听器的故障转移功能。 这可确保在辅助数据库脱机时,主数据库的性能不会受到影响。 但是,这也意味辅助数据库恢复前,只读会话将无法连接。 如果不能容忍只读会话停机,但能容忍以主数据库的潜在性能降级为代价将主数据库用于只读和读写流量,则可以通过配置 AllowReadOnlyFailoverToPrimary 属性为只读侦听器启用故障转移。 在这种情况下,如果辅助节点不可用,则会将只读流量自动重定向到主要节点。

    注意

    仅当启用了自动故障转移策略并且已触发自动异地故障转移时,AllowReadOnlyFailoverToPrimary 属性才有效。 在这种情况下,如果将该属性设置为 True,则新的主数据库将同时处理读写会话和只读会话。

  • 计划的故障转移

    将辅助角色切换为主角色之前,计划内故障转移在主数据库与辅助数据库之间执行完整数据同步。 这可以保证数据不会丢失。 计划内故障转移用于以下场景:

    • 不可接受数据丢失时在生产环境中执行灾难恢复 (DR) 演练
    • 将数据库重新定位到不同的区域
    • 缓解服务中断(故障回复)后将数据库恢复到主要区域

    注意

    如果数据库包含内存中 OLTP 对象,则主数据库和目标辅助异地复制数据库应具有匹配的服务层级,因为内存中 OLTP 对象始终在内存中合成。 如果目标异地复制数据库上的服务层级较低,可能会导致内存不足问题。 如果发生这种情况,受影响的异地辅助数据库副本可能会进入一种受限的只读模式,称为“内存中 OLTP 仅检查点”模式。 允许只读表查询,但受影响的异地辅助数据库副本不允许只读内存中 OLTP 表查询。 如果异地辅助数据库中的所有副本处于仅检查点模式,则计划的故障转移被阻止。 由于内存不足问题,计划外故障转移可能会失败。 为了避免这种情况,请升级辅助数据库的服务层级,使其在计划的故障转移期间与主数据库匹配,或进行钻取。 服务层级升级操作会针对不同的数据大小,可能需要一段时间才能完成。

  • 未计划的故障转移

    计划外故障转移或强制故障转移立即将辅助角色切换为主角色,而不会等待从主角色传播最近的更改。 此操作可能导致数据丢失。 在服务中断期间当主要节点不可访问时,计划外故障转移将用作恢复方法。 缓解中断时,旧的主数据库将自动重新连接,并成为新的辅助数据库。 可以执行计划内故障转移以进行故障回复,将副本返回到其原来的主和辅助角色。

  • 手动故障转移

    可随时手动启动异地故障转移,而不考虑自动故障转移配置。 在中断影响主要角色的情况下,如果未配置自动故障转移策略,则需要进行手动故障转移,以将辅助角色提升为主要角色。 可以启动强制(计划外)或友好的(计划内)故障转移。 只有在可以访问旧的主数据库时,才可以使用友好的故障转移,并且可以用来将主数据库重新定位到次要区域,而不会丢失数据。 故障转移完成后,会自动更新 DNS 记录,以确保与新的主要副本建立连接。

  • 数据丢失宽限期

    由于数据是通过异步复制复制到辅助数据库的,因此自动异地故障转移可能会导致数据丢失。 可以自定义自动故障转移策略,以便反映应用程序对数据丢失的容错。 通过配置 GracePeriodWithDataLossHours,可以控制系统启动可能导致数据丢失的强制故障转移之前的等待时间。

故障转移组体系结构

自动故障转移组必须在主要实例上进行配置,需将其连接到不同 Azure 区域中的辅助实例。 实例中的所有用户数据库将复制到辅助实例。 不会复制 mastermsdb 这样的系统数据库。

下图演示了使用托管实例和自动故障转移组的异地冗余云应用程序的典型配置:

SQL MI 的自动故障转移组示意图

如果应用程序使用 SQL 托管实例作为数据层,进行业务连续性设计时,请遵循以下一般准则和本文列出的最佳做法。

创建异地辅助实例

若要确保故障转移后与主要 SQL 托管实例的连接不中断,主要实例和辅助实例必须位于同一 DNS 区域。 这将确保可以使用同一多域 (SAN) 证书来验证客户端与故障转移组中两个实例中任一实例的连接。 准备好将应用程序部署到生产环境后,在不同的区域中创建一个辅助 SQL 托管实例,并确保它与主要 SQL 托管实例共享 DNS 区域。 可以通过在创建期间指定可选参数来实现。 如果使用 PowerShell 或 REST API,则可选参数的名称为 DNSZonePartner。 Azure 门户中相应可选字段的名称是主要托管实例。

重要

在子网中创建的第一个托管实例确定同一子网中所有后续实例的 DNS 区域。 这意味着,同一子网中的两个实例不能属于不同的 DNS 区域。

有关在主要实例所在的 DNS 区域中创建辅助 SQL 托管实例的详细信息,请参阅创建辅助托管实例

使用配对区域

出于性能方面的考虑,将两个托管实例部署到配对区域。 与非配对区域相比,配对区域中的 SQL 托管实例故障转移组具有更好的性能。

启用和优化实例之间的异地复制通信流

必须建立和维护托管主实例和辅助实例的虚拟网络子网之间的连接,确保异地复制通信流不间断。 有多种方法可以在实例之间提供连接,你可以根据网络拓扑和策略从中进行选择:

重要

建议使用全局虚拟网络对等互连(VNet 对等互连),在故障转移组中的两个实例之间建立连接。 它使用 Microsoft 主干基础结构,在对等互连的虚拟网络之间提供低延迟、高带宽的专用连接。 在对等互连的虚拟网络之间通信不需公共 Internet、网关或额外加密。 自 2020 年 9 月 22 日以来创建的子网中托管的实例支持全局虚拟网络对等互连。 若要能够对在 2020 年 9 月 22 日之前创建的子网中托管的 SQL 托管实例使用全局虚拟网络对等互连,请考虑在实例上配置非默认维护时段,因为它会将实例移动到支持全局虚拟网络对等互连的新虚拟群集中。

无论连接机制如何,都必须满足异地复制通信流的要求:

  • 托管主实例的子网上的网络安全组 (NSG) 规则允许:
    • 来自托管辅助实例的子网的端口 5022 和端口范围 11000-11999 上的入站流量。
    • 发往托管辅助实例的子网的端口 5022 和端口范围 11000-11999 上的出站流量。
  • 托管辅助实例的子网上的网络安全组 (NSG) 规则允许:
    • 来自托管主实例的子网的端口 5022 和端口范围 11000-11999 上的入站流量。
    • 发往托管主实例的子网的端口 5022 和端口范围 11000-11999 上的出站流量。
  • 托管主实例和辅助实例的 VNet 的 IP 地址范围不得重叠。
  • 托管主实例和辅助实例的 VNet 与它们通过本地虚拟网络对等互连或其他方式与之对等互连的任何其他 VNet 之间没有间接的 IP 地址范围重叠

此外,如果使用其他机制(而不是使用建议的全局虚拟网络对等互连)来提供实例之间的连接,则需要确保:

  • 使用的任何网络设备(例如防火墙或网络虚拟设备 (NVA))都不会阻止上述流量。
  • 路由已正确配置,并且避免了非对称路由。
  • 如果在跨区域的中心辐射型网络拓扑中部署自动故障转移组,复制流量应直接在两个托管实例子网之间传输,而不是通过中心网络来定向。 这将有助于避免连接和复制速度问题。

重要

在涉及其他网络设备的实例之间提供连接的其他方法可能会导致在出现连接或复制速度问题时很难完成故障排除过程,并且需要网络管理员的积极参与解决,会显著延长解决时间。

初始种子设定

在托管实例之间建立故障转移组时,在数据复制开始之前,会有一个初始种子设定阶段。 初始种子设定阶段是操作过程中耗时最长且开销最大的阶段。 初始种子设定完成后,数据将会同步,但只会复制后续的数据更改。 完成初始种子设定所需的时间取决于数据大小、复制的数据库数、主数据库的工作负荷强度,以及托管主实例和辅助实例的虚拟网络之间的链接速度,该速度主要取决于建立连接的方式。 在正常情况下,使用推荐的全局虚拟网络对等互连建立连接时,SQL 托管实例的种子设定速度高达每小时 360 GB。 为一批用户数据库并行执行种子设定,不必同时为所有数据库执行种子设定。 如果实例上托管了许多数据库,可能需要多个批次。

如果两个实例之间的链接速度比所需速度慢,则种子设定时间可能会受到明显影响。 可以根据所述种子设定速度、数据库数量、数据总大小和链接速度,来估算在数据复制开始之前初始种子设定阶段花费的时间。 例如,对于单个 100 GB 的数据库,如果链路每小时能够推送 84 GB 数据,并且没有其他数据库正在进行种子设定,则初始种子设定阶段大约需要 1.2 小时。 如果链路每小时只能传输 10 GB,则为 100 GB 数据库设定种子需要大约 10 小时。 如果有多个数据库要复制,则种子设定将会并行执行,在链接速度较慢的情况下,初始种子设定阶段可能需要相当长的时间,尤其是为所有数据库中的数据并行设定种子超过可用的链接带宽时。

重要

如果由于链接速度极慢或繁忙而导致初始种子设定阶段需要花费数天时间,则故障转移组创建可能超时。创建过程将在 6 天后自动取消。

管理到异地辅助实例的异地故障转移

故障转移组将管理主要托管实例上所有数据库的异地故障转移。 创建某个组后,实例中的每个数据库将自动异地复制到异地辅助实例。 无法使用故障转移组针对一部分数据库启动部分故障转移。

重要

如果从主要托管实例中删除了某个数据库,该数据库也会在异地辅助托管实例上自动删除。

使用读写侦听器(主 MI)

对于读写工作负载,使用 <fog-name>.zone_id.database.chinacloudapi.cn 作为服务器名称。 连接将自动定向到主数据库。 此名称在故障转移后不会更改。 异地故障转移涉及更新 DNS 记录,因此,仅在刷新客户端 DNS 缓存后,新客户端连接才会路由到新的主数据库。 由于辅助实例与主要实例共享 DNS 区域,客户端应用程序可以使用相同的服务器端 SAN 证书重新连接到辅助实例。 需要终止现有客户端连接,然后重新创建它们,然后才能将它们路由到新的主数据库。 无法通过托管实例的公共终结点访问读写侦听器和只读侦听器。

使用只读侦听器(辅助 MI)

如果逻辑上隔离的只读工作负载可以容忍数据延迟,则可以在异地辅助数据库上运行。 若要直接连接到异地辅助数据库,请使用 <fog-name>.secondary.<zone_id>.database.chinacloudapi.cn 作为服务器名称。

在业务关键层级中,SQL 托管实例支持通过只读副本,使用连接字符串中的 参数卸载只读查询工作负载。 如果配置了异地复制的辅助节点,则可以使用此功能连接到主要位置或异地复制位置中的只读副本:

  • 若要连接到主要位置中的只读副本,请使用 ApplicationIntent=ReadOnly<fog-name>.<zone_id>.database.chinacloudapi.cn
  • 若要连接到辅助位置中的只读副本,请使用 ApplicationIntent=ReadOnly<fog-name>.secondary.<zone_id>.database.chinacloudapi.cn

无法通过托管实例的公共终结点访问读写侦听器和只读侦听器。

故障转移后性能可能下降

典型的 Azure 应用程序使用多个 Azure 服务,并由多个组件构成。 是否对故障转移组进行自动异地故障转移仅根据 Azure SQL 组件的状态来决定。 主要区域中的其他 Azure 服务可能不受中断的影响,其组件可能仍在该区域中可用。 将主数据库切换到次要区域后,依赖组件之间的延迟可能会增大。 请确保对次要区域中的所有应用程序组件采用冗余配置,并对应用程序组件和数据库进行故障转移,这样应用程序的性能就不会受到较高的跨区域延迟的影响。

故障转移后潜在数据丢失

如果主要区域发生服务中断,最新事务可能无法复制到异地辅助区域。 故障转移将延迟到使用 GracePeriodWithDataLossHours 指定的时间段。 如果配置了自动故障转移策略,请做好数据丢失的准备。 一般情况下,在中断期间 Azure 倾向于可用性。 将 GracePeriodWithDataLossHours 设置为更大的数字(例如 24 小时)或禁用自动异地故障转移可降低数据丢失的可能性,但会牺牲数据库可用性。

DNS 更新

启动故障转移后,读写侦听器的 DNS 更新会立即发生。 此操作不会导致数据丢失。 但是,在正常情况下,切换数据库角色的过程可能需要 5 分钟时间。 在完成之前,新主实例中的某些数据库仍是只读的。 如果使用 PowerShell 发起故障转移,则切换主要副本角色的操作是同步的。 如果使用 Azure 门户启动故障转移,UI 会指示完成状态。 如果使用 REST API 启动故障转移,请使用标准 Azure 资源管理器的轮询机制来监视完成情况。

重要

缓解引发异地故障转移的服务中断后,使用手动计划故障转移将主数据库移回初始位置。

启用依赖于系统数据库中的对象的方案

系统数据库不会复制到故障转移组中的辅助实例。 若要启用依赖于系统数据库中的对象的方案,请确保在辅助实例上创建相同的对象并让辅助实例与主实例保持同步。

例如,如果你计划在辅助实例上使用相同的登录名,请确保使用相同的 SID 创建它们。

-- Code to create login on the secondary instance
CREATE LOGIN foo WITH PASSWORD = '<enterStrongPasswordHere>', SID = <login_sid>;

有关详细信息,请参阅复制登录名和代理作业

同步实例属性和保留策略实例

故障转移组中的实例保持独立的 Azure 资源,对主实例配置所做的任何更改都不会自动复制到辅助实例。 确保同时在主要和辅助实例上执行所有相关更改。 例如,如果在主实例上更改备份存储冗余或长期备份保留策略,请确保在辅助实例上也进行更改。

缩放实例

可以在同一服务层级内将主实例和辅助实例纵向伸缩到不同的计算大小。 在纵向扩展时,建议你首先扩展异地辅助数据库,然后再扩展主数据库。 纵向缩减时,则按相反顺序进行:先缩减主数据库,再缩减辅助数据库。 将实例缩放到不同服务层级时,将强制执行此建议操作。

特别建议按此顺序进行,以避免出现以下问题:较低 SKU 的异地辅助数据库过载,并且必须在升级或降级过程中重新设定种子。

使用故障转移组和虚拟网络服务终结点

如果使用虚拟网络服务终结点和规则来限制对 SQL 托管实例的访问,请注意,每个虚拟网络服务终结点仅适用于一个 Azure 区域。 终结点不允许其他区域接受来自该子网的通信。 因此,只有部署在同一区域中的客户端应用程序才能连接到主数据库。

防止关键数据丢失

由于广域网的延迟时间较长,异地复制使用了异步复制机制。 如果主数据库发生故障,异步复制会导致数据丢失不可避免。 为了防止这些关键事务数据丢失,应用程序开发人员可以在提交事务后立即调用 sp_wait_for_database_copy_sync 存储过程。 调用 sp_wait_for_database_copy_sync 会阻止调用线程,直到最后提交的事务已传输并强制执行到辅助数据库的事务日志中。 但是,它不会等待传输的事务在辅助数据库上进行重播(恢复)。 sp_wait_for_database_copy_sync 范围限定为特定异地复制链接。 对主数据库具有连接权限的任何用户都可以调用此过程。

为了防止在用户发起的计划性异地故障转移过程中丢失数据,复制会自动临时更改为同步复制,然后执行故障转移。 然后,复制在异地故障转移完成后返回到异步模式。

注意

sp_wait_for_database_copy_sync 防止特定事务异地故障转移后数据丢失,但不保证完全同步进行读取访问。 sp_wait_for_database_copy_sync 过程调用导致的延迟可能很明显,具体取决于调用时主数据库上尚未传输的事务日志大小。

故障转移组状态

自动故障转移组报告其状态,描述数据复制的当前状态:

  • 正在设定种子 - 初始种子设定是在创建故障转移组后进行,直到在辅助实例上初始化所有用户数据库。 当自动故障转移组的状态为“种子设定”时,无法启动故障转移过程,因为用户数据库尚未复制到辅助实例。
  • 正在同步 - 自动故障转移组的常规状态。 这意味着主要实例上的数据更改正在异步复制到辅助实例。 该状态不能保证数据在每个时刻都完全同步。 因为自动故障转移组中实例之间的复制过程存在异步性质,所以主要实例中的一些数据更改可能仍然需要复制到辅助实例。 自动和手动故障转移都可以在自动故障转移组的状态为“同步”时启动。
  • 正在进行故障转移 - 此状态指示自动或手动启动的故障转移过程正在进行。 当自动故障转移组位于此状态时,无法启动对故障转移组或其他故障转移的更改。

权限

通过 Azure 基于角色的访问控制 (Azure RBAC) 管理故障转移组的权限。

创建和管理故障转移组需要具有 Azure RBAC 写入访问权限。 SQL 托管实例参与者拥有管理故障转移组所需的全部权限。

有关特定权限范围,请查看如何在 Azure SQL 托管实例中配置自动故障组

限制

注意以下限制:

  • 无法在同一 Azure 区域中的两个实例之间创建故障转移组。
  • 无法重命名故障转移组。 需要删除该组,并使用不同的名称重新创建它。
  • 故障转移组正好包含两个托管实例。 不支持将其他实例添加到故障转移组。
  • 一个实例在任何时候只能参与一个故障转移组。
  • 故障转移组中的数据库不支持数据库重命名。 需要临时删除故障转移组,才能重命名数据库。
  • 系统数据库不会复制到故障转移组中的辅助实例。 因此,依赖于系统数据库中对象(例如服务器登录和代理作业)的方案要求在辅助实例上手动创建对象,并在对主实例进行更改后手动保持同步。 唯一的例外是 SQL 托管实例的服务主密钥 (SMK),它在创建故障转移组期间自动复制到辅助实例。 但是,在主实例上进行的任何后续 SMK 更改都不会复制到辅助实例。 若要了解详细信息,请参阅如何启用依赖于系统数据库中的对象的方案
  • 如果任一实例位于实例池中,则无法在实例之间创建故障转移组。

以编程方式管理故障转移组

也可以使用 Azure PowerShell、Azure CLI 和 REST API 以编程方式管理自动故障转移组。 下表描述了可用的命令集。 活动异地复制包括一组用于管理的 Azure 资源管理器 API,其中包括 Azure SQL 数据库 REST APIAzure PowerShell cmdlet。 这些 API 需要使用资源组,并支持 Azure 基于角色的访问控制 (Azure RBAC)。 有关如何实现访问角色的详细信息,请参阅 Azure 基于角色的访问控制 (Azure RBAC)

Cmdlet 说明
New-AzSqlDatabaseInstanceFailoverGroup 此命令会创建故障转移组,并将其同时注册到主实例和辅助实例
Set-AzSqlDatabaseInstanceFailoverGroup 修改故障转移组的配置
Get-AzSqlDatabaseInstanceFailoverGroup 检索故障转移组的配置
Switch-AzSqlDatabaseInstanceFailoverGroup 触发故障转移组到辅助实例的故障转移
Remove-AzSqlDatabaseInstanceFailoverGroup 删除故障转移组

后续步骤