Perspectives on the CAP Theorem

论文链接:https://groups.csail.mit.edu/tds/papers/Gilbert/Brewer2.pdf

论文主要是介绍了一下cap理论以及在分布式系统中的一些权衡的例子

Brewer first presented the CAP Theorem in the context of a web service. A web service is implemented by a set of servers, perhaps distributed over a set of geographically distant data centers. Clients make requests of the service. When a server receives a request from the service, it sends a response. Notice that such a generic notion of a web service can capture a wide variety of applications, such as search engines, e-commerce, on-line music services,or cloud-based data storage.

这段话的意思是:

一般的服务,都是部署在多个机器上,服务器之间需要进行通信,而客户端可以访问其中任一一台服务器,并且这台服务器需要返回结果给客户端

 

CAP原理内容:

Thus, for the purpose of this section, the CAP Theorem can be stated as follows: In a network subject to communication failures, it is impossible for any web service to implement an atomic read/write shared memory that guarantees a response to every request.

也就是cap三点最多只能保证两点

文章里面提供了一个简单的证明,具体还得看他们的另外一篇论文

一致性(C):each server returns the right response to each request

  • write-write导致数据不一致

    • 当在多用户并发的情况下,在同一个服务提供者执行,这可能导致更新丢失(第二次的修改覆盖第一次的修改),这是一种导致数据不一致的情况;另外,如果表数据之间有关联,由于只是修改了某个表的数据,并没有一起修改关联的数据,也可能导致数据不一致;总之,服务内部的操作要保证一致性,这在某个服务提供者内部比较好实现,通过事务即可解决,也可以通过悲观锁或者乐观锁解决丢失更新

    • 多个服务提供者同时提供服务访问,如果用户1和用户2同时访问位于服务器A和服务器B上的同一个服务,这个服务提供电话号码的修改,这将会导致两个对等服务器的数据不一致;如果需要解决这个问题,只能保证对某个服务提供者数据的修改顺序与所有其它同一服务的提供者一样,即A上执行用户1的调用,同时确保B上也执行了用户1的操作,然后在B上执行用户2的调用,同时在A上也执行用户2的调用。这也叫做顺序一致性(sequential consistency),在多主数据库中就是采用这样的方式实现的,比如mariaDB的多主结构

  • read-write不一致

    • logic consistency:在关系型数据库中,如果一个服务需要操作两张表(这两张表的数据有相关性),如果不采用任何手段,将会导致一种数据不一致性出现,当用户1已经更新完第一张表的数据,还没更新完第二张表的数据时,用户2此时来读取第一张表和第二张表的相同数据(与用户1的操作相关),这将导致用户2调用服务时读取到的数据不正确,出现数据不一致,在关系型数据库中用事务解决了此问题,但是在nosql的数据库中,由于不支持事务或者事务的支持粒度比较小(mongodb只支持单文档内部的修改是有事务)

    • replication consistency:在多服务提供者的情况下(对于数据库来说,是多个数据库提供同一份数据),当用户1在服务器A上执行数据修改并完成,用户2会在服务器B上执行数据查询(与用户1操作的数据相关),如果不采取上面的wirte-write一致性中描述的同时写入,则用户2读取不到最新的数据,会出现数据不正确,即不一致;有时候为了提升性能,会采用从A异步的方式复制数据到B,由于是异步,数据有延时,在某个延时窗口下,会存在数据不一致,在mysql的master-slave架构下就存在这样的一致性问题

可用性(A):every request received by  a nonfailing node in the system must result in a response

  • 此概念与日常说的高可用性不一样,即日常把服务不能访问叫做没有高可用性,此处的可用性不包括服务的服务提供者服务器不能连接的情况;强调的是在一定时间内返回执行结果,出现超时被认为不可用

  • 在分布式环境下(由很多服务器组成,提供相同的服务),由于网络的不可靠,更容易导致不可用(某次请求涉及操作3个分片数据,由于某个分片服务器网络不稳定,就会导致超时严重)

  • 两种不可用性举例

    • 在中国,大家都知道由于某些原因,南方和北方的网之间切换会导致网速比较慢,为了让用户访问比较快速,比较大的电商系统都会在南方和北方机房部署系统,这必然导致数据同步问题,如果想避开此问题,那只能让不同机房的数据各自维护,这将会导致南方的用户和北方的用户同时登录系统的时候,看到的商品可能不一样,比如北方的卖完了,而南方的还有,则此时,对北方的用户来说,这个电商系统算是不可用的,因为它虽然能访问到网站系统,但是却不能实现购买,这算是一种不可用情况。

    • 当用户发起访问,请求可以发到服务器,但是由于服务出了故障(死锁导致等待又或者访问太多,导致请求处理不过来)导致服务一直不响应或者服务在期望的时间内没有响应,则这算是服务不可用,我们说的服务不可用绝大多数情况属于这种

分区容忍性(P):communication among the servers is not reliable, and the servers may be partitioned into multiple groups that cannot communicate with each other

 理解:

  • 分区容忍性即提供服务的服务器之间的通信是不可靠的,会导致通信信息的延迟或者丢失,这种情况也叫脑裂(split brain)

  • 在一个服务由多个服务提供者形成集群提供服务的背景下,尤其是跨机房的部署,这种不可靠是一定会出现的,所以才说分布式系统中,是一定会有P,只能在C和A中进行权衡

  • 基于分片思想设计的系统虽然不是对等的(即不同的分片存储数据不一样),但是返回用户正确的结果可能需要多个分片同时参与执行,也涉及到通信只不过是通过路由节点完成(比如mongodb 的mongos),因此分片节点通信中断或者超时也算是出现分区不可靠 

  • 如果能保证节点之间的通信是可靠的或者很少出现不可靠,又或者出现不可靠时能立即解决掉,那是可以同时获取到CA的,满足下面条件:

    • 同一个机房内,由于是局域网,网络相对可靠

    • 针对这种分区可以利用一些手段进行处理,比如实时检测出现分区,然后通过选举等手段重新确定集群,并通过某种手段把分离出去的节点shutdown,让分离出去的节点不能接收请求(这也是解决脑裂的办法,oracle的rac集群就提供了这种解决办法)

    • 通过共享存储的方式解决数据同步,所有数据都写入同一个物理硬盘,则不需要进行数据复制或者数据同步写入

    • 结合上面这三点,是可以同时获取数据一致性和高可用性的,但是付出的代价会比较高 

 

CAP原理总结:

1.所谓的分布式系统下,P这个条件是一定要满足的,是说在多个服务器的集群部署下,服务器之间的通信是不可靠的,尤其是集群服务器分布在多个区域机房

2.在服务器之间会出现分区的这种前提下,权衡一致性和可用性,但不是二选一,而是降低某一方面的要求而增强某一方面的要求