高可用性(HA),顾名思义,就是尽可能地减少系统不能提供服务的时间;如果一个系统能够一直保持工作状态,可以对外提供服务,那么我们就说系统的可用性是100%;大部分公司不会把话说这么满,所以经常会提出三个9、四个9的目标,也就是全年系统可用性为99.9%、99.99%。
那么如何保证系统的高可用呢?我认为核心的思想就是【防止单点,增加冗余】,先让我们看看传统的架构是什么样的,哪里会有风险。
可以看到,架构的每一个部分都是单点的话,简直是风险重重,任何一个环节出现了问题,可能会造成整个系统垮掉(缓存部分可能不会直接影响系统,但往往缓存失去效果之后,会拖垮数据库),解决方法也很容易,其实就是把系统的每个部分都增加冗余:
客户端到Web应用:要增加Web应用,首先要增加反向代理层,也就是负载均衡,比如Nginx;不过如果只部署一个Nginx的话,它又是一个单点了,通常我们会部署多台,一台提供服务,另外的相当于“备胎”,通过keepalived的方式监控工作中的Nginx是否存活,当主服务器发生故障无法对外提供服务时,动态将virtual IP(虚IP)切换到备用机,继续提供服务。
负载均衡到Web应用:搭建多个Web应用,在负载均衡如Nginx中配置多个Web端的地址,并且可以监控多个Web端的存活性,当监控到某台应用挂掉,那么Nginx不在将请求分发到这台机器上。
Web应用到服务层:这里有很多种实现方式,比如服务层前端也挂负载均衡,或者走客户端内的负载均衡(这里Web应用就是客户端,相当于配置多个服务层的地址,每次请求按照一定规则,选取连接来访问下游服务,并使用service-connection-pool监控服务层应用的存活性);也可以使用服务注册发现的方式(可提供服务的应用才会出现在注册中心)。
服务层到缓存:缓存的存在,本身就是一种冗余;缓存层也可以通过集群来解决缓存层的高可用问题。以Redis为例,支持主从同步,而且有sentinel哨兵机制,来做Redis的存活性检测。
服务层到数据库:数据库一般会采用主从架构;数据库【读】的高可用,通常使用db-connection-pool来保证自动故障转移;而【写】操作,通常需要keepalived+virtual IP(虚IP)自动切换。
以上都是保证系统高可用的方案,尽量做到客户端所有的请求都可以响应,但是系统资源不可能无限投入,所以需要一些方案保证系统的高可用,不过需要【牺牲】部分用户:
限流:我们接口只能支持200的并发,我们的页面只能支持一万人同时访问,那么多余的部分,对不起,我需要限制你们进入;常见的限流算法有:漏桶、令牌桶;
降级:牺牲非核心的业务功能,保证核心功能的稳定运行;
熔断:当服务链路中(A调B,B调C,C调D),某个服务响应时间过长或失败,会进行服务的降级,进而熔断该节点服务的调用,快速返回错误信息;不过嘛,我从来没有见过谁敢用熔断...
灰度发布:将部分流量导到新上线的应用上,来验证新的功能修改,如果上线后有BUG,也可以快速回滚,尽可能降低发布的风险。
我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有