CAP理论

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理论证明作者Seth Gilbert和Nancy A.Lynch的文章Perspectives on the CAP Theorem

中文意思:

      一个服务部署在很多服务器上,也就是说服务提供者有多个,这些服务提供者之间形成一个集群,彼此有通信,并且这些服务提供者可能分布在不同的机房。客户端需要调用这个服务(可以认为是通过前端负载均衡器调用也可以理解为不同的客户端直接连接其中的某个服务器),当某个服务器接收到客户端的一次服务调用时,此服务器需要返回一个服务调用的结果。

      这个服务是一个通用应用的抽象,它可以是一个搜索引擎,电商系统,在线音乐服务,也可以是云数据存储


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

3.理论上是可以构建一个强一致性及高可用性的系统的,但是这将会付出很多的代价来解决分区问题,如上面分区容忍性中讲的一样

4.对于单个节点的关系型数据库来说,满足CA的要求,但是更多的是满足C,因为如果并发一多,单个节点的负载就会更大,响应就会慢,可用性就会降低;

5.对于Key-value的nosql数据库来说,满足AP,是因为通过一定算法(比如一致哈希)把数据分散到不同的分片节点,对于某个分片节点会采用异步复制的方式保证同一个分片的数据可用性。而所有的操作,都只能在同一个key的单个操作内保证事务,所以在一致性方面会导致复制一致性(replication consistency)  顺序一致性(sequential consistency) 逻辑一致性(logic consistency)等问题


结合mongodb分析CAP理论:

1.当mongodb只部署单节点时,与mysql等关系型数据库相比,mongodb由于只保证单文档的事务,所以也是可能存在数据不一致性的(当同时更新相关的多条记录时);同时,由于对事务的弱支持,提高了数据更新的效率,也就减少了响应时间,从而减少超时导致的不可用,也就提高了可用性

2.当mongodb部署为副本集时,满足了CAP里面的服务由多个服务器提供场景;

  • mongodb提供了写属性配置,可以让写操作同步写入所有的节点,这是保证一致性的手段,但是这时候如果某个节点不能通信(出现分区),则副本集会重新进行选举,在这期间(1分钟以内,某次测试是8s),客户端可以连接上副本集但是不能进行操作,也就是不具有可用性

  • 当写操作只在主节点执行,通过异步复制到从节点(secondary);此时,读操作通过设置属性在从节点读取数据,这会减轻主节点的压力,如果此时从节点从集群分裂出去,mongodb的读属性可以配置成转移到主节点读取数据,虽然实际测试中有100ms的时间操作失败,但是比上面的8s,已经有了很大的提升,即此时是损失一定的数据一致性特性而增强了可用性

  • 在进行分片部署的情况下,虽然某次服务的数据可能涉及到多个分片节点,但是分片之间是不会进行通信的,所以不存在复制一致性的问题,但是存在write-write以及logic consistency问题,因为如果操作涉及到多个文档的更新,而mongodb并没有提供分布式事务解决此问题,甚至连同集合的多文档修改都没有事务保证;由于数据被分到多个分片,提高了数据操作性能,也就减少了系统响应时间,降低了数据可用性的概率,也就是增强了可用性

参考资料:

Nosql Distilled

Perspectives on the CAP Theorem


你可能感兴趣的:(CAP)