大厂都是如何对高并发系统做到高可用的?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 系统具备较高的无故障运行的能力。Hadoop1.0的NameNode是单点,一旦故障,整个集群不可用。Hadoop2提出的NameNode HA方案就是同时启动两个NameNode:

高可用性(High Availability,HA)


系统具备较高的无故障运行的能力。


Hadoop1.0的NameNode是单点,一旦故障,整个集群不可用。Hadoop2提出的NameNode HA方案就是同时启动两个NameNode:


一个处Active状态

另一个处Standby状态

两者共享存储,一旦Active NameNode故障,可将Standby NameNode切换成Active状态继续服务,增强了Hadoop持续无故障运行能力,即提升可用性。


可用性度量:


MTBF(Mean Time Between Failure)

平均故障间隔,代表两次故障的间隔时间,也就是系统正常运转的平均时间。这个时间越长,系统稳定性越高。


MTTR(Mean Time To Repair)

故障的平均恢复时间,也可以理解为平均故障时间。值越小,故障对于用户的影响越小。


可用性与MTBF和MTTR的值息息相关,公式关系:


Availability = MTBF / (MTBF + MTTR)


这个公式计算出的结果是个比例,代表系统可用性。一般会使用几个9描述系统可用性:



三个9后,系统的年故障时间从3d锐减到8h。到了四个九之后,年故障时间缩减到1小时之内。在这个级别的可用性下,你可能需要建立完善的运维值班体系、故障处理流程和业务变更流程。

还需要在系统设计上有更多的考虑。比如,在开发中你要考虑,如果发生故障,是否不用人工介入就能自动恢复。

工具建设也需更完善,以便快速排查故障原因,让系统快速恢复。

120.png

五个9后,故障就不能靠人力恢复。这个级别的可用性考察的是系统的容灾和自动恢复的能力,让机器来处理故障,才会让可用性指标提升一个档次。


核心业务系统的可用性,需要达到四个九,非核心系统可用性最多容忍三个九。


2 高可用系统设计

2.1 系统设计

“Design for failure”,高可用系统设计时秉持的第一原则。在承担百万QPS的高并发系统中,集群中机器的数量成百上千台,单机的故障是常态,几乎每一天都有发生故障的可能。


系统设计时,要把发生故障作为重要考虑点,预先考虑如何自动化发现故障,故障后如何解决。

还需掌握具体优化方法,如failover(故障转移)、超时控制、降级和限流。


发生failover的节点可能:


在完全对等的节点之间做failover

在不对等的节点之间,即系统中存在主、备节点

在对等节点之间做failover相对来说简单些。在这类系统中所有节点都承担读写流量,并且节点中不保存状态,每个节点都可以作为另一个节点的镜像。在这种情况下,如果访问某一个节点失败,那么简单地随机访问另一个节点就好了。


比如Nginx可以配置当某一个Tomcat出现>500的请求时,重试请求另一个Tomcat节点:

119.png

针对不对等节点的failover机制会复杂很多。比方有一个主节点,多台备用节点,这些备用节点可以是热备(同样在线提供服务的备用节点),也可以是冷备(只作为备份使用),那么我们就需要在代码中控制如何检测主备机器是否故障,以及如何做主备切换。


2.2 故障检测机制 - 心跳

可在客户端上定期地向主节点发送心跳包,也可在从备份节点上定期发送心跳包。当一段时间内未收到心跳包,就可以认为主节点已经发生故障,触发选主。


选主结果需在多个备份节点达成一致,所以会使用分布式一致性算法Paxos,Raft。


2.3 系统间调用超时

高并发系统通常有很多系统模块组成,依赖很多组件服务,如缓存组件,队列服务。调用最怕延迟,因为失败通常瞬时,可重试解决。而一旦调用某模块或服务发生较大延迟,调用方就会阻塞在这次调用,它已占用的资源无法释放。当存在大量这种阻塞请求,调用方就会因为用尽资源而宕机。


系统开发初期,超时控制通常不重视或未设置合适超时时间。


某项目的模块间RPC调用,超时时间默认30s。平时系统运行稳定,但流量大时,RPC服务端出现一定数量慢请求时,RPC客户端线程就会大量阻塞在这些慢请求上长达30s,造成RPC客户端用尽调用线程而宕机。


确定超时时间

超时时间过短

会造成大量超时错误,对用户体验产生影响

超时时间过长

又起不到作用

推荐收集系统之间的调用日志,统计比如99%响应时间是怎样的,然后依据该时间指定超时时间。

若无调用日志,则只能据经验指定超时时间。

无论使用何方式,超时时间都不会一直不变,系统迭代维护过程中会不断修改。


超时控制实际上就是不让请求一直保持,而是在经过一定时间之后让请求失败,释放资源给其它请求使用。

这对于用户有损,但是必要的,牺牲少量请求却保证了系统可用性。


还有两种有损方案保证系统高可用:


2.4 降级

为保证核心服务的稳定而牺牲非核心服务。


比方发条微博会先经过反垃圾服务检测,检测内容是否是广告,通过后才完成诸如写DB逻辑。


反垃圾检测是相对较重操作,涉及很多策略匹配,在日常流量下虽然会比较耗时却还能正常响应。

但并发较高时,它可能成为瓶颈,而且它也不是发微博的主体流程,可暂时关闭,这就能保证主体的流程稳定。


2.5 限流

通过对并发请求进行限速保护系统。


比如对Web应用,限制单机只能处理每s 1000次请求,超过部分直接返回错误给客户端。

这种做法虽损害用户体验,但是在极端并发下的无奈之举,属短暂行为可接受。


3 系统运维

可从灰度发布、故障演练考虑提升系统可用性。


在业务平稳运行过程中,系统很少故障,90%的故障发生在上线变更阶段。

比如你上了个新功能,由于设计方案问题,DB的慢请求数翻了一倍,导致系统请求被拖慢而产生故障。


若未变更,DB怎会无缘无故产生那么多慢请求?

重视变更管理很重要。除了提供回滚方案,另一个方案就是灰度发布。


灰度发布

系统的变更不是一次性推到线上,而是按照一定比例逐步推进。

一般灰度发布以机器维度进行。比如先在10%机器变更,同时观察系统性能指标及错误日志。

若观察一段时间后,系统指标依旧平稳且无大量错误日志,再推动全量变更。


所以灰度发布给了开发和运维同学转运机会,能在线上流量观察变更的影响,这是保证系统高可用的关键流程。


灰度发布是在系统正常运行条件下,保证系统高可用的运维手段,那如何知道发生故障时的系统表现?


故障演练

对系统进行一些破坏性的手段,观察在出现局部故障时,整体的系统表现是怎样的,从而发现系统中存在的,潜在的可用性问题。


比如磁盘,DB,网卡等组件随时随地可能故障,一旦故障,会不会如蝴蝶效应造成整体服务不可用呢?我们也无法知道,因此,必须故障演练。

和“混沌工程”的思路类似,作为混沌工程鼻祖,Netfix在2010年推出的“Chaos Monkey”工具就是故障演练绝佳的工具。它通过在线上系统上随机地关闭线上节点模拟故障,让工程师能够知晓在出现此类故障时会有何种影响。


这一切是以你的系统可抵御一些异常情况为前提。

若你的系统还没做到这点,建议你另外搭建一套和线上部署结构一模一样的线下系统,然后在这套系统上做故障演练,从而避免影响生产系统。


4 总结

开发注重的是如何处理故障,关键词是冗余和取舍


冗余指的是有备用节点,集群来顶替出故障的服务,比如文中提到的故障转移,还有多活架构等等

取舍指的是丢卒保车,保障主体服务安全

从运维角度来看则更偏保守,注重的是如何避免故障的发生,比如更关注变更管理以及如何做故障的演练。


两者结合起来才能组成一套完善的高可用体系。


提高系统的可用性,有时是以牺牲用户体验或系统性能为前提,也需大量人力才能建设完善。所以不该优化。比如核心系统四个九的可用性已经可满足需求,不必盲目追求更高可用性了。


有没有不追求性能,只追求极致可用性的呢?

有的。比如配置下发的系统,只需在其它系统启动时提供一份配置,所以秒级返回也可,十秒钟也OK,无非就是增加其它系统的启动时间。但对可用性要求极高,甚至六个九,因为配置可以获取慢,但不能获取不到!

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
6月前
|
消息中间件 缓存 NoSQL
谈谈高并发系统的设计方法论
设计 `高并发` 系统,就是要让该系统保证它 `整体可用` 的同时,能够尽可能多的 `处理很高的并发用户请求`,能够 `承受很大的负载流量冲击`。
744 6
|
6月前
|
缓存 NoSQL 关系型数据库
|
消息中间件 缓存 应用服务中间件
Nginx系列教程(02) - 高可用与高并发介绍
Nginx系列教程(02) - 高可用与高并发介绍
118 0
|
4月前
|
消息中间件 算法 数据库
架构设计篇问题之商城系统高并发写的问题如何解决
架构设计篇问题之商城系统高并发写的问题如何解决
|
1月前
|
Java Go 云计算
Go语言在云计算和高并发系统中的卓越表现
【10月更文挑战第10天】Go语言在云计算和高并发系统中的卓越表现
|
3月前
|
监控 算法 Java
企业应用面临高并发等挑战,优化Java后台系统性能至关重要
随着互联网技术的发展,企业应用面临高并发等挑战,优化Java后台系统性能至关重要。本文提供三大技巧:1)优化JVM,如选用合适版本(如OpenJDK 11)、调整参数(如使用G1垃圾收集器)及监控性能;2)优化代码与算法,减少对象创建、合理使用集合及采用高效算法(如快速排序);3)数据库优化,包括索引、查询及分页策略改进,全面提升系统效能。
49 0
|
4月前
|
消息中间件 缓存 监控
如何设计一个秒杀系统,(高并发高可用分布式集群)
【7月更文挑战第4天】设计一个高并发、高可用的分布式秒杀系统是一个非常具有挑战性的任务,需要从架构、数据库、缓存、并发控制、降级限流等多个维度进行考虑。
132 1
|
4月前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
57 0
|
6月前
|
算法
【数据结构与算法 11,高并发系统基础篇
【数据结构与算法 11,高并发系统基础篇
|
6月前
|
缓存 负载均衡 网络协议
作者推荐 | 高并发挑战?试试这些架构优化篇技巧,让你的系统焕发新生!
作者推荐 | 高并发挑战?试试这些架构优化篇技巧,让你的系统焕发新生!
341 1