当前位置: 首页 > 科技观察

究竟啥才是互联网架构“高可用”

时间:2023-03-23 10:29:25 科技观察

什么是互联网架构的“高可用”?一、什么是高可用性高可用性(HA)是分布式系统架构设计中必须考虑的因素之一。通常是指通过设计减少系统不能提供服务的时间。假设系统已经能够提供服务,我们说系统的可用性是100%。如果系统每运行100个时间单位,就会有1个时间单位不能提供服务,我们说系统的可用性是99%。很多公司的高可用目标是4个9,也就是99.99%,也就是说系统每年宕机时间是8.76小时。百度的搜索首页是业界公认的高可用保障优秀的系统。人们甚至通过能否访问www.baidu.com来判断“网络连通性”。百度的高可用服务让人留下“网络畅通”,百度能访问”,“百度打不开,应该是网络连不上”的印象,这其实是对百度HA***的褒奖。2.如何保证系统的高可用我们都知道单点是系统高可用的大敌,单点往往是系统高可用的风险和大敌,我们在系统设计的过程中要尽量避免单点。从方法论上来说,高可用保证的原则是“集群”,或者说“冗余”:只有一个单点,一旦失效就会影响服务;如果有冗余备份,还有其他备份可以发生故障接管。为了保证系统的高可用,架构设计的核心原则是:冗余。光有冗余是不够的。每次发生故障,都需要人工干预来恢复系统,这不可避免增加系统的无用实践。因此,系统的高可用性往往是通过“自动故障转移”来实现的。接下来我们看看在典型的互联网架构下,如何通过冗余+故障自动切换来保证系统的高可用。3、常见的互联网分层架构常见的互联网分布式架构如上,分为:客户端层:典型的调用者是浏览器或手机应用APP;反向代理层:系统入口,反向代理;站点应用层:实现核心应用逻辑,返回html或json;服务层:如果实现了服务,就有这一层;数据缓存层:缓存加速对存储的访问;data-数据库层:数据库固化数据存储;整个系统的高可用,通过冗余+各层自动故障转移全面实现。四、分层高可用架构实践1、【客户端层->反向代理层】的高可用从【客户端层】到【反向代理层】的高可用是通过反向代理层的冗余来实现的。以nginx为例:nginx有两台,一台提供在线服务,一台冗余保证高可用。常见的做法是keepalived存活检测,同一个虚拟IP提供服务。自动故障转移:当nginx宕机时,keepalived可以检测到,会自动进行故障转移,自动将流量迁移到shadow-nginx。由于使用的是同一个虚拟IP,这个切换过程对调用者来说是透明的。2.【反向代理层->site层】的高可用【反向代理层】到【site层】的高可用是通过site层的冗余实现的。假设反向代理层是nginx,可以在nginx.conf中配置多个web后端,nginx可以检测多个后端的生存能力。自动故障转移:当网络服务器宕机时,nginx可以检测到它,并自动进行故障转移,并自动将流量迁移到其他网络服务器。整个过程由nginx自动完成,对调用者透明。3、【站点层->服务层】的高可用通过服务层的冗余来实现从【站点层】到【服务层】的高可用。“服务连接池”会与下游服务建立多个连接,每个请求都会“随机”选择连接访问下游服务。自动故障转移:当服务宕机时,service-connection-pool可以检测到,自动故障转移,自动将流量迁移到其他服务。整个过程由连接池自动完成,对调用者是透明的(所以RPC-client中的服务连接池是一个非常重要的基础组件)。4.【ServiceLayer>CacheLayer】的高可用从【ServiceLayer】到【CacheLayer】的高可用是通过缓存数据的冗余来实现的。缓存层的数据冗余有几种方式:第一种是利用客户端的封装,服务端对缓存进行双读或双写。缓存层也可以通过支持主从同步缓存集群来解决缓存层的高可用问题。以redis为例,redis天然支持主从同步,redis官方有sentinel哨兵机制检测redis的生存能力。自动故障转移:Sentinel可以检测到redismaster何时宕机,并会通知调用者访问新的redis。整个过程由sentinel和rediscluster配合完成,对调用者是透明的。说完缓存的高可用,这里还要多说一点。业务不一定对缓存有“高可用”的需求。缓存的更多使用场景是用来“加速数据访问”:把一些数据放在缓存中这里,如果缓存宕机或者缓存不活跃,可以去后端数据库重新获取数据.对于这种允许“cachemiss”的业务场景,对于缓存架构的建议是:将kv缓存封装成一个服务集群,上游设置一个agent(agent可以使用集群冗余来保证高可用),agent的backend根据缓存访问serverkey级别分为若干个instance,每个instance的访问不具备高可用。缓存实例挂掉掩码:当一个水平拆分的实例挂掉时,代理层直接返回缓存未命中。此时缓存挂起对调用者也是透明的。key水平切分的实例减少,不建议做re-hash,容易导致缓存数据不一致。5.【服务层>数据库层】高可用互联网技术和数据库层大多采用“主从同步,读写分离”的架构,所以数据库层的高可用分为“读数据库高可用”还有两种“写库高可用”。6、【服务层>数据库层“读”】的高可用【服务层】到【数据库读】的高可用是通过读库的冗余实现的。由于读库冗余,一般来说,从库至少有2个。“数据库连接池”会与阅览库建立多个连接,每个请求都会路由到这些阅览库。自动故障转移:当读库宕机时,db-connection-pool可以检测到,会自动进行故障转移,自动将流量迁移到其他读库。整个过程由连接池自动完成,调用者是透明的(所以DAO中的数据库连接池是一个非常重要的基础组件)。7、【服务层>数据库层“写”】的高可用【服务层】到【数据库写】的高可用是通过写库的冗余来实现的。以mysql为例,可以设置两台mysql双主同步,一台提供在线服务,一台冗余保证高可用。常见的做法是keepalived存活检测,同一个虚拟IP提供服务。自动故障转移:当写库宕机时,keepalived可以检测到,会自动进行故障转移,自动将流量迁移到shadow-db-master。由于使用同一个虚拟IP,这个切换过程对调用方没有影响是透明的。五、小结高可用性HA(HighAvailability)是分布式系统架构设计中必须考虑的因素之一。通常是指通过设计减少系统不能提供服务的时间。从方法上讲,高可用性是通过冗余+自动故障转移来实现的。整个互联网分层系统架构的高可用性是通过各层的冗余+自动故障转移来全面实现的。具体来说:从【客户端层】到【反向代理层】的高可用是通过reverse来实现的,常见的做法是keepalived+虚拟IP自动failover;通过站点层的冗余实现从【反向代理层】到【站点层】的高可用。常见的做法是nginx和生存能力检测以及网络服务器之间的自动故障转移;从[站点层]到[服务层]的高可用性是通过服务层的冗余来实现的。一种常见的做法是使用service-connection-pool来保证故障自动转移;从【服务层】到【缓存层】的高可用是通过缓存数据的冗余来实现的。常见的做法是缓存客户端双读双写,或者使用缓存集群的主从数据同步和哨兵保活和自动故障转移;在更多的业务场景下,对缓存没有高可用的要求,可以使用缓存服务来屏蔽底层的复杂性,不让调用者看到;[servicelayer]到[database"read"]的高可用是通过读库实现的,常见的做法是通过db-connection-pool保证自动故障转移;通过写数据库的冗余实现从[服务层]到[数据库“写入”]的高可用,常见的做法是keepalived+VirtualIPautomaticfailover;最后希望文章思路清晰,希望大家对高可用的概念和实践有一个系统的认识,谢谢。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文