高可用
wiki
高可用性(英语:high availability,缩写为 HA),IT术语,指系统无中断地执行其功能的能力,代表系统的可用性程度。是进行系统设计时的准则之一。高可用性系统与构成该系统的各个组件相比可以更长时间运行。
高可用性通常通过提高系统的容错能力来实现。定义一个系统怎样才算具有高可用性往往需要根据每一个案例的具体情况来具体分析。
评定标准
其度量方式,是根据系统损害、无法使用的时间,以及由无法运作恢复到可运作状况的时间,与系统总运作时间的比较。
度量方式 就是是SLA,全称 Service Level Agrement,也就是有几个9的高可用性。
计算公式为:
A = MTBF / (MTBF + MTTR)
A(可用性),MTBF(平均故障间隔),MDT(平均修复时间)
在线系统和执行关键任务的系统通常要求其可用性要达到5个9标准(99.999%)。
ps: 99.999%,即年故障时间:32秒。
例子
百度的搜索首页,是业内公认高可用保障非常出色的系统,甚至人们会通过 www.baidu.com 能不能访问来判断“网络的连通性”,百度高可用的服务让人留下啦“网络通畅,百度就能访问”,“百度打不开,应该是网络连不上”的印象,这其实是对百度HA最高的褒奖。
如何保证
我们都知道,单点是系统高可用的大敌,单点往往是系统高可用最大的风险和敌人,应该尽量在系统设计的过程中避免单点。
方法论上,高可用保证的原则是“集群化”,或者叫“冗余”:只有一个单点,挂了服务会受影响;如果有冗余备份,挂了还有其他backup能够顶上。
保证系统高可用,架构设计的核心准则是:冗余。
有了冗余之后,还不够,每次出现故障需要人工介入恢复势必会增加系统的不可服务实践。
所以,又往往是通过“自动故障转移”来实现系统的高可用。
接下来我们看下典型互联网架构中,如何通过冗余+自动故障转移来保证系统的高可用特性。
设计原理
要做到数据不丢,就必需要持久化
要做到服务高可用,就必需要有备用(复本),无论是应用结点还是数据结点
要做到复制,就会有数据一致性的问题。
我们不可能做到100%的高可用,也就是说,我们能做到几个9个的SLA。
一些技巧
高并发原则
-
无状态设计:因为有状态可能涉及锁操作,锁又可能导致并发的串行化。
-
保持合理的粒度:无论拆分还是服务化,其实就是服务粒度控制,控制粒度为了分散请求提高并发,或为了从管理等角度提高可操性。
-
缓存、队列、并发等技巧在高并发设计上可供参考,但需依场景使用。
高可用原则
-
系统的任何发布必须具有可回滚能力。
-
系统任何外部依赖必须准确衡量是否可降级,是否可无损降级,并提供降级开关。
-
系统对外暴露的接口必须配置好限流,限流值必须尽量准确可靠。
业务设计原则
-
安全性:防抓取,防刷单、防表单重复提交,等等等等。
-
at least 消费,应考虑是否采用幂等设计
-
业务流程动态化,业务规则动态化
-
系统 owner 负责制、人员备份制、值班制
-
系统文档化
-
后台操作可追溯
高可用
事前:副本、隔离、配额、提前预案、探知
事发:监控、报警
事中:降级、回滚、应急预案,failXXX系列
事后:复盘、思考、技改
事前
- 副本
数据冗余。
当代理通过心跳检测机制检测到有一台机器出现问题时,就将其下线,其他‘副本’机器继续提供服务;存储领域也是经常使用副本技术的。
- 隔离技术
隔离其实就是一种,即资源隔离。
因此,隔离的本质,其实就是对资源的独立保护。因为每个资源都得到了独立的保护,其中一个资源出了问题,不会影响到其他资源,这就提高了整体服务的可用性。
- 配额技术
限流是配额技术的一种,它通过调节入口流量水位上线,来避免供给不足所导致的服务宕机。
- 探知技术
压测和演练和最常见的探知技术。
- 预案
预案一般分为提前预案(事前)和应急预案(事中)。
事发
- 监控和报警
越早识别故障,就能越早解决问题。
CI 便是为此而生。
事中
- 降级
降级的本质是弃车保帅,通过临时舍弃部分功能,保证系统整体可用性。
不可能有真正的无损降级,而常说的无损降级指的是用户体验无损。
降级一定发生在层与层之间(上下游),要么 a 层临时性不调用 b 层,这叫做熔断,
要么 a 层临时调用 c 层( c 层合理性一定小于 b 层),这叫备用链路。
- 回滚
回滚有一个大前提:变更必须具有可回滚性。
比如DB的事务回滚(DB事务机制),代码库回滚(GIT的文件版本控制),发布回滚(发布系统支持)等等。
- failXXX 系列
当出现下游调用失败时,我们一般有几种处理方式
-
failretry,即失败重试,需要配合退避时间,否则马上重试不一定会有效果。
-
failover,即所谓的故障转移。比如调用下游a接口失败,那么RPC的负载均衡器将会调用a接口提供方的其他机器进行重试;在比如数据库x挂了,应用自 适应容灾将对x库的调用切换到y库调用,此y库即可以是faillover库(流水型业务),也可以备库(状态型业务)。
-
failsafe,即静默,一般下游链路是弱依赖的时候,可以采用failsafe,即可和failover相结合,比如failover了3次还是失败,那么执行 failsafe。
-
failfast,立即报错,failfast主要让工程师快速的感知问题所在,并及时进行人工干预。
-
failback,延迟补偿(回血),一般可以采用消息队列或定时扫描等。
事后
复盘、思考、技改。不多赘述。
高并发
核心原则
想要高并发无外乎从以下几个方面入手:
- 提高处理速度
缓存 异步
- 增加处理人手
多线程(多进程),扩容
- 减少访问人数
预处理,本文不涉及
提高处理速度
- 缓存
① 从效果角度。命中率越高越好吗?10万个店铺数据,缓存了1000个,命中率稳定100%,那是不是说,有99000个店铺都是长尾店铺?缓存效果评估不能单看命中率。
② 从回收策略。如果把缓存当做数据库一样的存储设备去用,那就没有回收的说法了(除非重启或者宕机,否则数据依然有效);如果只存储热数据,那就有回收和替换的问题。回收有两种方 式,一种是空间配额,另一种是时间配额。替换也有几种方式,LRU,FIFO,LFU。
③ 从缓存使用模式角度:用户直接操作缓存和db;用户直接操作缓存,缓存帮助我们读写DbB;
④ 从缓存分级角度。java堆内缓存、java堆外缓存、磁盘缓存、分布式缓存,多级缓存。
⑤ 从缓存使用角度。null穿透问题、惊群问题、缓存热点问题、缓存一致性问题、读写扩散问题。。。。。。
⑥ 更新方式。读更新、写更新、异步更新。
- 异步
业务允许延迟处理,是使用队列中间件的大前提,即非实时系统或准实时系统更适合使用。
主要作用有:异步处理(增加吞吐),削峰蓄洪(保障稳定性),数据同步(最终一致性组件),系统解耦(下游无需感知订阅方)。
同步转异步,可以提高吞吐量;异步转同步,可以增加可靠性。
增加处理人手
- 多线程
线程数:一般设置的时候,会参考平均处理时长、并发峰值、平均并发量、阻塞率、最长可容忍响应时间、CPU核心数。
- 扩容
在无状态服务下,扩容可能是迄今为止效果最明显的增加并发量的技巧之一。
从扩容方式角度讲,分为垂直扩容(scale up)和水平扩容(scale out)。
垂直扩容就是增加单机处理能力,怼硬件,但硬件能力毕竟还是有限;水平扩容说白了就是增加机器数量,怼机器,但随着机器数量的增加,单应用并发能力并不一定与其呈现线性关系, 此时就可能需要进行应用服务化拆分了。
从数据角度讲,扩容可以分为无状态扩容和有状态扩容。
无状态扩容一般就是指我们的应用服务器扩容;有状态扩容一般是指数据存储扩容,要么将一份数据拆分成不同的多份,即sharding,要么就整体复制n份,即副本。
sharding遇到的问题就是分片的可靠性,一般做转移、rehash、分片副本;副本遇到的问题是一致性性,一般做一致性算法,如paxos,raft等。
常见架构
拓展阅读
- cache
- 实时监控
- 限流 & 降级
- 负载均衡
- 数据库平滑切分
参考资料
- 高可用
https://coolshell.cn/articles/17459.html
https://zh.wikipedia.org/wiki/%E9%AB%98%E5%8F%AF%E7%94%A8%E6%80%A7
- 如何设计
http://ifeve.com/%E5%A6%82%E4%BD%95%E5%BB%BA%E8%AE%BE%E9%AB%98%E5%8F%AF%E7%94%A8%E7%B3%BB%E7%BB%9F/
http://www.infoq.com/cn/articles/designing-a-microservices-architecture-for-failure
https://linux.cn/article-8377-1.html
http://kriszhang.com/high_performance/
https://coolshell.cn/articles/17459.html
- 常见互联网高可用架构
https://www.xncoding.com/2017/06/30/architect/ha.html
https://tech.meituan.com/tag/%E9%AB%98%E5%8F%AF%E7%94%A8