本文介绍最近几年美团点评 MySQL 数据库高可用架构的演进过程,以及我们在开源技术基础上做的一些创新。
同时,也和业界其他方案进行综合对比,了解业界在高可用方面的进展和未来我们的一些规划和展望。
MMM
在 2015 年之前,美团点评(点评侧)长期使用 MMM(Master-Master replication manager for MySQL)做数据库高可用。
因此我们积累了比较多的经验,但也踩了不少坑,可以说 MMM 在公司数据库高速发展过程中起到了很大的作用。
MMM 的架构如下:
如上图所示,整个 MySQL 集群提供 1 个写 VIP(Virtual IP)和 N(N>=1)个读 VIP 的对外服务。
每个 MySQL 节点均部署有一个 Agent(mmm-agent),mmm-agent 和 mmm-manager 保持通信状态,定期向 mmm-manager 上报当前 MySQL 节点的存活情况(这里称之为心跳)。
当 mmm-manager 连续多次无法收到 mmm-agent 的心跳消息时,会进行切换操作。
mmm-manager 分两种情况处理出现的异常:
- 出现异常的是从节点,mmm-manager 会尝试摘掉该从节点的读 VIP,并将该读 VIP 漂移到其他存活的节点上,通过这种方式实现从库的高可用。
- 出现异常的是主节点,如果当时节点还没完全挂,只是响应超时,则尝试将 Dead Master 加上全局锁(flush tables with read lock),在从节点中选择一个候选主节点作为新的主节点,进行数据补齐。
数据补齐之后,摘掉 Dead Master 的写 VIP,并尝试加到新的主节点上。将其他存活的节点进行数据补齐,并重新挂载在新的主节点上。
主库发生故障后,整个集群状态变化如下:
mmm-manager 检测到 master1 发生了故障,对数据进行补齐之后,将写 VIP 漂移到了 master2 上,应用写操作在新的节点上继续进行。
然而,MMM 架构存在如下问题:
- VIP 的数量过多,管理困难(曾经有一个集群是 1 主 6 从,共计 7 个 VIP)。某些情况下会导致集群大部分 VIP 同时丢失,很难分清节点上之前使用的是哪个 VIP。
- mmm-agent 过度敏感,容易导致 VIP 丢失。同时 mmm-agent 自身由于没有高可用,一旦挂掉,会造成 mmm-manager 误判,误认为 MySQL 节点异常。
- mmm-manager 存在单点,一旦由于某些原因挂掉,整个集群就失去了高可用。
- VIP 需要使用 ARP 协议,跨网段、跨机房的高可用基本无法实现,保障能力有限。
同时,MMM 是 Google 技术团队开发的一款比较老的高可用产品,在业内使用的并不多,社区也不活跃,Google 很早就不再维护 MMM 的代码分支。
我们在使用过程中发现大量 Bug,部分 Bug 我们做了修改,并提交到开源社区。
MHA
针对于此,从 2015 年开始,美团点评对 MySQL 高可用架构进行了改进,全部更新为 MHA,很大程度上解决了之前 MMM 遇到的各种问题。
MHA(MySQL Master High Availability)是由 Facebook 工程师 Yoshinori Matsunobu 开发的一款 MySQL 高可用软件,从名字就可以看出,MHA 只负责 MySQL 主库的高可用。
当主库发生故障时,MHA 会选择一个数据最接近原主库的候选主节点(这里只有一个从节点,所以该从节点即为候选主节点)作为新的主节点,并补齐和之前 Dead Master 差异的 Binlog。数据补齐之后,即将写 VIP 漂移到新主库上。
整个 MHA 的架构如下(为简单起见,只描述一主一从):
这里我们对 MHA 做了一些优化,避免一些脑裂问题。
比如 DB 服务器的上联交换机出现了抖动,导致主库无法访问,被管理节点判定为故障,触发 MHA 切换,VIP 被漂到了新主库上。
随后交换机恢复,主库可被访问,但由于 VIP 并没有从主库上摘除,因此 2 台机器同时拥有 VIP,会产生脑裂。
我们对 MHA Manager 加入了向同机架上其他物理机的探测,通过对比更多的信息来判断是网络故障还是单机故障。
MHA+Zebra(DAL)
Zebra(斑马)是美团点评基础架构团队开发的一个 Java 数据库访问中间件。
它是在 c3p0 基础上包装的美团点评内部使用的动态数据源,包括读写分离、分库分表、SQL 流控等非常强的功能,它和 MHA 配合,成为了 MySQL 数据库高可用的重要一环。
如下是 MHA+Zebra 配合的整体架构:
以主库发生故障为例,处理逻辑有如下两种方式:
- 当 MHA 切换完成之后,主动发送消息给 Zebra monitor,Zebra monitor 更新 ZooKeeper 的配置,将主库上配置的读流量标记为下线状态。
- Zebra monitor 每隔一段时间(10s ~ 40s)检测集群中节点的健康状况,一旦发现某个节点出现了问题,及时刷新 ZooKeeper 中的配置,将该节点标记为下线。
一旦节点变更完成,客户端监听到节点发生了变更,会立即使用新的配置重建连接,而老的连接会逐步关闭。
整个集群故障切换的过程如下(仅描述 Zebra monitor 主动探测的情况,***种 MHA 通知请自行脑补^_^)。
由于该切换过程还是借助于 VIP 漂移,导致只能在同网段或者说同个二层交换机下进行,无法做到跨网段或者跨机房的高可用。
为解决这个问题,我们对 MHA 进行了二次开发,将 MHA 添加 VIP 的操作去掉,切换完之后通知 Zebra monitor 去重新调整节点的读写信息(将 Write 调整为 new master 的实 IP,将 Dead Master 的读流量摘除)。
整个切换就完全去 VIP 化,做到跨网段、甚至跨机房切换,彻底解决之前高可用仅局限于同网段的问题。
上述切换过程就变成了如下图:
然而,这种方式中的 MHA 管理节点是单点,在网络故障或者机器宕机情况下依然存在风险。
同时,由于 Master-Slave 之间是基于 Binlog 的异步复制,也就导致了主库机器宕机或者主库无法访问时,MHA 切换过程中可能导致数据丢失。
另外,当 Master-Slave 延迟太大时,也会给数据补齐这一操作带来额外的时间开销。
Proxy
除了 Zebra 中间件,美团点评还有一套基于 Proxy 的中间件和 MHA 一起配合使用。
当 MHA 切换后,主动通知 Proxy 来进行读写流量调整,Proxy 相比 Zebra 更加灵活,同时也能覆盖非 Java 应用场景。
缺点就是访问链路多了一层,对应的 Response Time 和故障率也有一定增加。
未来架构设想
MHA 架构依然存在如下两个问题:
- 管理节点单点
- MySQL 异步复制中的数据丢失
针对于此,我们在部分核心业务上使用 Semi-Sync,可以保证 95% 以上场景下数据不丢失(依然存在一些极端情况下无法保障数据的强一致性)。
另外,高可用使用分布式的 Agent,在某个节点发生故障后,通过一定的选举协议来选择新的 Master,从而解决了 MHA Manager 的单点问题。
针对上述问题,我们研究了业界的一些领先的做法,简单描述如下。
主从同步数据丢失
针对主从同步的数据丢失,一种做法是创建一个 Binlog Server,该 Server 模拟 Slave 接受 Binlog 日志,主库每次的数据写入都需要接收到 Binlog Server 的 ACK 应答,才认为写入成功。
Binlog Server 可以部署在就近的物理节点上,从而保证每次数据写入都能快速落地到 Binlog Server。
在发生故障时,只需要从 Binlog Server 拉取数据即可保证数据不丢失。
分布式 Agent 高可用
针对 MHA 管理节点单点问题,一种做法是让 MySQL 数据库集群中每个节点部署 Agent,当发生故障时,每个 Agent 均参与选举投票,选举出合适的 Slave 作为新的主库,防止只通过 Manager 来切换,去除 MHA 单点。
整个架构如下图所示:
MGB 结合中间件高可用
上述方式某种程度上解决了之前的问题,但是 Agent 和 Binlog Server 却是新引入的风险,同时 Binlog Server 的存在,也带来了响应时间上的额外开销。
有没有一种方式,能够去除 Binlog Server 和 Agent,又能保证数据不丢失呢 ?答案当然是有的。
最近几年,MySQL 社区关于分布式协议 Raft 和 Paxos 非常火,社区也推出了基于 Paxos 的 MGR 版本的 MySQL,通过 Paxos 将一致性和切换过程下推到数据库内部,向上层屏蔽了切换细节。
架构如下(以 MGR 的 single-primary 为例):
当数据库发生故障时,MySQL 内部自己进行切换。切换完成后将 topo 结构推送给 Zebra monitor,Zebra monitor 进行相应的读写流量变更。
不过,该架构存在与 Binlog Server 同样的需要回复确认问题,就是每次主库数据写入,都需要大多数节点回复 ACK,该次写入才算成功,存在一定的响应时间开销。
同时,每个 MGR 集群必须需要奇数个数(大于 1)的节点,导致原先只需要一主一从两台机器,现在需要至少三台,带来一定的资源浪费。
但不管怎么说,MGR 的出现无疑是 MySQL 数据库又一次伟大的创新。
结语
本文介绍了美团点评 MySQL 数据库高可用架构从 MMM 到 MHA+Zebra 以及 MHA+Proxy 的演进历程,同时也介绍了业界一些高可用的做法。
数据库最近几年的发展突飞猛进,数据库的高可用设计上没有***的方案,只有不断的突破和创新,我们也一直在这条路上探索更加优秀的设计与更加***的方案。