在Uber,MySQL®数据库群集是数据基础设施的核心,支持着平台各种关键操作。Uber运行着一个庞大的MySQL群集,包含超过2300个独立的集群。构建一个能够管理如此大规模群集的控制平面,同时确保零停机时间和无数据丢失,这是行业中最具挑战性的问题之一。
提升可用性
在过去几年中,我们致力于将MySQL群集的可用性从99.9%提升到99.99%,通过多种优化和对控制平面的重新架构实现了这一目标。这是我们关于Uber MySQL部署和操作多部分博客系列的第一篇文章。本文将讨论Uber的MySQL群集架构、控制平面操作以及过去几年中在MySQL控制平面层面上的一些改进。
架构概览
Uber的MySQL群集由多个集群组成,每个集群有众多节点。主要有两种流程:数据流,客户端/服务与MySQL集群交互;控制流,管理集群生命周期。
对于数据流,托管在Kubernetes®上的无状态服务通过标准客户端连接到其MySQL集群。每个服务器都有一个反向代理,它根据角色(主/副本/批处理)存储MySQL节点的路由映射。这使得客户端能够根据要执行的查询,使用JDBC™协议发现并连接到适当的集群。
控制流负责管理集群和节点的供应、维护和退役,同时确保安全态势并与Uber生态系统集成。
MySQL群集的主要组件如图1所示:
- 控制平面
- 数据平面
- 发现平面
- 可观察性
- 数据变更捕获和数据仓库摄取
- 备份/恢复
控制平面
MySQL控制平面是一个基于状态的系统,由多个组件/服务和存储组成。核心技术管理者负责协调其他控制平面组件。其中一个关键职责是发布集群的目标状态或所需状态到Odin,这是Uber内部用于有状态技术的状态无关管理平台,还管理节点放置。管理者发布目标状态到Odin。目标状态包括关键配置,例如资源配置文件、节点数、角色(主/跟随者)、应在数据节点上运行的侧容器、服务器设置(如二进制日志格式、SQL模式)等。控制平面确保实际的MySQL集群或节点始终收敛到任何阶段定义的所需状态。
另一个关键技术管理者的角色是允许通过工作流更改系统状态。工作流是由Cadence支持的容错长期运行过程。一些工作流的例子包括在现有集群上添加新节点、在集群上执行主故障转移、应用某些MySQL变量到节点、更改MySQL副本的复制主节点等。技术管理者的其他关键功能如下:
- 集群管理:处理创建、更新和删除集群的操作。
- 主故障转移:更改集群的主节点。
- 节点生命周期管理:通过添加、替换和删除MySQL服务器节点来管理节点生命周期。
- 平衡放置:为Odin的放置引擎提供信号,以确保在所有部署Uber基础设施的地理区域中平衡放置服务器节点。这保证了对硬件故障甚至数据中心宕机的弹性。
- 数据库操作:管理特定于数据库的操作,如系统变量设置、复制设置和扩展操作。
传统上,MySQL控制平面与底层基础设施过程紧密耦合。随着MySQL群集的增长,这导致基础设施放置操作被MySQL故障阻止。MySQL团队花费大量时间调试这些问题。这种耦合影响了60多个工作流的操作可靠性,包括主故障转移、节点替换等。此外,MySQL依赖基于Git的配置存储系统来管理集群状态,这并不是为此类用例优化的解决方案。这一切提出了可靠性和可扩展性问题,需要对整个控制平面进行重新架构。
控制器
作为控制平面重新设计的一部分,我们在MySQL控制平面中引入了一个名为控制器的组件。控制器充当所有MySQL集群的外部观察者,从数据库和其他控制平面组件收集信号。控制器包含一个规则评估器,监控这些信号并在任何集群中违反任何定义的规则时采取行动。控制器的关键角色之一是监控MySQL实例中主节点的健康状况,并在当前主节点出现问题时自动触发主故障转移。此外,控制器还确保在组复制设置中属于共识组的部分建立集群平衡。
关键流程的编排
与控制平面交互的主要机制是通过工作流。工作流是异步的、事件驱动的过程,定义为一系列步骤来编排复杂的长期任务。MySQL控制平面使用Cadence™来支持这些工作流,提供持久性、容错性和可扩展性。图2显示了MySQL控制平面中的典型工作流。
此次重新设计已彻底改革了所有控制平面操作。下一节将审查几个关键流程的编排。
主故障转移
在Uber,我们有一个单主多副本设置。写入由主节点处理,并通过标准MySQL二进制日志复制到副本。
主故障转移是一个自动化过程,将集群的主节点从一个主机更改为另一个。由于只有一个主节点,保持其健康和运行对于保证高写入可用性和最小化停机时间至关重要。这些主故障转移工作流被用作组件的缓解措施,这些组件持续监控主节点的健康状况并在出现任何降级时执行故障转移。
根据现有主节点的健康状况,我们执行两种类型的故障转移:优雅型和紧急型。
优雅型升级是在当前主节点的一般维护活动期间需要的,例如当现有主节点所在的主机需要修复时。它们涉及选择一个新的主候选节点,然后优雅地将写负载从旧的主节点转移到新的主节点。优雅故障转移假设现有的主节点可用且健康。这适用于异步和半同步复制设置。还有涉及组复制的另一部署步骤,但不在本文讨论范围内。
优雅故障转移执行以下步骤:
- 将当前主节点置于只读模式。
- 停止当前主节点上的流量。
- 选择一个新的主节点(主选举)。默认情况下,工作流从同一个数据中心选择主选举。还会考虑副本节点的复制延迟,优先选择具有最先进二进制日志位置的节点。
- 获取前一个主节点的二进制日志位置,并等待这些事务在主选举中应用。
- 启用新主节点的写入。
如果现有主节点不可用(由于数据中心区域故障或网络隔离),MySQL执行紧急故障转移。它执行与优雅升级相同的步骤,唯一的例外是它不会依赖当前主节点将所有数据复制到新的主节点,因为当前主节点被认为无法访问。
我们向下游服务保证99.99%的可用性,而主故障转移是我们实现此SLA的关键过程。
节点替换
在控制平面中替换节点涉及到在不影响该MySQL数据库用户的情况下,将MySQL节点(及其所有数据)从一个主机移动到另一个主机。
Uber的硬件基础设施分布在多个云提供商和本地数据中心,包括数十万台机器和其他硬件和网络组件。节点替换在MySQL控制平面中至关重要,可以保护群集免受此庞大规模基础设施的中断,并保持群集敏捷。节点替换工作流是一种维护活动,会在受影响主机上关闭节点,并在不同的主机上创建一个具有类似资源和地理位置的相同节点,整个过程对数据库用户完全透明,他们甚至不会意识到这个移动。
虽然看似简单的数据移动操作,节点替换也有一些细微之处:
- 硬件配置:新节点必须与被替换的节点具有相同的硬件配置。这意味着它必须具有相同数量的CPU核心、磁盘和内存空间、端口等。
- 共置:新节点必须放置在具有与所替代节点相同容错级别的主机上,以确保相同的网络延迟。客户只关心查询延迟保持一致,无论节点的位置如何。
- 依赖关系:如果当前节点是拓扑中其他节点的复制父节点,则其子节点必须指向新的替换节点或连接到集群中的另一个节点。
- 主提升:如果要替换的节点是集群的主节点,在其退役或退出流量之前,必须触发优雅的主提升以将写入职责转移到不同的主节点。
节点替换内部由两个独立的操作组成:节点添加和节点删除。
节点添加是引导过程,包括放置和数据预配。放置包括找到节点的位置。这涉及识别包含新节点所需资源的主机。数据同步包括在识别的节点上安装MySQL进程,然后从现有节点之一(最好是主节点)启动数据传输到新节点。节点添加过程旨在支持并行添加多个节点,这对灾难恢复场景特别有用。
节点删除是优雅地删除主机的过程,在处理完节点的所有依赖关系后(如上所述)。
模式变更
MySQL控制平面通过自助工作流自动化模式变更。此过程使用MySQL的即时修改或Percona™ ptosc(pt-online-schema-change)对主节点执行安全且非阻塞的模式更新。工作流智能地根据模式变更类型和数据大小选择模式应用策略。例如,它使用即时修改进行快速和安全的列添加,以及非阻塞在线方法如ptosc进行数据类型变更。
模式变更工作流还允许进行试运行。试运行使客户能够在将模式变更为主节点(和其余集群)之前应用于孤立的副本。这提供了额外的保证,即模式变更是向后兼容、非破坏性和安全的。
模式变更工作流也与Uber的CI-CD管道集成,使模式变更过程完全自动化并接受审查过程。开发人员在模式文件中进行模式变更,并与其他源代码一起提交。一旦更新获得批准并合并到主分支,CI系统会检测到它并触发模式变更工作流。这给了开发人员对其模式的完全控制,并确保部署的代码始终与数据库模式一致。
数据平面
运行中的MySQL节点由在同一主机上运行的多个容器组成。数据库容器运行MySQL进程和其他执行明确定义任务的辅助组件。这些组件是孤立的Docker®容器,运行在同一主机内并通过Docker网络相互通信。MySQL节点的解剖如图4所示。
MySQL节点包括:
- 数据库容器:在mysqld进程中运行Oracle InnoDB®引擎。我们可以将其配置为使用其他MySQL引擎,如Meta RocksDB™。
- 工作容器:这是伴随容器,负责将节点的实际状态收敛到其目标状态。这将MySQL节点与Odin放置引擎集成。
- 度量容器:轮询MySQL进程发出的各种数据库信号(如QPS、查询类型、锁定时间、连接度量)并发布它们以供监控。
- 健康探测器:定期跟踪MySQL进程的健康状况,并发出主健康信号。控制器消费这些信号并采取措施缓解主节点故障,为Uber的MySQL用户提供严格的写停机时间SLA。
- 备份:一个短暂的容器,定期生成数据库备份并将其上传到对象存储。
发现平面
路由或发现平面通过在不断变化的Uber硬件基础设施之上提供抽象简化客户端与MySQL集群的交互。这为服务提供了一个单一的虚拟IP以连接到其MySQL集群,隐藏了硬件级别的所有更改。
路由和平面发现由三个主要组件组成:
- 反向代理:充当负载均衡器并将客户端的请求转发到和来自数据库主机。
- 池服务:负责在任何集群/节点管理操作期间更新代理配置,例如主故障转移或节点替换。
- 标准客户端:根据请求类型(读/写)提供简单易用的函数来创建与主节点和副本节点的连接,以及连接轮询、超时处理、与客户端相关的度量等。
作为控制平面重新设计的一部分,路由平面已更新为使用强一致性etcd™数据存储作为其拓扑存储。经理记录拓扑的变化,如添加新节点或处理主故障转移。这些更新通过etcd™监视传播到池服务,后者调整反向代理配置以将流量导向新节点或从离开的节点排水(在节点替换期间)。所有这些对客户端都是完全抽象的,他们使用静态VIP连接到反向代理。代理配置生成以将写查询路由到主节点并在所有副本上负载均衡读查询,优先考虑同一地理区域内的副本。
发现平面支持禁用特定节点上的流量。这对于调试MySQL节点中的任何硬件或软件故障非常有用,而不会影响客户流量。还可以使用控制器自动化此功能,以禁用遇到问题(如复制延迟)的节点上的流量。
可观察性
除了从容器和集群收集系统度量外,探测器还用于模拟数据流并收集有关每个集群各组件健康状况的度量。这些度量和日志由Uber的度量和日志系统收集。配置了警报以检测主节点上的写不可用、复制延迟、高CPU使用率和异常连接等故障。这种可观察性生态系统确保MySQL-db-as-a-service团队掌握MySQL群集的健康状况。拥有上游服务连接到数据库的团队也可以订阅这些警报。
数据变更捕获
对于数据变更捕获(CDC),MySQL群集使用Storagetapper,它从binlog捕获更改(插入、更新、删除),将其流式传输到Apache Kafka®,然后再摄入到Apache Hive™数据存储中。该系统可以处理上游模式变更、转换和格式转换。
备份和恢复
在Uber,MySQL的备份和恢复是完全自动化的流程。备份使用Percona XtraBackup™功能。MySQL备份和恢复保持4小时RPO和几分钟到几小时的RTO,具体取决于数据大小。
结论
MySQL是Uber许多关键服务的核心。控制平面为这些服务提供了一个可靠、可扩展且高性能的MySQL平台,抽象了在Uber规模下维护这样一个群集的所有操作开销。
本篇入门博客探讨了MySQL控制平面的主要组件,讨论了每个组件的架构和作用。我们还探讨了一些重要的操作和自动化,这些使群集保持健康和敏捷,无需手动干预,使我们能够服务于众多客户和用例。在本系列的下一篇博客中,我们将深入探讨如何操作MySQL以保证高可用性和高吞吐量。
