一、什么是高可用
高可用(High availability,缩写为 HA),是指系统无中断地执行其功能的能力,代表系统的可用性程度。
高可用的主要目的是为了保障“业务的连续性”,即在用户眼里,业务永远是正常对外提供服务的。
二、高可用架构设计
针对架构的高可用,第一步,采用分层的思想把一个大的IT系统拆分成应用层,中间层,数据存储层,每一层再拆分为更细粒度的组件;第二步,让每个组件对外提供服务,毕竟每个组件不是孤立存在的,需要互相协作。
高可用可分为“冗余”和“自动故障转移”。冗余:组件出现故障时,集群中的其它机器可以随时顶替。自动故障转移:借助第三方工具(仲裁者)来实现自动的故障转移,达到近实时的故障转移的目的。
怎样的系统可以称之为高可用呢,业界一般用几个九来衡量系统的可用性,如下一、什么是高可用
高可用(High availability,缩写为 HA),是指系统无中断地执行其功能的能力,代表系统的可用性程度。
高可用的主要目的是为了保障“业务的连续性”,即在用户眼里,业务永远是正常对外提供服务的。
怎样的系统可以称之为高可用呢,业界一般用几个九来衡量系统的可用性,如下
可用性级别 | 系统可用性% | 宕机时间/年 | 宕机时间/月 | 宕机时间/周 | 宕机时间/天 |
---|---|---|---|---|---|
不可用 | 90% | 36.5 天 | 73 小时 | 16.8 小时 | 144 分钟 |
基本可用 | 99% | 87.6 小时 | 7.3 小时 | 1.68 小时 | 14.4 分钟 |
较高可用 | 99.9% | 8.76 小时 | 43.8 分钟 | 10.1 分钟 | 1.44 分钟 |
高可用 | 99.99% | 52.56 分钟 | 4.38 分钟 | 1.01 秒 | 8.64 秒 |
极高可用 | 99.999% | 5.26 分钟 | 26.28 秒 | 6.06 秒 | 0.86 秒 |
大厂一般要求 4 个 9,其他要求严苛的业务要达到五个九以上。
三、互联网架构剖析
可以看到架构主要分以下几层
接入层:主要由 F5 硬件或 LVS 软件来承载所有的流量入口
反向代理层:Nginx,主要负责根据 url 来分发流量,限流等
网关:主要负责流控,风控,协议转换等
站点层:主要负责调用会员,促销等基本服务来装配 json 等数据并返回给客户端
基础 service:其实与站点层都属于微服务,是平级关系,只不过基础 service 属于基础设施,能被上层的各个业务层 server 调用而已
存储层:也就是 DB,如 MySQL,Oracle 等,一般由基础 service 调用返回给站点层
中间件:ZK,ES,Redis,MQ 等,主要起到加速访问数据等功能
接入层&反向代理层
这两层的高可用与keepalived有关
当两个LVS以主备形式对外提供服务时,只此只有master在工作(VIP在master上生效),另一个backup在master宕机后会接管master的工作。
主备机会通过keepalived的心跳检测彼此的情况,一旦发现master宕机,则backup自动转成master对处提供服务,此时VIP在backup上,这也就是我们常说的IP漂移。
keepalived 的心跳检测主要通过发送 ICMP 报文,或者利用 TCP 的端口连接和扫描检测来检测的,同样的,它也可以用来检测 Nginx 暴露的端口,这样的话如果某些 Nginx 不正常 Keepalived 也能检测到并将其从 LVS 能转发的服务列表中剔出。Nginx也能通过端口检测服务健康状态。
微服务
网关
、站点层、基础服务层属于微服务架构,还需要通过RPC框架,如Dubbo来支撑通信。
生产者(Provider)向注册中心(Register)注册服务,然后消费者(Consumer)向注册中心订阅和拉取生产者的服务列表。获取到服务列表后,消费者根据其负载均衡算法,选择其中一个生产者,向其发出请求。当某个生产者不可用的,会被注册中心监听(通过心跳机制)到,及时推到消费者,消费者可以从生产者列表中剔除,以此来实现了故障的自动转移。
这里的注册中心就起到了类似于keepalived的作用。
中间件
ZK
ZK只有一个 Leader,很显然,此 Leader 存在单点隐患。Follower 与 Leader 会用心跳机制保持连接,如果 Leader 出现问题了(宕机或者因为 FullGC 等原因无法响应),Follower 就无法感知到 Leader 的心跳,就会认为 Leader 出问题了,于是它们就会发起投票选举,最终在多个 Follower 中选出一个 Leader 来(这里主要用到了 Zookeeper Atomic Broadcast,即 ZAB 协议,它是为 ZK 专门设计的一种支持崩溃恢复的一致性协议),选举的细节不是本文重点,就不在此详述了。
除了 ZAB 协议,业界上常用的还有 Paxos,Raft 等协议算法,也可以用在 Leader 选举上,也就是在分布式架构中,这些协议算法承担了“第三者”也就是仲裁者的作用,以承担故障的自动转移
Redis
主从模式
其中主节点负责读写,然后同步数据到多个从节点上。引入哨兵(集群)来判定主节点是否宕机。如已宕机,则使用Raft协议来选举出新的主节点。
问题:
主节点写的压力难以降低:因为只有一个主节点能接收写请求,如果在高并发的情况下,写请求如果很高的话可能会把主节点的网卡打满,造成主节点对外无法服务
主节点的存储能力受到单机存储容量的限制:因为不管是主节点还是从节点,存储的都是全量缓存数据,那么随着业务量的增长,缓存数据很可能直线上升,直到达到存储瓶颈
同步压力大:因为数据都是从 master 同步到 slave 的,如果有多个从节点的话,master 节点的压力会很大
Cluster分片集群
将数据分片,每一个分片数据由相应的主节点负责读写,这样的话就有多个主节点来分担写的压力,并且每个节点只存储部分数据,也就解决了单机存储瓶颈的问题,但需要注意的是每个主节点都存在单点问题,所以需要针对每个主节点做高可用。
原理也很简单,在 Proxy 收到 client 执行的 redis 的读写命令后,首先会对 key 进行计算得出一个值,如果这个值落在相应 master 负责的数值范围(一般将每个数字称为槽,Redis 一共有 16384 个槽)之内,那就把这条 redis 命令发给对应的 master 去执行,可以看到每个 master 节点只负责处理一部分的 redis 数据,同时为了避免每个 master 的单点问题,也为其配备了多个从节点以组成集群,当主节点宕机时,集群会通过 Raft 算法来从从节点中选举出一个主节点。
ES
在 ES 中,数据是以分片(Shard)的形式存在的,如下图所示,一个节点中索引数据共分为三个分片存储
但只有一个节点的话,显然存在和 Redis 的主从架构一样的单点问题,这个节点挂了,ES 也就挂了,所以显然需要创建多个节点。
ES 的工作原理
节点的工作机制,节点(Node)分为主节点(Master Node)和从结点(Slave Node),主节点的主要职责是负责集群层面的相关操作,管理集群变更,如创建或删除索引,跟踪哪些节点是集群的一部分,并决定哪些分片分配给相关的节点。主节点也只有一个,一般通过类 Bully 算法来选举出来,如果主节点不可用了,则其他从节点也可以通过此算法来选举以实现集群的高可用,任何节点都可以接收读写请求以达到负载均衡的目的
分片的工作原理,分片分为主分片(Primary Shard,即图中 P0,P1,P2)和副本分片(Replica Shard,即图中 R0,R1,R2),主分片负责数据的写操作。当从节点接收到数据时,此节点会将写请求调度到主分片所在的节点上,写入主分片后,主分片再把数据复制到其他节点的副本分片上,如下
存储层
MySQL的高可用也分为主从和分片(分表分库)
主从类似于LVS,使用keepalived实现高可用。
数据量大了后,需要分表分库,有了多个主节点,也要对每个主节点配置主从以保证高可用。
总结
高可用的核心思想「冗余」和「自动故障转移」,除此以为,一个高可用的系统还存在以下问题:
瞬时流量问题:比如我们可能会面临秒杀带来的瞬时流量激增导致系统的承载能力被压垮,这种情况可能影响日常交易等核心链路,所以需要做到系统之间的隔离,如单独为秒杀部署一套独立的集群
安全问题:比如 DDOS 攻击,爬虫频繁请求甚至删库跑路等导致系统拒绝服务
代码问题:比如代码 bug 引起内存泄露导致 FullGC 导致系统无法响应等
部署问题:在发布过程中如果贸然中止当前正在运行的服务也是不行的,需要做到优雅停机,平滑发布
第三方问题:比如我们之前的服务依赖第三方系统,第三方可能出问题导致影响我们的核心业务
不可抗力:如机房断电,所以需要做好容灾,异地多活,之前我司业务就由于机房故障导致服务四小时不可用,损失惨重
其中关于降级的例子:
我们之前对接过一个第三方资金方由于自身原因借款功能出了问题导致无法借款,这种情况为了避免引起用户恐慌,于是我们在用户申请第三方借款的时候返回了一个类似「为了提升你的额度,资金方正在系统升级」这样的文案,避免了客诉
在流媒体领域,当用户观看直播出现严重卡顿时,很多企业的第一选择不是查 log 排查问题,而是为用户自动降码率。因为比起画质降低,卡得看不了显然会让用户更痛苦
双十一零点高峰期,我们把用户的注册登录等非核心功能给停掉了,以保证下单等核心流程的顺利