多机房部署的难道
多机房部署的含义是:
- 在不同的IDC机房中,部署多套服务,这些服务共享同一份业务数据,并且都可以承接来自用户的流量。
- 这样,当其中某一个机房出现网络故障、火灾等不可抗的灾难时,随时可以将用户的流量切换到其他地域的机房中,从而保证系统可以不简单的持续运行。
这种架构听起来非常美好,但是在实现上却是非常复杂和困难的,那么它复杂在哪儿呢?
假如我们有两个机房A和B都部署了应用服务,数据库的主库和从库都部署在A机房,那么机房B的应用如何访问到数据呢?有两种思路:
- 一个思路是直接跨机房读取A机房的从库
- 另一个思路是在机房B部署一个从库,跨机房同步主库的数据,然后机房B的应用就可以读取这个从库的数据了。
无论是哪一种思路,都涉及到跨机房的数据传输,这就对机房之间的延迟情况有着比较高的要求了。而机房之间的延迟,和机房的距离息息相关。
(1)北京同地双机房之间的专线延迟一般在1ms~3ms。
- 这个延迟会造成怎样的影响呢?要知道,我们的接口响应时间需要控制在200ms之内,而一个接口可能会调用几次第三方HTTP服务,或者RPC服务。如果这些服务部署在异地机房,那么接口响应时间就会增加几毫秒,是可以接受的
- 一次接口可能会涉及几次数据写入,那么如果数据库主库在异地机房,那么接口的响应时间也会因为写入异地机房的主库,增加几毫秒到十几毫秒,也是可以接受的
- 但是,接口读取缓存和数据库的数量,可能会达到十几次设置几十次,那么这就会增加几十毫秒甚至上百毫秒的延迟,就不能接收了
(2)国内异地双机房之间的专线延迟会在 50ms 之内。
具体的延迟数据依据距离的不同而不同。比如,北京到天津的专线延迟,会在 10ms 之内;而北京到上海的延迟就会提高到接近 30ms;如果想要在北京和广州部署双机房,那么延迟就会到达50ms了。在这个延迟数据下,要想保证接口的响应时间在200ms之内,就要尽量减少跨机房的服务调用,更要避免跨机房的数据库和缓存操作了
(3)如果你的业务是国际化的服务,需要部署跨国的双机房,那么机房之间的延迟就更高了,比如,从国内想要访问部署在美国西海岸的服务,这个延迟会在 100ms~200ms 左右。在这个延迟下,就要避免数据跨机房同步调用,而只做异步的数据同步。
机房之间的数据延迟,在客观上是存在的,你没有办法改变,可以做的就是尽量避免数据延迟对接口响应时间的影响。那么在数据延迟下,要如何设计多机房部署的方案呢?
逐步迭代多机房部署方案
同城双活
假设这样的场景:你在北京有 A 和 B 两个机房,A 是联通的机房,B 是电信的机房,机房之间以专线连接,方案设计时,核心思想是,尽量避免跨机房的调用。具体方案如下:
- 首先,数据库的主库可以部署在一个机房中,比如部署在A机房,那么A和B机房的数据都会被写入到A机房中
- 然后,在A、B两个机房中各部署一个从库,通过主从复制的方式,从主库中同步数据,这样双机房的查询请求可以查询本机房的从库
- 一旦A机房发生故障,可以通过主从切换的方式,将B机房的从库提升为主库,达到容灾的目的
- 缓存也可以部署在两个机房中,查询请求也读取本机房的的缓存,如果缓存中数据不存在,就穿透到本机房的从库中,加载数据。数据的更新可以更新双机房中的数据,保证数据的一致性
- 不同机房的RPC访问会向注册中心,注册不同的服务组,而不同机房的RPC客户端,也就是Web服务,只订阅同机房的RPC服务组,这样就可以实现RPC调用尽量发生在本机房内,避免跨机房的RPC调用
使用了同城双活架构之后,可以实现机房级别的容灾,服务的部署也能够突破单一机房的限制,但是,还是会存在跨机房写数据的问题,不过鉴于写数据的请求量不高,所以在性能上是可以容忍的。
异地多活
目的:即使机房所在的城市发生重大的自然灾害,也要保证系统的可用性、
在考虑异地多活的方案时,首先要考虑的是异地机房的部署位置,它部署的不能太近,否则发生自然灾害时,很可能会波及。但这样会造成更高的数据传输延迟,同城双活中,使用的跨机房写数据库的方案,就不合适了。
所以,在数据写入时,你要保证只写本机房的数据存储服务,再采用数据同步的方案,将数据同步到异地机房中。一般来说,数据同步的方案有两种:
- 一种基于存储系统的主从复制,比如MySQL和Redis。也就是在一个机房部署主库,在异地机房部署从库,两者同步主从复制,实现数据的同步
- 一种是基于消息队列的方式。一个机房产生写入请求后,会写一条消息到消息队列,另一个机房的应用消费到这条消息后,再执行业务处理逻辑,写入到存储服务中
建议,采用两种同步相结合的方式,比如,你可以基于消息的方式,同步缓存的数据、HBase 数据等。然后基于存储,主从复制同步 MySQL、Redis 等数据。
无论采用哪种方案,数据从一个机房,传输到另一个机房都会有延迟。所以,你需要尽量保证用户在读取自己的数据时,读取数据主库所在的机房。为了达到这一点,你需要对用户做分片,让一个用户每次的读写都尽量在同一个机房中。同时,在数据读取和服务调用时,也要尽量调用本机房的服务。
总结
- 不同机房的数据传输延迟,是造成多机房部署困难的主要原因,你需要知道,同城多机房的延迟一般在1ms~3ms,异地机房的延迟在50ms以下,而跨过机房的延迟在200ms以下。
- 同城多机房方案可以允许有跨机房数据写入的发生,但是数据的读取和服务的调用应该尽量保证在同一个机房中
- 异地多活方案则应该避免跨机房同步的数据写入和读取,而是采取异步的方式,将数据从一个机房同步到另一个机房。
多机房部署是一个业务发展到一定规模,对于机房容灾有需求时,才会考虑的方案,能不做则尽量不要做。一旦你的团队决定做多机房部署,那么同城双活已经能够满足你的需求了,这个方案相比异地多活要简单很多。而在业界,很少有公司,能够搭建一套真正的异步多活架构,这是因为这套架构在实现时过于复杂,所以,轻易不要尝试。