作为DBA,大家在运维数据库的时候都会遇到 数据库发生 Failover /Switchover 切换的场景。数据库发生切换导致业务连续性受损,少则分钟级,多则小时级别。(最近互联网的故障比较多)。
本文 基于 MySQL 数据库架构场景来分析我们在遇到数据库 HA 切换时是系统会面临什么问题以及期待的解决方法。
一 导致HA 切换原因和影响
导致数据库切换的因素:
当数据库发生HA/容灾切换时,无论是计划内还是计划外,运维人员的主要目标是使系统恢复在线并最大程度的减少数据丢失,因为每一分钟的停机时间都会产生直接和间接成本(比如不能 打车/付款/刷脸, 其他各种服务不可用), 衡量停机影响的指标就是 RTO 和 RPO。
恢复时间目标(RTO): 是指业务中断的持续时间,从业务故障开始到全部恢复到可稳定访问的状态。
恢复点目标(RPO): 可接受数据丢失的度量。它是故障前最后提交的数据事务与故障后恢复的最新数据之间的时间间隔或延迟。实际数据丢失可能会有所不同,具体取决于发生故障时系统上的工作负载、故障类型以及所使用的高可用性解决方案的类型。
对于数据库系统来说 RTO 和 RPO 类似天平的两端,需要系统设计进行平衡。RTO 指标的影响时间除了探活时间 之外还有数据库系统本身的恢复时间。数据库系统的重要功能是保证事务的 ACID 能力,其中最重要的是保证“一致性”,这就需要对故障系统中已经提交的数据进行恢复,对没有提交的数据进行回滚。
所以往往追求减少 RTO 时间就会导致短期数据不一致。如果既要追求 RTO、又要追求RPO怎么办?这也不是完全不能达到的,一般来看都是增加物理硬件资源的投入,要么增加副本数、提高数据传输性能、使用非易失内存、使用高端的存储服务器,使用新的数据库架构,比如共享存储解决 RPO 时间长的问题等等。
二 不同架构 HA 切换遇到的问题
传统架构: 基于主从复制 + VIP /Proxy
传统主备模式的 MySQL的高可用都是基于 binlog 复制,存在复制延迟,sync_binlog
等参数配置等因素带来如下问题:
-
主备数据不一致(大事务/DDL 等因素导致主从延迟),需要人工介入进行数据回补。
-
业务连接闪断,事务回滚,会话中断等可能持续 30s+ 访问报错 ,这段耗时主要看 应用处理异常并且重新建联的时间。
-
故障探测时间周期 比如 每5秒一次,3次失败之后切换,15秒的探测时间导致 RTO 偏长,数据库切换完成,到业务恢复基本要60s 甚至更久。
-
还要需要系统或者DBA 接入处理RPO 相关的事情,DB切换时 binlog 是否传递到备库或者备库是否能及时获取全部的主库日志,多个从库场景下日志补齐等等,都影响整体的 RPO 指标。
MGR + Proxy
MGR场景下,数据安全性有非常大提高,解决数据丢失的风险。基于binnlog 复制的基础技术框架下,还是有问题:
-
有 DDL ,大事务 导致数据延迟的风险。
-
业务访问 DB 会话闪断,事务回滚的问题。
-
需要设置 group_replication_consistency 来平衡性能和数据一致性。
共享存储架构
基于共享存储的高可用通过物理复制 Redo,数据共享解决数据延迟以及基于主从架构的数据丢失的安全风险,规避 DDL 影响"主从延迟"的问题。但是该架构依然需要解决连接闪断和事务保持的问题。
三 云数据库如何解决?
基于前面谈到的高可用切换的痛点 ,PolarDB MySQL 开发新特性: 热备无感秒切技术,通过 VDS、全局预热系统、连接和事务保持三大特性,解决的故障探测、切换速度和切换体验问题, 直白的说 就是 提升系统切换的 RTO 和 RPO,做到"既要又要"。
故障探测:引入全新的高可用模块Voting Disk Service(简称VDS),该模块基于共享存储架构,实现自治的集群节点管理,大幅降低故障检测和集群选主耗时。
切换速度:新增支持全局预热系统的热备节点,通过对存储引擎内部的多个模块提前预热,优化升主的执行耗时。
热备节点是弱化版的只读节点,同时也是一个更接近主节点,并随时准备切换的灾备。相较于普通的只读节点,它保留了有限的读服务,预留了更多的 CPU 和 Memory 资源来优化切换速度。全局预热系统是热备切换中最核心的模块,主要负责实时同步主节点的元信息,将一些关键数据提前加载进内存,来提升未来潜在的升主切换速度。
切换体验:结合数据库代理(PolarProxy),支持连接保持和事务保持功能。在集群升降配或小版本升级过程中,开启连接保持和事务保持功能后,系统会尽可能地保证用户的连接和事务不中断,实现基本无感知的主动运维。
假设应用程序在 PolarDB 执行 UPDATE 的过程中,主节点出现故障。此时 PolarProxy 并不会立刻将底层的报错传给应用连接,而是将整个请求 hold 一段时间。热备切换选主之后,新的主节点通过Redo Log构建出所有的未提交事务,并异步等待未提交的事务,且暂时不进行回滚。
PolarProxy 在探测到主备切换成功信息后,会利用自身缓存的会话信息和事务信息,借助 PolarDB 的 Attach Trx 接口,桥接事务状态。PolarDB 会根据 PolarProxy 信息,判断相关的事务信息是否有效。如果事务有效,会将事务信息绑定到这个连接上,并回滚至最后一条语句(即上文的UPDATE)对应undo_no的Savepoint中。
四 别废话,动手体验
来都来了,动手试试吧,反正也不要钱。
为了能够让感兴趣的朋友对 PolarDB M 的无感切换有更加立体的认识和体验,(talk is cheap ,show me the code ) 我们开发线上功能体验馆,只要登陆官网然后动动鼠标即可免费体验到 无感切换的功能。
感兴趣的朋友可以通过 阅读原文 一键直达 PolarDB MySQL 无感切换功能体验页面。
测试场景
1. PolarDB 集群开启热备集群。
2. 通过 sysbench oltp_write_only,并发16,压测180s, 测试 PolarDB集群一主一只读节点的写入性能
3. 在压测过程中 主动 kill 主库 或者触发 switchover 动作切换数据库
4. 通过 sysbench的报告数据 体现 2种 切换对 TPS 的影响。
登陆体验馆,进入体验页面
实际体验页面: https://yaochi.console.aliyun.com/overview,点击 功能体验馆,进入 无感切换页面。
测试方法说明: https://help.aliyun.com/zh/polardb/polardb-for-mysql/user-guide/free-experience-polardb-mysql-failover
创建任务
单击页面下方 创建任务 按钮,并在弹出框中单击 确定 开始创建 Sysbench 压测任务。
注意后台启动任务需要大概 30s 左右,请耐心等待,操作标题对应的 查看详情变蓝。
根据如下图示 右上角的 刷新 按钮 ,刷新任务列表,可以看到用户创建的压测任务已开始。
进入切换页面
切换压测任务创建成功之后,点击体验记录 或者 操作标题对应的 查看详情 ,进入切换页面 ,进入实时压测情况页面。可以看到,压测任务已经开始,两个 PolarDB 集群在相同压测任务下的TPS水位是动态一致的。
点击切换测试 ,查看切换数据
单击左上角 开始切换测试,后台会触发两个 PolarDB 集群切换动作,通过动态实时 输出 sysbench 的压测数据,我们可以观测到如下结果:
普通切换的 PolarDB 集群的TPS 直接跌零,并持续了近15-20秒左右才恢复正常水平。这里的正常切换同样适用于其他 MySQL 架构的切换场景。
开启 无感秒切的PolarDB 集群的 TPS并未跌零,只是出现了短暂的下降,三秒后就恢复了正常水平。