高可用
Kafka高可用:多副本机制
高可用(HA)对于企业的核心系统来说是至关重要的。因为随着业务的发展,集群规模会不断增大,而大规模集群中总会出现故障,硬件、网络都是不稳定的。当系统中某些节点各种原因无法正常使用时,整个系统可以容忍这个故障,继续正常对外提供服务,这就是所谓的高可用性。对于有状态服务来说,容忍局部故障本质上就是容忍丢数据(不一定是永久,但是至少一段时间内读不到数据)。
系统要容忍丢数据,最朴素也是唯一的办法就是做备份,让同一份数据复制到多台机器,所谓的冗余,或者说多副本。为此,kafka 引入 leader-follower 的概念。topic 的每个 partition 都有一个 leader,所有对这个 partition 的读写都在该 partition leader 所在的broker 上进行。partition 的数据会被复制到其它 broker 上的 follower

producer 在生产消息时,会直接把消息发送到 partition leader 上,leader 把消息写入自己的 log 中,然后等待 follower 来拉取数据进行同步。
注意 kafka 中数据复制是依赖 follower 主动从 leader 拉数据,非 leader 主动推,不采用推模式。
producer 进行 ack 的时机非常关键,这直接关系到 kafka 集群的可用性和可靠性
如果数据到达
leader并成功写入leader的log就进行ack优点:不用等数据同步完成,速度快,吞吐率高,可用性高;
缺点:如果
follower数据同步未完成时leader挂了,就会造成数据丢失,可靠性低。如果等
follower都同步完数据时进行ack优点:当
leader挂了之后follower中也有完备的数据,可靠性高;缺点:等所有
follower同步完成很慢,性能差,容易造成生产方超时,可用性低。
而具体什么时候进行 ack ,对于 kafka 来说是可以根据实际应用场景配置的。
kafka 控制器 controller
在 kafka 集群中的 broker,其中有一个 broker 会被选举为控制器 controller,它负责管理整个集群中所有分区和副本的状态,集群中只能有一个控制器
某个分区的
leader副本出现故障时,由控制器负责为该分区选举新的leader副本检测到某个分区的
ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息当为某个
topic增加分区数量时,由控制器负责分区的重新分配
kafka 控制器的选举
kafka 中的控制器选举工作依赖于 zookeeper,成功竞选成为控制器的 broker 会在 zookeeper 中创建 /controller 临时节点。
每个
broker启动的时候会去尝试读取/controller节点的brokerid的值。并对该节点注册watch函数,在控制器挂掉后触发控制器的选举如果读取到的
brokerid的值不为 -1,表示已经有其他broker节点成功竞选为控制器,当前broker就会放弃竞选如果
zk中不存在/controller节点,或者这个节点的数据异常,那么就会尝试去创建/controller节点,创建成功的那个broker就会成为控制器
每个
broker都会在内存中保存当前控制器的brokerid值,这个值可以标识为activeControllerIdZookeeper中还有一个与控制器有关的/controller_epoch节点,用于记录控制器发生变更的纪元,及轮数
leader选举
controller会在zk注册对broker的watch函数,一旦有broker宕机导致其在zk对应的znode过期被删除,zk会触发watch函数,通知controllercontroller会读取本地上该broker的状态,遍历该broker上的所有partition,读取每个partition的ISR从
ISR中随机选一个replica作为新leader。如果没有ISR,则从幸存的replica中随机选一个。如果没有幸存的replica,将leader设为-1将新的
leader、ISR和纪元记录到本地
kafka 2.8
kafka 2.8 抛弃了 zk,改为使用 raft 协议自行实现,称为 kraft,主要基于以下考虑:
使用
zk相当于引入了新的外部依赖。导致kafka可用性不仅取决于自身,还受到外部组件制约。zk的设计是CP模型,为了保证一致性,在可用性方面做出了牺牲。选主期间,集群可能不可用(比如正好GC)zk的watch机制也有些问题,watch只会通知节点有信息发生了变化,具体是什么变化需要节点再次查询zk才知道,有时差
raft不是外部组件的形式,而是协议,作为一个协议嵌入应用中,与应用本身是一体的目前还处于测试状态,不建议用于生产环境,因为无法平滑从老版本进行升级
leader选举
kafka 2.8 下的 leader 选举不再使用 zk,而是自行选举。投票时,按以下优先级:
优先投给
epoch高的优先投给有最新数据的 ("longest")
存在
epoch高、但数据少的点被选为leader,这种情况下follower上多出的数据会被清除
参考
Last updated