系统设计:如何让系统高可用?
系统的高可用性是指系统具备较高的无故障运行的能力。
很多开源组件中可以看到 HA 方案就是提升组件的可用性,让系统免于宕机无法服务的方案。
举个例子, Hadoop 1.0 中 NameNode 是单点的,一旦发生故障则整个集群不可用,Hadoop 2.0 时 ,采用的是两个 NameNode. 一个状态是Active,一个状态是 Standy 状态,两者共享存储。一旦 Active NameNode 发生故障,Standy NameNode 切换成 Active 状态继续提供服务。
一个高并发大流量的系统,系统出现故障比系统性能低更影响用户体验。一个日活百万的网站,如果出现一分钟故障,可能就影响了上千用户。
如何度量一个高可用系统?
系统可用性计算:
MTBF
Mean Time Between Failure 是瓶颈故障间隔的意思,代表两次故障的间隔时间,也就是系统正常运转的平均时间。这个时间越长,系统稳定性越高。
MTTR
Mean Time To Repair 表示故障的恢复时间,也可以理解为瓶颈故障时,这个值越小,故障对于用户的影响越小。
Availablity = MTBF/(MTBF+MTTR)
这个比例表示的是系统的可用性:
一般来说,核心系统的稳定性需要达到 4个9 ,非核心系统的可用性最多容忍 3个9 。
高可用系统设计思路
看MTBF 系统故障间隔时间 ,MTTR 系统故障恢复时间。因此高可用的设计思路主要两个方面:
- 系统设计,让系统更稳定
- 运维角度,让系统恢复更快。" Design for failture ",主要方法有:failover(故障转移),超时控制,限流,降级。
系统设计
故障转移 failover
- 同级别的 failover
完全对等节点之间做 failover。这类系统所有节点都承担读写流利,并且节点中不保存状态,每个节点都可以作为另外的一个节点的镜像。
举个例子:
Nginx 可以配置当某一个 Tomcat 出现 500 的请求时候,重试请求另外一个 Tomcat 节点。
2. 不同级别的 failover
主要指的是一个主从节点,可以在客户端上定期向主节点发送心跳包,也可以从备份节点上定期发送心跳包。选主的结果需要在多备份节点上达成一致。一般采用分布式一致性算法 paxos 或者 Raft.
超时控制
比如RPC框架,默认超时是30秒,平时运行可能比较稳定,但是一旦遇到比较大的流量,RPC 会出现一定数量的慢请求时 ,RPC 调用就可能超过30s ,造成 RPC 客户用尽调用线程而宕机。如歌设置了超时,就可以在出现慢请求是,触发超时,不会导致系统雪崩。
如何确定超时时间?
超时时间,一般通过收集系统之间的调用日志来确定,比如统计 99% 的响应时间是怎样的,然后根据这个时间来指定超时时间。
超时控制,其实是不让请求一直保持,经过一段时间后,释放资源给其他请求,避免消耗系统资源,导致雪崩。
服务降级
降级是为了保证核心服务的稳定从而牺牲非核心服务的做法。
在日常流量下,采用反垃圾邮件系统,对流量进行检查,虽然比较耗时但是依然能正常响应,但是在高并发情况下,这样反垃圾邮件系统的就可能成为瓶颈,这个时候就需要关闭掉反垃圾邮件系统,让主流量更加稳定。
服务限流
限流是对并发的请求进行限速来保护系统。
限制单机只能处理每秒 1000 次请求,超过的部分直接返回错误给客户端,限流一般是短暂行为。
系统运维
保证系统的可用性从运维角度,可以从灰度发布,故障演练两个方面考虑如何提升系统的可用性。
灰度发布
会不发布是指系统变更不是一次性推到生产上,按照一定比例推进, 一般情况下,灰度发布是以机器维度进行的。灰度发布是在系统正常运行条件下,保证系统高可用的运维手段。以便于在出现问题时快速回滚恢复。
故障演练
故障演练是指在发生故障时,如何快速恢复。
故障演练是指在系统进行一些破坏,观察出现局部问题时,整体的系统表现,从而发现系统潜在的问题。建议在线下搭建和线上部署结构一样的系统,这样可以在这套系统上故障演练,避免对生产系统影响。