谈谈数据库的跨机房容灾

社区编辑2018-05-18 16:30

作者:郭忆 网易云基础服务
 
近年来,我们经常可以看到某某公司因为机房电力故障或者机房网络光纤被市政施工挖断导致整个数据中心服务不可用,进而对产品和业务产生严重影响的事件的发生。
 
随着互联网产品对服务可用性,数据可靠性要求的进一步提高,原先的单机房集中部署模式已经不能满足要求,跨机房部署的需求越来越多。
 

 
“两地三中心” 已经是跨机房灾备的标准技术架构,通常会在相距 40 公里范围以内的同座城市建设灾备数据中心,应对机房级别的故障。之所以将距离锁定在 40 公里范围以内是考虑到这个距离通过高速光纤相连,机房之间的响应延迟一般在 1ms 左右,从业务层面讲可以认为是在同一个局域网内。
 
除了同城灾备,“两地三中心” 的方案还包括在相距 1000 公里以外的两个不同城市组建异地灾备数据中心,应对区域性故障,不过由于距离长度的限制,机房之间的网络延迟难以避免。
 

 
“两地三中心” 的技术架构最早在银行和金融行业应用实施,但一般都只有一个机房提供服务,其他的灾备机房仅同提供服务的生产机房进行数据复制,这种冷备的模式并不适用于互联网业务:
 
维护成本过高:由于只有生产机房提供服务,同城的灾备机房和异地灾备机房都处于空闲状态,随着业务数据量和访问量的增长,需要花费三倍的成本去维护灾备机房,对于互联网业务海量数据和高并发访问的特点,维护成本过高。
 
切换时间无法保障:由于只有生产机房是提供服务的,灾备机房没有承担业务的访问请求,一旦生产机房出现故障,灾备机房的启用和预热都需要花费一定的时间,同时由于该机房之前没有提供服务,在启用过程中难免会存在各种问题,由此导致的切换时间难以保障,无法满足互联网业务对实时性的要求。
 
难以扩展:由于整个架构是单点写入,数据库很容易成为性能瓶颈,而数据库的扩展方案非常复杂,导致整个架构的扩展也变得难以实施。
 
接下来,我们就来谈谈适用于互联网业务的 “互联网版” 两地三中心架构:
 

同城双活

 
在同城的数据中心之间,一般通过高速光纤相连,在网络带宽有保障的前提下,网络延迟一般在可接受范围内,两个机房之间可以认为在同一个局域网内。该架构下,有两种部署模式:
 
应用层双活,数据库双活:两个机房的应用程序同时对外提供服务,两个机房的数据库也同时提供读写,每个机房的应用程序读写同一个机房内的数据库,两个数据库之间双向复制,通过一致性协议解决双向写冲突问题(例如 MySQL 5.7.17 推出的 Group Replication Plugin),该模式理论上实现了数据库多点写入,但是在实际跨机房场景中,尤其是在写冲突密集的业务场景下,性能下降非常大,不适用于跨机房的 OLTP 系统。
 
应用层双活,数据库单活:两个机房的应用程序同时对外提供服务,但是只有一个机房的数据库提供读写,另外一个机房的应用程序需要跨机房访问数据库,数据库之间单向复制。该模式在网络延迟相对低的同城环境下表现良好,但是如果距离超过 100 公里,机房之间的网络延迟就会超过 2ms,此时对于跨机房访问的数据库请求,性能有较大影响。
 
针对同城网络延迟低,可以看作是同一个局域网的特点,应用层采用双活,数据库采用单活是相对合理的方案。应用跨机房访问数据库,一旦某个机房故障,则将另外一个机房的应用访问请求切换到本机房的数据库,从而实现同城任何一个数据中心出现故障,都不会影响到整体业务的运行。
 
由于同城之间网络条件相对较好,MySQL 数据库原生的复制性能一般能够满足要求,MySQL 5.7 推出的并行复制可以有效解决容灾机房日志回放慢的问题。
 

 
同城双活相对实施成本较低,对业务的侵入较少,适用于跨机房容灾的初级阶段的用户。此外,为了确保方案的有效,还需要定期进行演练。

 

异地多活

 
当两个机房之间的距离超过 1000 公里,机房之间的网络传输延迟已经无法支撑跨机房的数据库访问请求的实时性要求,此时要实现多活,难度增加,需要从业务架构和数据库层进行改造。
 
单元化:将业务按照一定的维度拆分成独立的单元,每个单元内包含完整的基础设施,包括应用程序、数据库、消息队列等,单元内是封闭的,每个单元内部的应用访问和数据库读写均在同一个单元内部完成,单元之间仅允许少量的服务调用,这样就很好地解决了跨单元访问延迟的问题。
 
单元化的核心在于选择一个合理的维度,例如在电商的业务场景中,买家链路是交易系统的核心,所以电商类业务基于买家来做数据拆分是一个相对合理的选择,在游戏、邮箱、社交类业务中,可以基于用户维度进行数据拆分。数据拆分后,每个单元的数据库中只负责一部分数据的读写,所以要确保业务请求必须路由到正确的单元中,否则就会出现数据库读写的错乱。
 
数据传输:虽然按照买家维度,将同一个买家的所有交易信息都在同一个单元的数据库中写入,但是商品信息、卖家信息还是需要在不同单元之间进行共享,这就涉及单元之间数据同步的问题。由于跨域的原因,网络延迟无法避免,但是我们可以通过压缩的方式,减少日志的传输量,提高复制的效率。
 
原生 MySQL 的复制并不支持压缩功能,可以基于第三方的外部组件来实现压缩的特性,网易的 NDC 已实现了该功能。
 

 
异地多活在一定程度上可以有效地提高产品和业务应对区域故障的能力,确保出现故障的情况下绝大多数用户的核心体验可用。但是不可否认,异地多活的实施成本和代价也是非常高昂的,尤其是面对迭代节奏非常快的互联网业务,所以异地多活适用于业务模型已经趋于稳定的应用。但即便如此,在实施过程中,也要有针对性地选择核心和关键业务,并不是所有的业务都需要异地多活的部署。
 
单元化的应用架构,还有一个显著优势就是扩展性,由于每个单元相互独立,负责处理一部分的业务请求和一部分的数据读写,当业务请求数量或者数据量增长时,只需要通过增加单元,即可实现整个系统处理能力的线性扩展。