【高可用架构】高可用架构的一般思路总结

前言

“高可用”,“高并发”,"一致性"都是老生常谈的问题了,他们的定义在百科都可以查到,本文不谈具体的架构,只是谈谈一般思路,总结一些概念切入点。想一想几个问题:

  1. 高可用解决的痛点是什么?
  2. 高可用架构设计难点在哪里?
  3. 有没有必要把所有的系统都按高可用设计?

正文

一般我们说的系统主要由处理程序和存储构成,我们的一个个服务的本质就是将数据按一定的逻辑处理输入输出,怎么让我们的输入输出能在可接受的时间内无人工介入地正常运行,就是我们做高可用要做的工作。

高可用解决的痛点是什么?

评估一个系统的高可用一般会用可用性去表示,可用性=平均故障间隔/(平均故障间隔+平均修复时间),也就是我们常说的多少个9,99.9%,99.99% 。 我们技术人员经常在写kpi的时候也会有一个服务的稳定性的指标和故障处理能力指标,如平均故障处理时间,平均故障反馈时间等。

  • 做好高可用,减少了运营期间,研发人员的介入,提高了用户体验,毕竟自动化的程序比手工操作来的快。
  • 提高了数据的安全性,没有100%可靠的程序,我们能做的就是把损失降到最低,通俗讲就是鸡蛋不能都放一个篮子里面。

有没有必要把所有的系统都按高可用设计?

很多小成本或者说一个创新产品(随时都可能下掉)的系统很少会考虑高可用,其实很容易理解,毕竟技术是为业务服务的吗,成本也是一个值得考量的因素。

  • 小公司,没有完善的基础建设,为一个不确定的产品考虑太多,一是影响开发进度,二是增加了早期投入的运营成本而且同机房的单点故障其实概率很低(前提是选择了靠谱的IDC托管,靠谱的云厂商),大部分程序可能运行个几年也就偶然几次小故障。可以在业务进入另一个里程碑的时候,结合预算进行架构演进,预算多了后,无论从用户角度还是从研发成本角度考虑都是有比较高的投入回报的
  • 大公司,基础设施完善,任何一个模块都有比较成熟稳定的高可用解决方案,早期的投入并不会很高,而且大部分都是资源共享的,不用白不用嘛,这个时候就可以一开始就将这部分考虑到系统架构设计中。

处理程序的高可用

处理程序一般都是无状态的,我们多增加处理程序来防止单点故障,对于有状态的,比如我们的Web服务,一般都会部署多台,然后通过负载均衡来让多个服务同时提供处理。

  • 就好比飞机有2个发动机,坏了一个还能继续飞。
  • 把一个域名DNS解析到2个Nginx,每个Nginx又负载均衡到N个节点上。
  • 多个Master,通过分布式锁,或者选主(利用zookeeper),让一个时刻只有一个点进行处理,一但故障出现时可以自动切换。
  • 多个Master,通过keepalived,然后通过vip进行提供服务。

存储的高可用

说到存储或者说数据库高可用,业界有个理论,CAP理论,说的是对一个系统来说,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance),只能同时满足其中的两项。网上也有其论证的文章,感兴趣的可以去查一下,我这里用一个比较直观的例子来描述我的理解。

  1. 假如我们现在有个单体的应用比如是http+web+mysql 的这种架构,对于web部分,我们可以参考上面说的处理程序的高可用进行设计。对于数据库Mysql来说,单点故障怎么解决?
  2. 俗话说鸡蛋不能放同一个篮子里面,同样我们的数据如果存在一个节点上,随时可能出现数据丢失或者说长时间无法恢复服务,为了降低风险,我们就必须冗余处理,如果一个点的故障率是1%,那么2个点同时故障的概率就降低到0.01%,这样我们的可用性(A) 就基本满足了。
  3. 但是当我们把数据进行多副本存储的时候,就必须面临的网络分区的问题,也就是P一般是要作为前提条件考虑的。
  4. 当出现网络分区了我们又面临了一个问题,我到底该往哪个节点写数据,该读哪个节点的数据,一个数据在不同节点可能存在不同的状态,这就是我们要考虑的一致性(C)的问题。

就如CAP理论所说,我们似乎陷入了一个死循环,但是人嘛总有些取舍,我们又不是机器即1非0,总有一种情况是可以被大家接受的。我们说的可用性,不会说是100%,通常是99.9%,99.99% , 99.999%。 似乎我们看到了一个跳出循环的办法,我们考虑C和P,同时把A的提升到一个我们能接受的范围不就可以了吗,这也是大部分热门的分布式数据库的做法。

三副本、四副本、五副本,两地三中心、两地四中心。

好了,到了这里我们已经明确了我们的方向,我们选择C和P,可用性上我们采用副本的方式来提高可用性。那么这里又有个问题了,既然选择了C那么多个副本的一致性怎么保证?

以MySQL的复制机制举例,有半同步复制,还有全同步复制,也有异步的复制。

  • semisync 插件实现半同步复制,这种机制下,可以保证binlog 至少同步到一个副本的relaylog后才提交事务,能保证数据不丢失。
  • 全同步机制,顾名思义就是要等到所有的副本全部写log成功后才提交事务,所以性能会受很大影响。
  • 异步复制是传统的Master -Slaver模式,副本都是异步同步的,只能做到最总一致性,但是性能是最高的。

到了这里,显然这个半同步复制更符合我们的要求,但是只要求写一个从成功能保证一致性吗?

Quorum机制了解一下?N个节点,只要保证W(写)+R(读)>N 即可保证数据的一致性,也就是常说的写半数以上节点。

当发送故障时需要在R个副本(最新写成功的节点)中选出一个节点作为主节点。

怎么选这个主节点出来,就要涉及到一些分布式的共识算法如Paxos,和Raft中。Leader election等

总结

在系统设计中,如果要实现高可用,必然需要采用多副本的模式,多副本下的写机制一般采用写半数以上节点的同步写机制,在这种分布式系统中,没有固定的Master,同一时刻只有一个节点作为Master提供服务,当这个节点出现问题时,通过选举算法在写成功的那些节点中选出一个新的Master提供服务。

上面对CAP的一些理解可能不是正在意义上的CAP,理解CAP理论也不是说为了让我们的系统就要按这个来设计一个AP或者CP的系统,个人觉得CAP理论更应该是作为一个"尺",可以作为我们在设计系统的时候对 业务和成本等因素的一个权衡标准,也不一定要其中的2个,我们也可以选90%C,90%A,100%P,不是吗?。

进阶学习

  • Paxos 、Multi-paxos、Raft
  • Redis sentinel的 领头选举
  • Zookeeper的选举,ZAB协议