50

人人都想学架构(四)

 4 years ago
source link: https://www.tuicool.com/articles/En2EBjJ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本文是《从0开始学架构》专栏学习的第四篇,主要讲解高可用架构,本文记录的是第六节CAP,CAP是一个理论,有很多不同的版本,所以理解的时候非常困惑,我觉得作者这个版本讲解的很全面,结合留言,让我对它的理解更上一层楼了,理论毕竟是理论,也没有绝对的对与错,重要的是学会思路,以便解决问题。

什么是CAP,在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保证一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须被牺牲。

分布式系统一定是有多个节点的,节点是互联的,共享代表某个节点有其他节点的数据(每个节点的数据不一定有全部数据)。按照这个理解,Memcached集群中每个节点数据都是独立的,所以不是CAP探讨的对象。

MySQL主从集群看上去算CAP探讨的对象,从写数据的角度看也能符合CA系统,可它是一个单点系统,如果遇到主库故障,则整个写服务就不可用了,如果是单点系统,这就不算一个分布式系统了(以上的领悟来源于留言,也是今天的收获)。

什么是一致性,首先要从 客户端 的角度去看,读操作保证能返回最新的写操作结果,其实一致性是CAP中最让人困惑的一个概念,专栏没有细说,最近在看《NoSQL精粹》这篇文章,讲的更全面。

CAP中的一致性表示线性一致性。最新的结果不代表节点之间数据是相同的,比如在更新一个事务的时候,某个节点拥有了最新的数据,但还没有提交,从这个角度看,其他节点没有办法获取未提交事务的数据。

什么是可用性,非故障的节点在合理的时间内返回合理的响应(reasonable response)。

客户端和节点之间如果有故障,这个和此处的非故障节点不是一回事,在分布式系统中,集群中的某个节点肯定会遇到故障,这个故障会影响其他非故障节点。

合理的响应表示没有错误或超时(如果不能连接其他节点或者连接超时则表示不具备可用性),但成功响应结果不代表是正确的(逻辑上)。

CAP中的可用性和高可用不一样,高可用是指部分实例挂了,能自动摘除,并由其它实例继续提供服务,关键是冗余。

什么是分区容忍性,当出现网络分区后,系统还能够“履行职责”,网络分区表示集群中某些节点不能和其他节点互通了,可能是丢包,也可能是连接中断,或者网络拥塞。履行职责和可用性是一致的,就是 reasonable response。

在分布式系统中,CAP中的P一定会发生,如果我们选择了 CA 而放弃了 P,那么当发生分区现象时,为了保证 C,系统需要禁止写入,当有写入请求时,系统返回 error(例如,当前系统不允许写入),这又和 A 冲突了,因此分布式系统理论上不可能选择 CA 架构,只能选择 CP 或者 AP 架构。关于这一点, 放弃P其实代表单点故障,MySQL主从是符合的,可分布式系统写入点不仅仅是一个节点,因为它们都是分片或分区的,那这个怎么牺牲?有个用户也留言了说牺牲P,说好说,怎么牺牲?理论和实践上还是有很长的路

什么是CP,见下图:

Qv2a2iv.png!web

由于分区造成同步问题,为了保证P和C,系统必须告诉用户功能部分不可用,由于是不可用,间接说明客户不会遇到最新数据的问题了。

保证P,代表系统在分区的情况下还能提供部分功能。

什么是AP,见下图:

7ZFjAjZ.png!web

发生分区后,为了保证A,此时客户拿不到最新的数据,牺牲了C。

以上内容好像很好理解,但作者认为这些概念太抽象化了,省去了很多细节,在具体实践的时候,由于情况很复杂,很容易出现误解和偏差,所以下面说的才是重点。

1:CAP关注大力度是数据,而不是整个系统。

根据数据的不同应用场景,选择性的使用CP或者AP,不是说一个系统只能选择CP或AP。

2:CAP是忽略网络延迟的

可这个问题确实又存在,在分布式环境下无法做到完美,所以对于一些重要级别的操作(比如用户余额),在这种情况下,只能选择CA,也就是单点写入,其他节点做备份,无法做到 分布式下的多点写入 。(非常感谢,我读了很多遍才有了体会)。

关于这点感觉说的就是MySQL(其他的中间件我没想到)主从,对于单个用户余额来说无法应用分布式架构,可对所有用户来说还是一个分布式架构。比如北京的用户存在在北京,广州的用户存在在广州,两个城市有全量数据,在无法保证P的情况下(比如北京节点挂了),对于部分来说至少广州节点还能用,但对于单个用户来说他可能就完全不能使用了,个体是非分布式的,整体是分布式的。

3:正常的情况下,可以同时存在CA

在不考虑P的情况下(假设不会出现网络分区),不同级别的数据实现CA的方式也可以不一样,比如不重要的数据就使用“数据库同步”的方式(简单但延迟高),重要的数据使用队列的方式(复杂但实时性高)。

4:废弃并不等于什么都不做,需要为分区恢复做好准备。

分区并不是经常性发生,在恢复后,要尽量让系统恢复到CA。麻烦的就是某些数据可能会有冲突,需要想一些策略来同步数据。

和CAP相关的两个概念是ACID和BASE,ACID来是为了保证数据库事务性的,其实没有可比性。网络上有很多比较Redis和MySQL事务的文章,强行比较挺难为人的。这个后续我再参考资料后再分享。

对于BASE来说,它是CAP理论中AP方案的延伸,更具有实践性。

BASE 是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency),核心思想是即使无法做到强一致性(CAP 的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性。

对于 基本可用 ,表示损失 部分 可用性,保证 核心 可用,部分和核心需要仔细分辨。

软状态,允许系统存在中间状态,而该中间状态不会影响系统整体可用性。这里的中间状态就是 CAP 理论中的数据不一致。

最终一致性,一定时间后数据最终一致,即达到CA。

BASE 理论本质上是对 CAP 的延伸和补充,更具体地说是对 CAP 中 AP 方案的一个补充

  • 延迟是肯定存在的

  • AP 方案中牺牲一致性只是指分区期间,而不是永远放弃一致性。

这一节写的很精彩,留言更精彩,摘抄一段:

设计分布式系统的两大初衷:横向扩展(scalability)和高可用性(availability)。“横向扩展”是为了解决单点瓶颈问题,进而保证高并发量下的「可用性」;“高可用性”是为了解决单点故障(SPOF)问题,进而保证部分节点故障时的「可用性」。由此可以看出,分布式系统的核心诉求就是「可用性」。这个「可用性」正是 CAP 中的 A:用户访问系统时,可以在合理的时间内得到合理的响应。

为了保证「可用性」,一个分布式系统通常由多个节点组成。这些节点各自维护一份数据,但是不管用户访问到哪个节点,原则上都>应该读取到相同的数据。为了达到这个效果,一个节点收到写入请求更新自己的数据后,必须将数据同步到其他节点,以保证各个节点的数据「一致性」。这个「一致性」正是 CAP 中的 C:用户访问系统时,可以读取到最近写入的数据。

需要注意的是:CAP 并没有考虑数据同步的耗时,所以现实中的分布式系统,理论上无法保证任何时刻的绝对「一致性」;不同业务系统对上述耗时的敏感度不同。

分布式系统中,节点之间的数据同步是基于网络的。由于网络本身固有的不可靠属性,极端情况下会出现网络不可用的情况,进而将网络两端的节点孤立开来,这就是所谓的“网络分区”现象。“网络分区”理论上是无法避免的,虽然实际发生的概率较低、时长较短。没有发生“网络分区”时,系统可以做到同时保证「一致性」和「可用性」。

发生“网络分区”时,系统中多个节点的数据一定是不一致的,但是可以选择对用户表现出「一致性」,代价是牺牲「可用性」:将未能同步得到新数据的部分节点置为“不可用状态”,访问到这些节点的用户显然感知到系统是不可用的。发生“网络分区”时,系统也可以选择「可用性」,此时系统中各个节点都是可用的,只是返回给用户的数据是不一致的。这里的选择,就是 CAP 中的 P。

分布式系统理论上一定会存在 P,所以理论上只能做到 CP 或 AP。如果套用 CAP 中离散的 C/A/P 的概念,理论上没有 P 的只可能是单点(子)系统,所以理论上可以做到 CA。但是单点(子)系统并不是分布 式系统,所以其实并不在 CAP 理论的描述范围内。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK