天天看点

最终一致性Quorum及其在Zookeeper和Kafka中的演变 QuorumZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeper Kafka 0.10Kafka 0.10Kafka 0.10Kafka 0.10KafkaKafka 

Quorum

['kwɔrəm]

•        写入数据的时候,要求W个节点确认收到

•        读取数据的时候,读取R个节点,获取最新数据版本

•        W + R > N(总节点数)则称为Quorum

最终一致性Quorum及其在Zookeeper和Kafka中的演变 QuorumZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeper Kafka 0.10Kafka 0.10Kafka 0.10Kafka 0.10KafkaKafka 

Zookeeper

ZAB: Zookeeper Atomic Broadcast

•        读的时候,读任意1个节点

•        写的时候,leader处理,过半数节点确认;类似两阶段提交

–     收到客户端写请求,如果自己是follower,转发给leader

–     Leader收到写请求,转换为事务,广播该事务

–     各节点收到事务广播,写入事务日志并返回确认

–     Leader收到多数节点确认,广播COMMIT消息;未收到多数节点确认,补发事务Proposal

–    各节点收到commit消息,该事物更新到内存的DataTree数据结构中

Zookeeper

ZAB: Zookeeper Atomic Broadcast

最终一致性Quorum及其在Zookeeper和Kafka中的演变 QuorumZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeperZookeeper Kafka 0.10Kafka 0.10Kafka 0.10Kafka 0.10KafkaKafka 

Zookeeper

ZAB: Zookeeper Atomic Broadcast

•        为什么称为原子广播协议?

–     Proposal具有幂等性(即原子性),重复发送无影响

–     Proposal中的事务包含的是znode的最终状态,而不是操作命令

–     每个Proposal有zxid,顺序递增由leader产生,保证follower能按leader的处理顺序进行处理

–     每次读或写znode的数据,只能全部读取或全部覆盖

•        Leader发送proposal、commit的时候也会发送给自己

•        Leader自己commit完成后向客户端返回处理结果

Zookeeper

故障处理

•        已经向client返回处理结果,此时leader故障

–     Follower与leader连接断开,达到阈值发起选举

–     过半数节点正常,选举方能成功

–     选举的节点是zxid最大的,myid文件内容最大的

–     新leader根据snapshot和事务日志恢复数据,同步至follower

•        未向client返回处理结果

–     client应查询一下leader,判断是否成功;也可查询任意follower,可能不一致,但最终一致

–     如果leader故障,等待新leader产生

Zookeeper

故障处理

•        选举出新leader,老leader恢复

–     老leader发起选举,发现有其他节点zxid比自己大,且已经有leader,于是成为follower,加入现集群

–     老leader发送最大zxid给新leader,新leader据此要求其丢弃部分数据(可能有没发送给follower的proposal),并重新发送故障期间的新事物

Zookeeper

FastLeaderElection选举(选举算法可在zoo.cfg中配置)

•        逻辑时钟clock表示第几轮选举,重启时为0,选举时加1

•        启动时处于looking状态

–     先选自己,选票为“clock(1)、 looking、zxid、myid”

–     广播选票,收到其他节点选票

–     如果其他节点选票的clock大,更新自己的clock;其他节点zxid大,或zxid相等但myid大,则更新自己选票的相应值为该节点值,表示选举该节点;

–     重新发出选票

•        收到选票时,判断当前的选票是否过半数选举同一节点;满足条件时结束选举

Zookeeper

zxid说明:为什么zxid不会重复,如何保证顺序递增

•        ZooKeeper Transaction Id

•        zxid为8字节64位

–     高32位表示逻辑时钟,初始为0,称为epoch

–     低32位表示事务顺序号,初始为0,每次事务加1

•        选举新leader后

–     新leader的zxid一定是最大的

–     新leader不会继续原来的zxid

–    高32位加1,低32位置0,将新的epoch通知follower

Zookeeper

hierarchical quorums跨数据中心

•        每个group有3个机器

–     group.1=1:2:3    group.2=4:5:6    group.3=7:8:9

•        每个机器默认权重为1,可修改

–     weight.1=1

•        过半数的group正常即可选举或ZAB时commit;

•        group中,正常的server加权求和,结果大于该group所有server加权求和,认定该group正常

•        如果3个group分别部署在3个数据中心,可容忍1个DC完全挂掉

Zookeeper

总结

•        可用性:3节点容忍1故障;5节点容忍2故障

•        一致性:写多数节点,读1节点,leader、follower可能短暂不一致,但最终一致

•        网络分区容忍性:网络分区不会导致数据出错,但多数节点仍联通时才能服务(否则也可处理只读操作)

•        适用场景:

–     读写比大于2,读多写少(因为写操作全部在leader上)

–     不适用大数据存储(znode只能全部读取或覆盖,znode数据必须小于1M),需要正常副本过半数

Quorum及其在Zookeeper中的演变 到此结束~~

后面是在Kafka中的应用

Kafka 0.10

来自Microsoft的PacificA协议

•        场景:高吞吐量,高可用性,高性能,大数据

•        W + R > N性能不高,修改后的协议读写都在leader,多个分区leader共同承担读写请求:

–     R = 1,W = 1(可丢数据)

–     R = 1,W = N1 < N(N1为正常的副本)(不丢数据,除非所有副本都故障)

–     正常(in-sync)的条件:和zookeeper的会话没有断开(通过定时的心跳消息),如果是follower,则不能落后leader太多。落后多久算太久是通过参数“replica.lag.time.max.ms”控制的。leader会根据这俩条件跟踪in-sync的follower

Kafka 0.10

Kafka概述

•        每个topic分为多个分区

•        每个分区可有多个副本

•        同一分区副本通常不在同一broker上;leader故障,in-sync的副本成为leader;无in-sync的副本,选举最新数据的副本

•        Broker:一个java进程,Kafka在服务器的唯一进程

–     replica.lag.time.max.ms超过此时间未与leader同步为不正常副本

–     min.insync.replicas最少需要多少个正常的副本才接受写请求

–     log.segment.bytes一个单独的文件存储多少字节的消息

–    message.max.bytes每个消息最大多少字节

Kafka 0.10

Kafka概述

•        消息在生产者发出的时候,broker存储、消费者消费的时候,都是同样的二进制格式,无需任何转换,性能更高

•        Producer生产者配置

–     acks:0-放入本地OS缓冲区后返回;1-leader处理后返回客户端;all-所有in-sync的副本都确认收到消息后才返回客户端

–     compression消息压缩格式

–     可使用sync或async的producer

–     batch.size达到多少字节才批量发送消息,async时有效

•        不建议使用fsync,网络完全可以比普通磁盘快

Kafka 0.10

Kafka概述

•        消费者采用pull模式,能按自己的能力尽最大努力处理消息

•        每次取一批消息,然后再处理;每个分区只能被一个消费者消费

•        取消息时,按offset取,服务端无需维护客户端状态,且可回溯

•        Consumer消费者配置

–    fetch.min.size:至少取多少字节消息,如果消息没有这么多,服务器阻塞等待

–    fetch.mat.wait.ms:消息不足fetch.min.size,服务器最多阻塞多久

–    max.partition.fetch.bytes:每个partition服务器最多返回多少字节数据,但如果第一条消息大于此值仍会返回

–    fetch.max.bytes:服务器总的最多返回多少字节数据,但如果第一条消息大小大于此值仍会返回

Kafka

总结

•        可用性:只要有1节点正常即可

•        一致性:

–     读写都在leader,完全一致;其他副本为特殊的消费者

–     发送消息时使用acks=all则leader故障后也一致

–     所有正常副本都收到特定消息后才可能被消费者消费到

•        网络分区容忍性:

–     网络分区不会导致partition出现多个leader的情况,因为使用了Zookeeper做协调

–     网络分区可能导致部分partition可用、部分不可用

Kafka

总结

•        高可用:只要有1节点正常即可

•        高吞吐量:

–     生产者可批量发送消息;消费者批量取消息后消费

•        高性能:

–     消息格式在producer、consumer、broker保持一致

–     sendfile减少文件内容copy次数,上下文切换次数

–     broker顺序写,顺序读,segment设计避免扫描大文件

•        大数据:

–     依靠分区将数据分布到不同节点处理

–     只需1节点即可使用避免Quorum重复存储大量数据

2017年3月29日