经过某个节点的写操做结果对后面经过其余节点的读操做可见。apache
若是更新数据后,并发访问的状况下可当即感知该更新,称为强一致性网络
若是容许以后部分或所有感知不到该更新,称为弱一致性。并发
若在以后的一段时间(一般该时间不是固定的)后,必定能够感知到该更新,称为最终一致性。app
便是任何一个没有发生故障的节点必须在有限的时间内返回合理的结果(不管是正确的仍是错误的)。异步
部分节点宕机或者是没法与其余节点通讯时,各分区间还能够保持分部式系统的功能,好比上海和北京两个网络分区,当上海分区光纤或其余缘由致使网络不通时,北京上海两个分区之间不可通讯,可是最起码要保证北京的分区中的分布式系统功能可用。分布式
分布式系统中,一致性,可用性,分区容忍性最多只可同时知足两个,可是通常分区容错性都是须要保障的,所以不少时候都是在可用性和一致性之间作权衡。以下一幅图讲解了CP和AP的两种模式的具体表现形式:性能
首先看CP模式,N1和N2之间表明了网络通讯,C表示客户端,X表示新写入的数据,Y表示旧数据,当C向N2发起请求时,因为N2与N1之间网络通讯异常,会致使N2不能同步到N1中的x,在保证一致性的状况下,此时N2不会正常返回处理结果,要么是等待网络链接成功,将N1的Y获取过来,保证数据一致,要么系统出现错误,这样的状况是不能保证高可用的,可是保证了数据一致性。ui
AP模式下,N1和N2之间表明了网络通讯,C表示客户端,X表示新写入的数据,Y表示旧数据,当C向N2发起请求时,因为N2与N1之间网络通讯异常,会致使N2不能同步到N1中的X,可是N2不会等待N1链接成功,或是返回错误信息,而是返回以前老的数据x,这样系统可以正常的运行,可是数据的一致性并无保证,此时选择了系统的高可用方案。spa
RDBMS的读写分离即为典型的Master-slave方案3d
同步复制可保证强一只性,可是会行影响性能(由于Master必需要等待全部的salve都接收到到更新才能返回)
异步复制提升可用性,可是会下降一致性,由于Master只须要本身写操做完成,就当即返回,同时向Slave进行复制,这期间可能会出现某个或多个Slave因为网络或其余缘由没有更新到数据,形成数据不一致性。
主要用于去中心化(P2P)的分布式系统中。DynamoDB与Cassandra即采用此方案,N表明副本数,W表明每次写操做要保证的最少写成功的副本数,R表明每次读至少读取的副本数,当W+R>N时,可保证每次读取的数据至少有一个副本具备最新的更新,多个写操做的顺序难以保证,可能致使多副本间的写操做顺序不一致,Dynamo经过向量时钟保证最终一致性。这里能够经过时间戳或者是自增主键之类的方式来保证过滤出读取的最新的数据。
Google的Chubby,Zookeeper的Zab,RAFT等
Kafka提供了Replica保证了数据一致性
当某个Topic的replication-factor为N切N大于1时,每一个Partition都会有N个副本(Replica),Replica的个数小于等于Broker数,即对每一个Partition而言每一个Broker上只会有一个Replica,所以可用Broker ID表示Replica,全部Partition的全部Replica默认状况会均匀分布到全部Broker上,如图:
图中能够看到,Broker中存的是Topic2的Partition0和Topic2的Partition2的Replica,可是在Broker2中却存了Topic2的Partition1和Topic2的Partition0的Replica,因此默认的Partition都是分布在集群节点上的,replica也同样。这就能够保证到某个节点挂掉以后,其余的节点中保存的replica仍然能够向消费者推送或被拉取消息,保证消息不丢失。
注意:
假如当前咱们搭建了三个Broker的集群,可是我此时指定4个Replica时,会出现org.apache.kafka.common.errors.InvalidReplicationFactorException: Replication factor: 4 larger than available brokers: 3异常,如图:
以下图:
当producer想leader节点发送消息时,其他follower节点(我的理解跟slave相似)将会如其余mq的consumer同样去从主节点的topic中将数据拉取或被推送到自身节点中。这样当leader节点挂掉以后,consumer访问集群时,仍然能够从其余的follower中获取到最新数据,防止了数据丢失。
ISR: Leader会维护一个与其基本保持同步的Replica列表,该列表称为ISR(in-sync Replica),若是一个Follower比Leader落后太多,或者超过必定时间未发起数据复制请求,则Leader将其从ISR中移除,当ISR中全部Replica都向Leader发送ACK时,Leader即Commit(告诉Producer消息发送成功)。
Commit策略
1. 在Server中配置
replica.lag.time.max.ms:默认100000,最大未发起数据复制请求的时间。
replica.lag.max.messages:最大落后消息数,根据自身须要配置
2. Topic配置
min.insync.replicas=1: ISR列表最小个数,默认1,只有当request.required.acks为-1时才生效,若是ISR中的副本数少于min.insync.replicas配置的数量时,客户端会返回异常:org.apache.kafka.common.errors.NotEnoughReplicasExceptoin: Messages are rejected since there are fewer in-sync replicas than required。
3. Produce配置
request.required.acks=1,默认为1,roducer发送数据到leader,leader写本地日志成功,返回客户端成功;此时ISR中的副本尚未来得及拉取该消息,leader就宕机了,那么这次发送的消息就会丢失,当为-1时,当producer设置request.required.acks为-1时,min.insync.replicas指定replicas的最小数目(必须确认每个repica的写数据都是成功的),若是这个数目没有达到,producer会产生异常。
如图:
1. 能够看到SR={A,B,C},Leader(A)节点中存在m1,m2,m3三条消息,F(B)存在m1,m2两条消息,f(c)只存在m1一消息,因此这里只会提交m1这条消息,由于m2这条消息尚未在ISR中完成复制。它只会提交三个ISR中都存在的消息。
2. 当L(A)在将消息m2复制到B,C以后挂掉,此时ISR中只有{B,C},B被选举成为新的主节点,当m2,m1都存在于B,C节点中时,B将会提交m1,m2两条消息,不会提交m3消息。
3. 此时消息将都会发送到B节点上,C节点同步了B节点中的新发的消息m4,m5以后,将会提交m4,m5.
5.此时A节点链接集群成功或重启,可使用了,它会从B节点中同步从m1,到m5的消息,直到它的消息与B和C中的一致为止,此时的Replica将会变成ISR={A,B,C},完成了Replica的恢复。这里咱们发现m3并无存在了,这里并非丢失了,只是当没有主节点提交m3这条消息时,它将会自动反馈到Producer,Producer会重试,或作其余处理,当重试成功后可能m3消息将会append到m5的后面,因此consumer消费消息时,咱们保证的顺序性不是producer发送消息的顺序,而是commit时的顺序。
当ISR中的Replica所有宕机时,能够经过以下方式处理:
1. 等待ISR中任一Replica恢复,并选它为Leader。
缺点:等待时间较长,下降可用性(由于不能使用全部集群节点),所以或ISR中的全部Replica都没法恢复或者数据丢失,则该Partition将永不可用。
2. 选择第一个恢复的Replica为新的Leader,不管它是否在ISR中。
缺点:并未包含全部已被以前Leader Commit过的消息(由于它不在以前的ISR中),所以会形成数据丢失,可是它提升了可用节点的范围,可用性比较高。