Apache Kafka 最早是由 LinkedIn 开源出来的分布式消息系统,现在是 Apache 旗下的一个子项目,并且已经成为开源领域应用最广泛的消息系统之一。尤其是做日志中间件。
前言
Apache Kafka 最早是由 LinkedIn 开源出来的分布式消息系统,现在是 Apache 旗下的一个子项目,并且已经成为开源领域应用最广泛的消息系统之一。尤其是做日志中间件。
- Kafka是一个分布式系统,易于向外扩展,扩展和容灾。
- 它同时为发布和订阅提供高吞吐量。
- 它支持多订阅者,当失败时能自动平衡消费者。
- 消息的持久化。
- 分区下顺序消息。
背景
我们公司迁移ActiveMQ消息中间件,采用Kafka中间件,因为随着接入的应用越来越多,ActiveMQ所需要的资源越来越多,为了减少资源开支,引入Kafka这种高性能高吞吐高并发的消息组件,减少公司的开支。
知识准备
- broker
就是一个kafka的server服务。
- zookeeper
kafka集群需要保证高可用,消费者需要获取partition leader节点,这些都需要zookeeper来帮助完成。
- Topic
Topic是用于存储消息的逻辑概念,可以看出是一个消息集合。每个Topic可以有多个生产者向其中推送消息,也可以有任意多个消费者消费其中的消息。
- Partition分区
每个Topic都有多个分区,。每个Rartition分区所存储的消息都是不同的,类似数据的水平切分的思想,可以提高并发读写的能力,这就是前面提到了的kafka易于向外扩展。可以通过提供分区数量,可以实现水平扩展。
- Replica副本
每个分区都有多个副本(Replica),这样可以实现消息的冗余备份。同一个分区的不同副本保存相同的数据,副本之间是一主多从,Leader和Follower角色。Leader副本负责读写请求,Folower只与Leader副本消息同步。Leader副本出现故障后,则从Follower副本中选举Leader副本对外提供服务。可以通过提高副本数量,可以提高容灾能力。
- consumer group消费组
所有向kafka去消费消息的服务都是一个消费者,他们可以组成一个或者多个消费组来向kafka集群拉去消息,一个Partition分区的消息只能被一个消费组的某一个消费者消费。
- 顺序保存
Kafka可以保证一个Partition内的消息有序性,并不能保证多个Partition之间数据的有序性。
kafka基础
作为消息中间件kafka,我们生产者直接向kafka的broker节点的Topic发送消息,剩余kafka自行处理。生产者不需要关心后续的处理逻辑,默认由消息中间件去完成事务的最终一致性。实际上kafka集群会有多个节点(Broker),一个topic下会有几个partition分片,这些分片会均匀散布在broker间,然后众多消费者会以消费组的概念向kafka的partition节点拉去信息,一个partition对应一个消费组的唯一的消费者。然后由消费者pull拉去消息后成功消费,然后返回ACK确认。partition就会标识当前消费组已消费的位置。
zookeeper的使用点在哪里
在项目真实的场景中,生产者和消费者并不感受到kafka的zookeeper节点信息,他们是直接连接kafka的broker节点,向其发送topic消息,然后由这个broker将当前topic消息负载均衡到正式partiton leader节点中,完成消息的发送。(有一个弊端就是因为每个生产者产生消费数量不同,无法做到真正的负载均衡,也无法感知kafka节点的新增删除)
另外一只方式就是生产者和消费者也感知zookeeper节点信息,因为当kafka的broker节点启动时会想zookeeper去注册信息,那么生产者和消费者会实时感知到节点信息的变化,可以实现动态的负载均衡。
zookeeper剩下的功能是在kafka集群中去使用,并且在kafka2.8开始尝试去去除zookeeper的作用,一直到kafka3.0完成对zookeeper的迁移工作。那么zookeeper与kafka有什么样的关系。
- 元数据信息
当kafka集群启动时,会想zookeeper去注册自己的元数据信息,比如自己的ip,端口。并且是临时节点,当某个broker节点出现宕机,这个信息就会丢失。zk节点信息如 /brokers/ids/[0...N]
还有topic信息,因为一个topic下会有多个partition信息,这个partition会分布在多个broker节点中,这些topic下的节点信息也要注册上去。zk节点信息如 /brokers/topics/[topic]
- consumer 消费者注册
消费者启动后,kafka会将消费者的信息注册到zookeeper上,节点信息如 /consumers/[group_id]/ids/[consumer_id],同时每个消费者都需要关注所属消费者分组中其他消费者服务器的变化情况,即对/consumers/[group_id]/ids节点注册子节点变化的Watcher监听,一旦发现消费者新增或减少,就触发消费者的负载均衡.
- consumer group 消费组
kafka中会为消费组分配一个group ID,消费组内的消费者公用这个ID,然后kafka也为每个消费者分配一个consumer id,因为一个分区只能针对一个消费组中唯一一个消费者进行消费,所以这些信息统计在zk中,记录分区和consumer之间的关系,zk节点信息 /consumers/[group_id]/owners/[topic]/[broker_id-partition_id]
- offset 消费进度
消费者针对某个分区的消费情况,需要定时将消费进度offset更新到zookeeper上,节点信息如 /consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]。方便当服务重新或者新的消费者代替他时,能够获取当前的消费进度。
- controller leader
当kakfa集群启动时,他们都会想zookeeper中去注册leader信息,当第一个kafka首先注册成功时,这个kafka就会成功为controller leader,其余broker节点就会监听这个节点信息,当出现这个节点消失时,就会重新向zookeeper注册节点,争抢controller leader的角色。而这个controller leader的作用就是负责partition leader的选举,有二种情况,一种是系统启动时的分区leader选举,另一种就是分区leader宕机时,其他节点竞选leader.
上面说到kafka在2.8版本开始逐渐去除zookeeper依赖,最终在kafka3.0版本可以不依赖zookeeper启动kafka.但是依旧兼容了zookeeper的集群方式。