【Java】分布式系统中的CAP理论

C:一致性(Consistency )

A:可用性(Availability)

P:分区容错性(Partition tolerance)

 

CAP理论指一个分布式系统中,只能同时满足上述三项中的两项。

                          

1、一个小例子

首先我们看一张图。

                            

现在网络中有两个节点N1和N2,他们之间网络可以连通,N1中有一个应用程序A,和一个数据库V,N2也有一个应用程序B2和一个数据库V。现在,A和B是分布式系统的两个部分,V是分布式系统的两个子数据库。

现在问题来了。突然有两个用户小明和小华分别同时访问了N1和N2。我们理想中的操作是下面这样的。

(1)小明访问N1节点,小华访问N2节点。同时访问的。

(2)小明把N1节点的数据V0变成了V1。

(2)N1节点一看自己的数据有变化,立马执行M操作,告诉了N2节点。

(4)小华读取到的就是最新的数据。也是正确的数据。

上面这是一种最理想的情景。它满足了CAP理论的三个特性。现在我们看看如何来理解满足的这三个特性。

一致性

一致性指的是所有节点在同一时间的数据完全一致。就好比刚刚举得例子中,小明和小华读取的都是正确的数据,对他们用户来说,就好像是操作了同一个数据库的同一个数据一样。

因此对于一致性,也可以分为从客户端和服务端两个不同的视角来理解。

(1)客户端

从客户端来看,一致性主要指的是多并发访问时更新过的数据如何获取的问题。也就是小明和小华同时访问,如何获取更新的最新的数据。

(2)服务端

从服务端来看,则是更新如何分布到整个系统,以保证数据最终一致。也就是N1节点和N2节点如何通信保持数据的一致。

对于一致性,一致的程度不同大体可以分为强、弱、最终一致性三类。

(1)强一致性

对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。比如小明更新V0到V1,那么小华读取的时候也应该是V1。

(2)弱一致性

如果能容忍后续的部分或者全部访问不到,则是弱一致性。比如小明更新VO到V1,可以容忍那么小华读取的时候是V0。

(3)最终一致性

如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。比如小明更新VO到V1,可以使得小华在一段时间之后读取的时候是V0。

可用性

可用性指服务一直可用,而且是正常响应时间。就好比刚刚的N1和N2节点,不管什么时候访问,都可以正常的获取数据值。而不会出现问题。好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。

分区容错性

 分区容错性指在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。就好比是N1节点和N2节点出现故障,但是依然可以很好地对外提供服务

 

N1节点更新了V0到V1,想在也想把这个消息通过M操作告诉N1节点,却发生了网络故障。这时候小明和小华都要同时访问这个数据,怎么办呢?现在我们依然想要我们的系统具有CAP三个特性,我们分析一下会发生什么。

(1)系统网络发生了故障,但是系统依然可以访问,因此具有容错性。

(2)小明在访问节点N1的时候更改了V0到V1,想要小华访问节点N2的V数据库的时候是V1,因此需要等网络故障恢复,将N2节点的数据库进行更新才可以。

(3)在网络故障恢复的这段时间内,想要系统满足可用性,是不可能的。因为可用性要求随时随地访问系统都是正确有效的。这就出现了矛盾。

正是这个矛盾所以CAP三个特性肯定不能同时满足。既然不能满足,那我们就进行取舍。

有两种选择:

(1)牺牲数据一致性,也就是小明看到的衣服数量是10,买了一件应该是9了。但是小华看到的依然是10。

(2)牺牲可用性,也就是小明看到的衣服数量是10,买了一件应该是9了。但是小华想要获取的最新的数据的话,那就一直等待阻塞,一直到网络故障恢复。

现在你可以看到了CAP三个特性肯定是不能同时满足的,但是可以满足其中两个。

三、CAP特性的取舍

我们分析一下既然可以满足两个,那么舍弃哪一个比较好呢?

(1)满足CA舍弃P,也就是满足一致性和可用性,舍弃容错性。但是这也就意味着你的系统不是分布式的了,因为涉及分布式的想法就是把功能分开,部署到不同的机器上。

(2)满足CP舍弃A,也就是满足一致性和容错性,舍弃可用性。如果你的系统允许有段时间的访问失效等问题,这个是可以满足的。就好比多个人并发买票,后台网络出现故障,你买的时候系统就崩溃了。

(3)满足AP舍弃C,也就是满足可用性和容错性,舍弃一致性。这也就是意味着你的系统在并发访问的时候可能会出现数据不一致的情况。

实时证明,大多数都是牺牲了一致性。像12306还有淘宝网,就好比是你买火车票,本来你看到的是还有一张票,其实在这个时刻已经被买走了,你填好了信息准备买的时候发现系统提示你没票了。这就是牺牲了一致性。

但是不是说牺牲一致性一定是最好的。就好比mysql中的事务机制,张三给李四转了100块钱,这时候必须保证张三的账户上少了100,李四的账户多了100。因此需要数据的一致性,而且什么时候转钱都可以,也需要可用性。但是可以转钱失败是可以允许的。

 

https://baijiahao.baidu.com/s?id=1650890231453975345&wfr=spider&for=pc

posted @ 2021-04-09 12:08    阅读(737)  评论(0编辑  收藏  举报