常见互联网高可用架构

高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一, 它通常是指,通过设计减少系统不能提供服务的时间。

单点往往是系统高可用最大的风险和敌人,应该尽量在系统设计的过程中避免单点。 高可用保证的原则是“集群化”,或者叫“冗余”:只有一个单点,挂了服务会受影响。 如果有冗余备份,挂了还有其他backup能够顶上。

有了冗余之后,还不够,每次出现故障需要人工介入恢复势必会增加系统的不可服务实践。 所以,又往往是通过“自动故障转移”来实现系统的高可用。

接下来我们看下典型互联网架构中,如何通过”冗余+自动故障转移”来保证系统的高可用特性。

常见的互联网分层架构

先用一个图简单说明一下这个分层架构:

从上至下分别为:

  1. 客户端层:典型调用方是浏览器browser或者手机应用APP
  2. 反向代理层:系统入口,反向代理
  3. 站点应用层:实现核心应用逻辑,返回html或者json
  4. 服务层:如果实现了服务化,就有这一层
  5. 数据-缓存层:缓存加速访问存储
  6. 数据-数据库层:数据库固化数据存储

整个系统的高可用,又是通过每一层的”冗余+自动故障转移”来综合实现的。

下面从反向代理层开始,分别介绍每一层的高可用实现

反向代理层高可用

【客户端层】到【反向代理层】的高可用,是通过反向代理层的冗余来实现的。以nginx为例:有两台nginx, 一台对线上提供服务,另一台冗余以保证高可用,常见的实践是keepalived存活探测,相同virtual IP提供服务。

自动故障转移:当nginx挂了的时候,keepalived能够探测到,会自动的进行故障转移, 将流量自动迁移到备份nginx,由于使用的是相同的virtual IP,这个切换过程对调用方是透明的。

站点层高可用

【反向代理层】到【站点层】的高可用,是通过站点层的冗余来实现的。 假设反向代理层是nginx,nginx.conf里能够配置多个web后端,并且nginx能够探测到多个后端的存活性。

自动故障转移:当web-server挂了的时候,nginx能够探测到,会自动的进行故障转移, 将流量自动迁移到其他的web-server,整个过程由nginx自动完成,对调用方是透明的。

服务层高可用

【站点层】到【服务层】的高可用,是通过服务层的冗余来实现的。“服务连接池”会建立与下游服务多个连接,每次请求会“随机”选取连接来访问下游服务。

自动故障转移:当service挂了的时候,service-connection-pool能够探测到,会自动的进行故障转移,将流量自动迁移到其他的service, 整个过程由连接池自动完成,对调用方是透明的(所以说RPC-client中的服务连接池是很重要的基础组件)。

一般这个会使用到分布式服务框架。

缓存高可用

业务对缓存并不一定有“高可用”要求,更多的对缓存的使用场景,是用来“加速数据访问”:把一部分数据放到缓存里, 如果缓存挂了或者缓存没有命中,是可以去后端的数据库中再取数据的。这类允许“cache miss”的业务场景,缓存架构的建议是:

缓存实例挂了屏蔽:当有水平切分的实例挂掉时,代理层直接返回cache miss,此时缓存挂掉对调用方也是透明的。 key水平切分实例减少,不建议做re-hash,这样容易引发缓存数据的不一致。

数据库层的高可用

大部分互联网技术,数据库层都用了“主从同步,读写分离”架构,所以数据库层的高可用,又分为“读库高可用”与“写库高可用”两类。

数据库读高可用

【数据库读】的高可用,是通过读库的冗余来实现的。 既然冗余了读库,一般来说就至少有2个从库,“数据库连接池”会建立与读库多个连接,每次请求会路由到这些读库。

自动故障转移:当读库挂了的时候,db-connection-pool能够探测到,会自动的进行故障转移,将流量自动迁移到其他的读库, 整个过程由连接池自动完成,对调用方是透明的(所以说DAO中的数据库连接池是很重要的基础组件)。

数据库写高可用

【数据库写】的高可用,是通过写库的冗余来实现的。 以mysql为例,可以设置两个mysql双主同步,一台对线上提供服务,另一台冗余以保证高可用,常见的实践是keepalived存活探测,相同virtual IP提供服务。

自动故障转移:当写库挂了的时候,keepalived能够探测到,会自动的进行故障转移,将流量自动迁移到shadow-db-master, 由于使用的是相同的virtual IP,这个切换过程对调用方是透明的。

总结

高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。 方法论上,高可用是通过冗余+自动故障转移来实现的。

整个互联网分层系统架构的高可用,又是通过每一层的冗余+自动故障转移来综合实现的,具体的:

  1. 【客户端层】到【反向代理层】的高可用,是通过反向代理层的冗余实现的,常见实践是keepalived + virtual IP自动故障转移
  2. 【反向代理层】到【站点层】的高可用,是通过站点层的冗余实现的,常见实践是nginx与web-server之间的存活性探测与自动故障转移
  3. 【站点层】到【服务层】的高可用,是通过服务层的冗余实现的,常见实践是通过service-connection-pool来保证自动故障转移
  4. 【服务层】到【缓存层】的高可用,是通过缓存数据的冗余实现的,常见实践是缓存客户端双读双写,或者利用缓存集群的主从数据同步与sentinel保活与自动故障转移;更多的业务场景,对缓存没有高可用要求,可以使用缓存服务化来对调用方屏蔽底层复杂性
  5. 【服务层】到【数据库“读”】的高可用,是通过读库的冗余实现的,常见实践是通过db-connection-pool来保证自动故障转移
  6. 【服务层】到【数据库“写”】的高可用,是通过写库的冗余实现的,常见实践是keepalived + virtual IP自动故障转移