什么是高可用“高可用”是指系统不间断地执行其功能的能力,代表着系统的可用性程度Kafka从0.8版本开始就提供了高可用机制,可以保证一个或多个Broker宕机后,其他Broker可以继续提供服务备份机制。Kafka允许在同一个Partition中有多个消息副本。每个Partition副本通常由1个Leader和0个或多个Follower组成。producer直接将消息发送给对应的Partition。Leader和Follower会周期性的向Leader发送同步请求。同一个Partition的Replicas不应该存放在同一个Broker上,因为一旦Broker宕机,该Partition对应的所有Replicas都将无法工作,达不到高可用。因此,Kafka会尽量将所有Partition以及每个Partition的副本均匀分布到整个集群中的各个Broker中。”如下图举例:”ISR机制“ISR副本集合”ISR中的副本都是与Leader同步的副本。相反,不在ISR中的follower副本被认为与Leader不同步。这里保持同步并不是说让数据和Leader完全一致。它只需要在replica.lag.time.max.ms的时间内与Leader保持有效连接,Follower周期性的向Leader发送FetchRequest请求。发送间隔在replica.fetch.wait.max.ms中配置,默认值为500到达点后,Leader立即返回结果,默认值为500privatefinalintminBytes;//Follower所能容忍的最小返回数据大小:当Leader数据足够时立即返回,等待maxWait返回,默认值是1privatefinalMaprequestInfo;//Follower中每个Partititon对应的LEO及获取个数}每个Partition的Leader负责维护ISR列表,将ISR的变化同步到ZooKeeper。从ISR中移除的Follower会继续向Leader发送FetchRequest请求,试图再次跟上LeaderISRISR中的所有副本都跟上了Leader。通常,只有ISR中的成员才能被选为Leader。"Uncleanleaderelection"当Kafka中配置unclean.leader.election.enable为true(默认值为false)且ISR内所有replicasdown时,允许ISR外的replicas被选为leader.这时,部分回答的数据会丢失。开启Uncleanleaderelection可能会导致数据丢失,但是好处是让partitionleader的副本一直存在,这样就不会停止对外提供服务,所以提高了高可用。相反,禁止uncleanleader选举的好处是保持数据一致性,避免消息丢失,但是以牺牲高可用为代价ACK机制领导者回应生产者。"acks=0"producer不需要等待server的任何确认,消息被添加到producer的socketbuffer后就被认为发送了,所以acks=0不能保证server已经收到消息。acks=all”Leader会等待ISR中的所有replicas确认后才响应,所以只要ISR中的任何replicas还活着,已经被应答的消息就不会丢失。acks=all是最可用的选择,但等待关注者回复会引入额外的响应时间领导者需要等待ISR中的所有副本响应。此时的响应时间取决于ISR中最慢的机器。客户端会感知到消息没有发送成功,他会再次尝试发送消息。以前Broker有一个配置项min.insync.replicas(默认值为1),代表正常写入producer数据所需的最少ISR数。当ISR中的副本数小于min.insync.replicas时,Leader停止写入生产者生产的消息,并向生产者抛出NotEnoughReplicas异常,阻塞等待更多的Follower赶上来重新进入ISR由Leader回答。至少有min.insync.replicas个副本,所以可以容忍min.insync.replicas-1个副本同时宕机。《结论:》发送的acks=1和0消息会丢失,生产可以配置不丢失消息acks=all&min.insync.replicas>=2故障恢复机制》Kafka引入了一套Leader自0.8版以来的选举和失败恢复机制。”首先,需要从集群中的所有Broker中选出一个Controller负责每次PartitionElection的Leader和Replica的重新分配,当Leader失效时,Controller会将Leader/Follower的变化通知给需要响应的Broker。Kafka使用ZooKeeper来存储Broker、Topic等状态数据。Kafka集群中的Controller和Broker会在ZooKeeper的指定节点上注册Watcher(事件监听器),这样当特定的事件被触发时,ZooKeeper会将该事件通知给对应的Broker。发生故障后,Controller负责为受影响的Partition选出新的Leader,并通知相关的Brokers。”当某个Broker出现故障,与ZooKeeper断开连接时,ZooKeeper对应的Broker的znode会被自动删除,ZooKeeper会触发Controller注册到该节点的Watcher中;Controller从ZooKeeper的/brokers/ids节点获取宕机Broker上的所有Partition;然后Controller从ZooKeeper的/brokers/topics中获取所有Partition的当前ISR;对于宕机的Broker是Leader的Partition,Controller从ISR中获取存活的Broker作为新的Leader;最后Controller通过LeaderAndIsrRequest请求向Broker发送LeaderAndISRRequest请求。Controller集群中的Controller也会失效,所以Kafka允许所有的Broker在ZooKeeperController节点上注册一个Watcher。当Controller失效时,对应的Controller临时节点会自动删除。这个时候注册在上面的Watcher就会被触发。所有AlllivingBrokers都会竞选成为新的Controller(即创建一个新的Controller节点,ZooKeeper保证只会创建一个成功)。选举的获胜者将是新的控制器