本文来自网易云社区

SQL Server 是windows平台.NET架构下标配数据库解决方案,与Oracle、MySQL共同构成了DB-Engines Ranking的第一阵营,在国内外企业市场中有着广泛的应用。Mirroring是SQL Server 最常用的高可用解决方案,具有自动故障转移,高安全模式下具有数据“零”丢失,对客户端透明等优势,目前AWS、阿里云、腾讯云均采用该技术实现云端SQL Server 高可用部署。今天我们就来聊聊SQL Server 高可用镜像实现原理;

数据副本

镜像技术实现了位于不同物理服务器上的两个SQL Server实例数据同步,在镜像集群中,SQL Server实例具有三种角色;

  • Principal:具有完整的数据副本,对外提供数据库读写服务;

  • Mirror:具有完整的数据副本,本身不提供读写服务,通过接收来自Principal的更新日志实现数据同步,允许创建快照实现报表;

  • Witness: 本身不存储数据,只负责在高安全运行模式下提供自动故障切换的能力,确保两个SQL Server实例只有一个对外提供服务,避免脑裂情况出现;

在镜像集群中,principal和mirror的数据同步是依靠事务日志来实现的,与Oracle和MySQL 不同,SQL Server的事务日志是Database级别的,不是实例级别的,每个Database都单独的事务日志,这也就使得SQL Server的镜像是可以基于Database层面实现。一个SQL Server实例中的两个Database,一个可以作为principal,一个可以作为mirror,分别与其他SQL Server实例组建镜像关系;另外,SQL Server 一个Database只能有一个mirror节点,一个mirror的database不可以再有mirror节点,这点与MySQL级联复制不同;

SQL Server的事务日志是物理记录级别的,记录了对数据库某个页的某行记录(slot)的操作,principal创建镜像后,会启动一个单独的事务日志发送线程,维护一个虚拟的发送队列,然后读取事务日志,将其进行压缩,根据官方公布的测试数据,压缩比不低于12.5%,然后发送给mirror节点,mirror节点接收到以后,会将其写入本地在磁盘上的一个重做队列文件中,然后再通过另外的一个线程异步的方式,从重做队列中获取事务日志,然后分发给应用线程(process unit)进行回放。

不同于MySQL Binlog,由于SQL Server的事务日志在principal上事务执行过程中就已经源源不断的写入(MySQL Binlog仅在事务提交阶段生成),在principal事务执行的同时事务日志就已经传递给了mirror,所以基于事务日志的SQL Server的复制性能会更理想,同时,在mirror回放的过程中,可以基于页(page)级别进行并发更新(redo parallel),在SQL Server的标准版中,仅提供一个线程进行事务日志回放(roll forward),在企业版中,如果当前服务器CPU大于5核,则每4个核,增加一个并行线程,如果低于5个核,则仍然使用单线程回放。同时,基于页的事务日志的并发执行,还有一个好处就是对于同一个页面的更新可以合并刷新,减少脏页刷新数量;

运行模式

镜像集群提供了三种运行模式:

  • 高性能模式:principal与mirror之间数据异步传输,principal上的事务提交无需等待mirror的响应,principal 宕机后,存在数据更新丢失的可能,不支持自动故障转移,可以通过强制服务的方式使得mirror提供服务,适合对数据可靠性要求不高,性能要求较高的业务场景,与MySQL 的异步复制模式,Oracle DataGuard 最大性能模式相近;

  • 不带故障转移的高安全模式:principal上所有的事务提交,都必须要确认该事务涉及的事务日志均已经传送到的mirror上,并写入mirror的重做队列中,持久化 (是否持久化到外存设备还与windows操作系统写入缓存策略相关),mirror返回确认后,才可提交,可以实现principal宕机下数据“零”丢失,不支持自动故障转移,可以通过手动转移或者强制服务方式使得mirror提供服务,与MySQL 5.7 Loss-less replication、Oracle DataGuard 最大可用模式相近;

  • 带故障转移的高安全模式:与不带故障转移的高安全模式相比,增加了witness(见证服务器),可以实现自动的故障转移,通过witness,可以确保只有一个节点成为principal,对外提供服务,实际上witness最重要的一个作用就是选主;

故障转移

镜像集群故障转移最复杂场景就是带见证服务器的支持自动故障转移的高安全模式,所以我们重点讨论该模式下的故障处理流程。

初始状态下,witness、principal和mirror三个节点两两之间均保持长连接会话,现在讨论其中一方连接中断情况:

  • principal 与 witness 连接中断:

    此时witness与 mirror连接正常,触发自动故障恢复流程,principal丢失witness连接会话,如果principal 仍在运行状态,则将状态标记为DISCONNECTED,表示失去与mirror连接,切断所有客户端连接, 停止读写服务,等待故障切换。为了防止网络抖动引起不必要的切换,会话超时默认时间为10秒;witness和mirror将principal标记为不可用,等待mirror上的重做队列中的事务日志回放(roll forward)完成后,mirror成为新的principal,开始对外提供读写服务。

最后mirror会通过后台线程,将未提交的事务回滚(基于binlog的MySQL复制由于binlog是在事务提交阶段生成的,所以不存在事务回滚的阶段)。

从整个故障切换的流程来看,故障切换时间主要包括三个部分:检测到principal宕机的时间、mirror上重做队列中事务日志的回放时间以及回滚未提交事务的时间,其中前面两段时间服务不可用,尤其时重做队列的回放时间,直接决定了服务不可用时间。

  • mirror 与 witness 连接中断:

    此时,principal与witness连接正常,principal状态变为Disconected,表示终止与mirror连接,mirror状态变为suspend,principal不再向mirror发送事务日志,等待mirror重新建立到witness链接后,principal才会恢复与mirror进行数据同步;

  • principal 与 mirror 连接中断: principal与mirror同时保持witness的连接会话,但是principal与mirror之间会话中断,witness会通知mirror,principal依然保持连接状态,不会触发故障切换;此时principal由于保持有witness的连接会话,服务正常;

下面来考虑三方会话两个会话同时中断情况:

  • principal 与所有节点会话中断

    只要mirror与witness会话正常,即可完成正常的故障转移;如果mirror与witness连接也中断,则无法完成,即便是后来mirror与witness的会话优先恢复,则也无法故障切换,因为已然不确定mirror是否拥有全部principal的数据,此时即便principal处于运行状态,也无法提供服务,等待principal与任意节点会话恢复正常,即可恢复读写服务;

  • mirror 与 所有节点会话中断

    不会触发故障切换,principal切入公开运行模式(异步),即不会再向mirror发送事务日志,也不再需要等待mirror的响应,直到mirror重新恢复会话。

  • witness 与 所有节点会话中断

    不会触发故障切换,principal继续提供读写服务,与mirror数据继续同步,镜像集群丧失自动故障转移能力,退化为不带故障转移的高安全模式;

    如果三方会话同时连接中断,则principal无法提供服务,直到principal与任意节点通信恢复正常。

    场景1中,初始状态实例A、B和witness保持会话连接,其后,A实例宕机,失去与其他成员的会话,实例B与witness保持会话,触发故障切换,实例B升级为principal。其后实例B也宕机,服务停止。然后实例A恢复,但是由于此时实例A已经是mirror,不能确定实例A拥有实例B的所有更新数据,所以无法故障切换,最后实例B恢复,服务恢复正常。

    场景2中,实例A和B同时失去了与witness的会话,但是服务已然正常,A与B之间数据继续同步,其后A与B同时宕机,服务停止。最后A恢复服务,与witness恢复会话,A继续提供服务。

透明切换

一个完整的高可用机制除了后端节点的切换选主,还包括发生故障转移后,客户端如何能够快速的连接到冗余节点,继续业务读写。常用的实现,包括Driver层解决方案,例如mongoDB replication set,也有通过二层内的广播方式实现vip,例如keepalived,当然还包括proxy,以及三层DNS的实现。

SQL Server的实现采用了Driver层处理的方式,开发者要实现自动的故障转移,在连接数据库时,除了必须要指定初始节点的IP和端口,还要指定故障转移的节点的IP和端口。客户端首先尝试使用初始节点创建连接,如果初始节点指向的实例当前为principal,则连接会建立成功,可以正常的读写。当发生故障切换时,principal会切断所有已有客户端连接,然后客户端建立到初始节点连接也会失败,通过一定的重试策略失败后,会尝试连接之前指定的故障转移节点,从而实现服务入口的切换。

SQL Server常用的访问接口:OLE DB、ODBC、ADO均支持指定故障转移节点,格式如下:

Server=250.65.43.21,4734; Failover_Partner=250.65.43.22,4734;

集群监控

镜像集群的监控可以通过SQL Server Management stdio启动镜像监视器,或者系统内置的存储过程来实现,监控的主要指标包括:

  • 未发送日志:principal上未发送的日志超过指定的阈值,会在principal上生成一个警告,在高性能模式下,强制服务时可以作为评估principal上事务丢失数量的依据,同样也适用于在高安全模式切换成异步模式状态下(mirror失去连接)

  • 未还原日志:重做队列中的未被应用的事务日志数量(KB),超过阈值,会在mirror上生成一个警告,该值可以作为评估故障转移时间的主要因素。

  • 最早未被发送的事务:principal发送队列中,最早未被发送的事务的至今的时间,单位时分钟,超过阈值,会在principal上生成警告,与未发送日志量一起,从时间维度,衡量高性能模式下和高安全异步模式下,数据丢失数量;

  • 镜像提交开销:高安全模式下,principal上事务从提交到等到mirror响应的时间开销的平均值,如果超过阈值,则在principal上生成一个警告,在同步模式下,该值可以i衡量同步开销;

参考文档:

网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易云社区,经作者郭忆授权发布。

深入解析SQL Server高可用镜像实现原理的更多相关文章

  1. 深入解析 SQL Server 高可用镜像实现原理

    作者:郭忆 本文由 网易云 发布. SQL Server 是 windows 平台 .NET 架构下标配数据库解决方案,与 Oracle.MySQL 共同构成了 DB-Engines Ranking ...

  2. sql server 高可用镜像

    一.什么是数据库镜像 基本软件的高可用性解决方案 快速的故障转移恢复(3秒转移),低硬件成本 基于数据库级别的实现 二.数据库镜像中的服务器角色 主体服务器 承载主体数据库 接受用户连接和事务处理请求 ...

  3. SQL Server高可用——日志传送(4-1)——概论

    原文:SQL Server高可用--日志传送(4-1)--概论 本文作为学习总结,部分内容出自联机丛书及其他书籍 日志传送是什么? SQLServer 2012之前(2012出现了AlwaysOn), ...

  4. SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn(实战篇)之AlwaysOn可用性组搭建

    因为篇幅原因,AlwaysOn可用性组被拆成了两部分:理论部分和实战部分.而实战部分又被拆成了准备工作和AlwaysOn可用性组搭建. 三篇文章各自的链接: SQL Server ->> ...

  5. SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn可用性组(理论篇)

    因为篇幅原因,AlwaysOn可用性组被拆成了两部分:理论部分和实战部分.而实战部分又被拆成了准备工作和AlwaysOn可用性组搭建. 三篇文章各自的链接: SQL Server ->> ...

  6. 京东云数据库RDS SQL Server高可用概述

    数据库的高可用是指在硬件.软件故障发生时,可以将业务从发生故障的数据库节点迁移至备用节点.本文主要讲述SQL Server高可用方案,以及京东云RDS数据库的高可用实现. 一.高可用解决方案总览 1. ...

  7. SQL Server高可用——日志传送(4-3)——使用

    原文:SQL Server高可用--日志传送(4-3)--使用 顺接上一篇:SQL Server高可用--日志传送(4-2)--部署 本文为本系列最重要的一篇,讲述如何使用日志传送及一些注意事项.从上 ...

  8. SQL Server高可用——日志传送(4-2)——部署

    原文:SQL Server高可用--日志传送(4-2)--部署 前文再续,书接上一回.本章演示一下日志传送的具体过程 准备工作: 由于时间关系,已经装好了3台虚拟机,且同在一个域里面: SQL01:主 ...

  9. SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn(实战篇)之建立活动目录域、DNS服务器和Windows故障转移群集(准备工作)

    因为篇幅原因,AlwaysOn可用性组被拆成了两部分:理论部分和实战部分.而实战部分又被拆成了准备工作和AlwaysOn可用性组搭建. 三篇文章各自的链接: SQL Server ->> ...

随机推荐

  1. java 内存, 类加载g

    1. java 内存区域 方法区 虚拟机栈 本地方法栈 堆 程序计数器 其中 :  方法区  和 堆 是所有线程共享的 , 其他是线程隔离的 1.  程序计数器 : 可以看做是当前线程所执行的字节码的 ...

  2. Spring Boot学习笔记:项目开发中规范总结

    Spring Boot在企业开发中使用的很广泛,不同的企业有不同的开发规范和标准.但是有些标准都是一致的. 项目包结构 以下是一个项目常见的包结构 以上是一个项目的基本目录结构,不同的项目结构会有差异 ...

  3. 【NIFI】 实现数据库到数据库之间数据同步

    本里需要基础知识:[NIFI] Apache NiFI 安装及简单的使用 数据同步 界面如下: 具体流程: 1.使用ExecuteSQL连接mysql数据库,通过写sql查询所需要的数据 2.nifi ...

  4. canvas 实现烟花效果

    一:创建画布 <canvas width="600" height="600" id="canvas" style="bor ...

  5. python学习 day1 (3月1日)

    01 cpu 内存 硬盘 操作系统 CPU:中央处理器,相当于人大脑. 飞机 内存:临时存储数据. 8g,16g, 高铁 1,成本高. 2,断电即消失. 硬盘:长期存储大量的数据. 1T 512G等等 ...

  6. 2019.01.14 bzoj2752: [HAOI2012]高速公路(线段树)

    传送门 线段树菜题. 题意简述:给一条nnn个点的链,链有边权,支持区间修改边权,查询在一段区间内随机选择不同的起点和终点路径的期望总边权和. 思路:考虑每条边的贡献. 考虑对于一段区间[l,r][l ...

  7. C++STL list

    list双向链表 高效进行插入删除数据 不可以随机存取元素,所以不支持at()和[]操作符.it可以++  --,不能it+5 节点序号从0开始 list<int> l; l.push_b ...

  8. 实现数组(java)

    一,数组 java中有对数组的数据结构:数组就是一个存放固定数据的结构. 数组的声明举例:int [] array=new int [3],与之相同的是private  in [ ] array; a ...

  9. canvas画的时钟

    结合几天来学习的canvas的API,终于完成了一个时钟呵呵 html <!doctype html> <html> <head> <meta charset ...

  10. linux systemctl 常用用法简介

    主要介绍systemctl的几个功能如下: 1.查看某个服务的状态 2.关闭某个服务 3.开启某个服务 4.设置某个为开机自启动 5.关闭某个服务为开机不启动 6.查看所有开启启动的服务 1.查看某个 ...