高可用包括:存储高可用,计算高可用,业务高可用。
一、存储高可用
存储的高可用,主要是通过数据冗余的方式来实现高可用,复杂性主要是在如何保持数据一致性,复制延迟和网络中断都会带来数据不一致。主要考虑的就是,数据如何复制,如何应对复制延迟,如何应对复制中断,各个节点的职责是什么。
常见的存储架构:主从,主备,主主,集群,分区。
1.主备,最常见最简单的一种存储方案。
主机存储数据,通过复制通道将数据复制到备机,客户端无论读写操作 ,都发送给主机。
备机不对外提供任何读写服务。
主机故障情况下,此时整个系统处于不可用状态,不能读写数据,如果主机不能恢复(例如,机器硬盘损坏,短时间内无法恢复), 则需要人工操作, 将备机升为主机。
优点:
对于客户端来说,不需要感知备机的存在。即使灾难恢复后,客户端无须知道是原来的备机升级为主机了 。
对于主机和备机来说 , 双方只需要进行数据复制即可,无须考虑太复杂的数据一致性问题。
缺点:
备机仅仅只为备份,并没有提供读写操作 ,硬件成本上有浪费。
故障后需要人工干预,无法自动恢复。
综合主备复制架构的优缺点,内部的后台管理系统使用主备复制架构的情况会比较多,数据变更频率很低,即使在某些场景下丢失,也可以通过人工的方式补全。
2.主从,主机负责读写操作,从机只负责读操作,不负责写操作。
主机存储数据,通过复制通道将数据复制到从机。
正常情况下,客户端写操作发送给主机,读操作可发送给主机也可以发送给从机。
主机故障情况下,客户端无法进行写操作,但可以将读操作发送 给从机,从机继续响应读操作。如果主机不能恢复(例如,机器硬盘损坏,短时间内无法恢复), 则需要人工操作, 将备机升为主机。
如果主从间数据复制延迟,则会出现主从读取的数据不一致的问题。
主从复制与主备复制相比,有以下不同的优缺点 :
主从复制在主机故障时,读操作相关的业务不受影响;发挥了硬件的性能;
主从复制要比主备复制复杂更多,主要体现在客户端需要感知主从关系,并将不同的操作发给不同的机器进行处理 。
综合主从复制的优缺点 , 一般情况下,写少读多的业务使用主从复制的存储架构比较多。例如,论坛、 BBS 、新闻网站这类业务。
主备倒换与主从倒换:
主机故障后,无法进行写操作 ,需要人工指定新的主机角色。
主备倒换和主从倒换方案就是为了解决上述问题而产生的。简单来说,这两个方案就是在原有方案的基础上增加 “倒换”功能, 即系统自动决定主机角色, 并完成角色切换 。
倒换方案的实现的要点:
主备间状态判断,状态传递的渠道(相互连接,还是第三方仲裁),状态检测的内容(进程存在,响应缓慢等)
倒换决策,什么情况下备机升级为主机,原来主机恢复后是否要再次倒换,倒换是完全自动,还是半自动需要人工确认。
数据冲突解决,原故障主机恢复后,新旧主机之间可能存在数据冲突。
3.主主复制,两台主机都存储数据,客户端将读写操作发送给任意一台主机。
主主复制架构,必须保证数据能够双向复制,对数据的设计有严格的要求,一般适合于那些临时性,可丢失,可覆盖的数据场景。例如用户的session数据,用户的行为日志数据,论坛的草稿数据等。
4.数据集群,这里主要指数据分散集群,每台服务器负责存储一部分数据,同时每台服务器会备份一部分数据。
设计集群时考虑点:
均衡性,保证服务器上的数据分区基本是均衡的。
容错性,当部分服务器故障时,将原来分配给故障服务器的数据分区分配给其他服务器。
可伸缩性,当集群容量不够,扩充新服务器后,能够自动将部分数据分区迁移至新服务器,保证扩容后的均衡性。
数据分散集群中的每台服务器都可以处理读写请求,必须有一个角色来负责执行数据分配算法,就像hadoop中的namecode。
分布式事务
数据可能分布在不同的集群节点上,由于节点间只能通过消息进行通信,因此分布式事务只能依赖消息通知,消息的不可靠性,这就带来了分布式事务的复杂性。
分布式事务算法中常见的有“二阶段提交”和“三阶段提交”
二阶段提交,“commit请求阶段”和“commit提交阶段”,(1)存在一个节点协调者,协调者向所有参与者发送询问是否可以执行提交事务;(2)参与者执行事务操作,执行成功,则将undo信息和redo信息写入日志,锁定资源返回YES不提交事务,执行失败,返回NO给协调者;(3)协调者收到响应消息都为YES时,发送COMMIT请求,如果任一参与者返回NO,则发送ROLLBACK请求,参与者执行事务操作,返回ACK消息,协调者收到反馈后确认是完成或取消事务。
实现简单,但缺点也很明显:同步阻塞,协调者和参与者互相等待响应消息,如果某个节点响应消息比较慢,则整个系统全部被拖慢,不适合高并发场景;状态不一致,某一参与者如果没有收到commit消息,会一直等待直到超时后回滚事务,其他参与者都已提交事务,导致事务状态不一致。
三阶段提交,协调者先向所有参与者发送一个询问是否可以执行事务,协调者在超时时间内收到所有yes后进入第二阶段;协调者发送准备提交请求,参与者执行事务操作,记录undo和redo事务日志,返回ACK消息;协调者收到所有ACK消息后,发送commit请求,如果没有收到全部ACK,则会发出回滚请求,参与者收到请求执行操作,如果等待超时还是会执行commit请求。
5.数据分区,指将数据按照一定的规则进行分区,不同分区分布在不同的地理位置上。
通过这种方式来规避地理级别的故障造成的巨大影响。
常见的分区复制规则:(1)集中式,备份指存在一个总的备份中心,所有的分区都将数据备份到备份中心。设计简单,分区间无交互,扩展容易,成本较高。(2)互备式,每个分区备份另外一个分区的数据,设计复杂,分区相互间互相关联和影响,扩展复杂,成本低,直接利用已有的设备。(3)独立式,每个分区自己有独立的备份中心,设计简单,扩展容易,成本高。
二、计算高可用
当部分硬件损坏时,计算任务能够继续正常运行。通过增加更多服务来达到计算高可用。
主备架构是计算高可用最简单的架构,可以细分为冷备架构和福备架构,常用温备架构 。
温备架构,备机上的业务系统己经启动,只是不对外提供服务,主机故障后,人工只需要将任务分 配器的任务请求切换为发送到备机即可。
高可用计算的集群
对称集群,集群中每个服务器的角色都是一样的,都可以执行所有任务,更通俗的叫法是负载均衡集群。
非对称集群, 集群中的 服务器分为多个不同的角色,不同的角色执行不同的任务,例如,最常见的 Master-Slave 角色。
不同角色的服务器承担不同的职责 。 以 Master-Slave 为例,部分任务是 Master 服务器才能执行,部分任务是 Slave 服务器才能执行。当指定类型的服务器故障时,需要重新分配角色。例如 ,Master 服务器故障后, 需要将剩余的 Slave 服务器中的一个重新指定为 Master服务器;Slave服务器故障,只需要剔除就可以了。
以 ZooKeeper 为例:
( 1 )任务分配器: ZooKeeper 中不存在独立的任务分配器节点,每个 Server 都是任务分配器, Follower 收到请求后会进行判断,如果是写请求就转发给 Leader,如果是读请求就自己处理。
(2 )角色指定: ZooKeeper 通过 ZAB 协议来选举 Leader,当 Leader 故障后,所有的 Follower 节点会暂停读写操作,开始进行选举,直到新的 Leader 选举出来后才继续对 Client 提供服务 。
三、业务高可用
业务高可用,如果保证了存储高可用和计算高可用,业务高可用的保障也已经很高了,通常来说已经可以满足大部分系统的需求了。这里再谈一下异地多活,针对极端情况的高可用方案。还有接口级故障方案,系统没有宕机网络也没问题情况下,表现为响应慢。
1.异地多活
异地就是指地理位置上不同的地方 通常指不同的机房, 类似于“不要把鸡蛋都放在同一篮子里”;
多活就是指不同地理位置上的系统都能够提供业务服务。
实现异地多活有很高的代价,具体表现为:
• 系统复杂度会发生质的变化,需要设计复杂的异地多活架构。
• 成本会上升,毕竟要多在一个或多个机房搭建独立的一套业务系统。
异地多活通常可以分为三种,同城异区,跨城异地,跨国异地。
同城异区指的是将业务部署在同一个城市不同区的多个机房 。关键在于搭建高速网络将两个机房连接起来,达到近似一个本地机房的效果。架构设计 上可以将两个机房当作本地机房来设计,无须额外考虑 。
跨城异地指的是业务部署在不同城市的多个机房,而且距离最好要远一些。跨城异地距离较远带来的网络传输延迟问题,给业务多活架构设计带来了复杂性,在数据短时间不一致的情况下,还能够正常提供业务 。架构设计的主要目的就是为了解决这个矛盾。
跨城异地肯定会导致数据不一致,如何解决这个问题呢?
重点还是在“数据”上,即根据数据的特性来做不同的架构。如果 是强一致性要求的数据,例如,银行存款余额,支付宝余额等,这类数据实际上是无法做到跨 城异地多活的 。
支付宝等金融相关的系统,对余额这类数据,不能做跨 城异地的多活架构,而只能采用同城异区这种架构 。
跨国异地指的是业务部署在不同国家的多个机房。跨国异地的距离更加远 了,因此数据同步的延时会更长,正常情况下可能就有几秒钟了。主要是面向不同地区用户提供业务,或者提供只读业务,对架构设计要求不高。
跨城异地多 活架构设计的一些技巧和步骤 :
技巧:
(1)保证核心业务的异地多活
(2)核心数据最终一致性,数据同步是异地多活架构的设计核心 。尽量减少数据同步,只同步核心业务相关的数据,保证最终一致性,不保证实时一致性。
采用多种手段同步数据:
存储系统本身都会有同步的功能,MySQL 的主备复制、 Redis 的 Cluster 功能、 Elasticsearch 的集群功能 。
当我们只考虑存 储系统本身的同步功能时,就会发现无法做到真正的异地多活。以 MySQL 为例, MySQL5.l 版本的复制是单线程的复制,在网络抖动或大量数据 同步时 , 经常发生延迟较长的问题,短则延迟十几秒,长则可能达到十几分钟 。
解决的方案就是拓展思路,避免只使用存储系统的同步功能,可以将多种手段配合存储系 统的同步来使用:1.消息队列方式,将数据通过消息队列同步到其他业务中心。2.二次读取方式,B 中心在读取本地数据失败时,可以根据路由规则,再去 A 中心访问一次。3.存储系统同步方式。4.回源读取方式,不同步数据,根据路由回原中心读取。5.重新生成数据方式。
步骤:
第一步:业务分级,挑选出核心的业务,只为核心业务设计异地多活,降低方案复杂度和成本。
第二步:数据分类,识别所有的数据及数据特征,数据特征会影响后面的方案设计。
数据特征分析维度:
数据量、唯一性(同类数据必须保证唯一 ,例如用户 ID)、可丢失性、可恢复性
第三步 : 数据同步,根据不同的数据设计不同的同步方案。
第四步:异常处理,一旦出现极端异常的情况,总是会有部分数据出现异常的。出现这些问题时,系统将采 取什么措施来应对。
常见的异常处理措施有如下几类。
( 1 )多通道同步 。采取多种方式来进行数据同步,其中某条通道故障的情况下 ,系统可以通过其他方式来进行同步。
( 2 )同步和访问结合。访问指异地机房通过系统的接口来进行数据访问 。
( 3 )日志记录 。用于故障恢复后对数据进行恢复。
2.接口级故障应对方案——降级、熔断、限流、排队
接口级故障的典型表现就是系统并没有宕机, 网络也没有中断, 但业务却出现问题了 。 例如,业务响应缓慢, 大量访问超时, 大量访问出现异常 ( 给用户弹出提示“无法连接数据库勺, 这类问题的主要原因在于系统压力太大, 负载太高, 导致无法快速处理业务请求, 由此引发更多的后续问题。最终用户看到的现象就是访问很慢。
导致接口级故障的原因,一般有如下几种 :
• 内部原因 程序 bug 导致死循环, 某个接口导致数据库慢查询, 程序逻辑不完善导致耗尽内存等。
• 外部原因 黑客攻击、促销或抢购引入了超出平时几倍甚至几十倍的用户访问, 第三方系统大量请求,第三系统响应缓慢, 等等 。
解决接口级故障的核心思想和异地多活基本类似:优先保证核心业务 , 优先保证绝大部分用户 。
(1)降级,系统将某些业务或接口的功能降低,可以是只提供部分功能,优先保证核心业务。
常见的实现降级 的方式有如下几种 :
• 系统后门降级,系统预留了后门用于降级操作,系统提供一个降级 URL, 当访问这个URL时 ,就相当于执行降级指令。
• 独立降级系统,将降级操作独立到一个单独的系统中。
(2)熔断,降级的目的是应对系统自身的故障,而熔断的目的是应对依赖的外部系统故障的情况。
A 服务的 X 功能依赖 B 服务的某个接口,当 B 服务的接口响应很慢的时候, A 服务的 X 功能响应肯定也会被拖慢,进一步导致 A 服务的线程都被卡在 X 功能处 理上,此时 A 服务的其他功能都会被卡住或响应非常慢 。 这时就需要熔断机制了,即 A 服务不 再请求 B 服务的这个接口, A 服务内部只要发现请求 B 服务的这个接口就立即返回错误,从而 避免 A 服务整个被拖慢甚至拖死。
熔断机制实现的关键是需要有一个统一的 API 调用层,由 API 调用层来进行采样或统计, 如果接口调用散落在代码各处就没法进行统一处理了 。
另外一个关键是阔值的设计。1 分钟内 30% 的请求响应时间超过 l 秒就熔断,这个策略中的“ 1 分钟”“ 30% ”“ l 秒”都对最终的熔断效果有影响 。
(3)限流,限流则是从用户访问压力的角度来考虑如何应对故障。 限流指只允许系统能够承受的访问量进来,超出系统访问能力的请求将被丢弃。
限流一般都是系统内实现的 ,常见的限流方式可以分为两类:基于请求限流和基于资源限流。
基于请求限流指从外部访问的请求角度考虑限流,常见的方式有限制总量和限制时间量 。
基于资源限流是从系统内部考虑 的, 即找到系统内部影响性能的关键资源,对其使用上限进行限制 。 常见的内部资源有连接数、文件句柄 、 线程 数、请求队列等 。
(4)排队,排队实际上是限流的一个变种 ,限流是直接拒绝用 户 ,排队是让用户等待很长时间,
一般情况下, 排队需要用独立的系统去实现。例如,使用 Kafka 这类消息队列来缓存用户请求。
网友评论