Kafka是分布式发布-订阅消息系统, Kafka是一个分布式的,可划分的,冗余备份的持久性的日志服务。它主要用于处理活跃的流式数据。
Kafka的基本架构如下图:
Kafka的架构比较简单,producer、broker和consumer均可以有多个,通常需要zookeeper来管理broker和consumer。
producer和consumer实现kafka注册的接口,消息从producer发送给broker, broker承担类似于消息仓库的功能,仅仅对消息进行存储和对注册到系统的consumer进行通知。consumer则根据监听和配置主动从broker拉取消息。
topic、partition、segment 和broker 的关系探究
1、topic是一个逻辑上的概念,表明消息的类型,partition则是物理上的概念,一个topic分成多个partition。producer发送消息到broker时,需要指定topic和partition(可不指定partition,若不指定则随机分布)。
2、partition在broker上对应一个文件夹,partition内又包含多个segment,一个segment对应一个文件,一个partition具备多个副本,分布在多个broker上,通过选举,其中一个partition作为leader,其余的作为follower。由leader执行读写操作,当leader宕机时,再在follower中选举一个作为新的leader。
3、segment 文件存储了分区内的消息,每条消息的id由其逻辑位置决定,即通过消息ID即可定位到消息的位置避免了额外的消息ID到位置的映射。当消息写入segment所在的分区时,消息将被append到最后一个segment的尾部。当segment写满了或者达到了配置的时间后,将flush到磁盘,此后consumer将可以开始消费消息。segment大小达到一定程度后,broker将创建新的segment。
4、每个partition在内存中对应一个index,存储了其下每个segment中第一条消息的偏移(offset),partition和segment的存储结构如下图:
了解kafka过程中疑惑的几个问题:
1、topic和broker的关系是什么?
答:topic和broker没有明确的对应关系。topic只是一个逻辑上的概念,对消息进行分类。topic在物理上分成多个partition,单独以 leader parition论,partition均匀的分布在broker上,这样做的好处是1、可以负载均衡,2、可以并行发送消息。
此外,每个partition leader在其他的若干个broker上会存有follower,用以保证分布式系统的可靠性。
2、topic 为什么要分区?
答:为了性能考虑。如果topic没有分区,那么topic的消息只能够在一个broker上写入,那么此broker的磁盘写入速度将会成为瓶颈,无法做到水平扩展。分区之后,新消息添加进topic时,消息分别均匀的追加进指定partition尾部。并行插入消息,提升效率。同样,consumer也可以并行从多个broker上的不同partition上读取数据。
3、为什么分区内还需要设置多个segment?
答:如果不引入segment,partition直接对应一个文件,那么这个文件会一直增大,同样,当需要清除历史消息的时候,需要擦除文件的前半部分,不符合kafka对文件顺序写的优化方案。按时间分隔多个segment的话,当需要清除过期消息时,只需要将旧的segment整个删除即可。
4、采用consumer group的意义何在?
答:consumer group 旨在同时拥有queue 和 publish-subscribe二者的优势。 传统的消息系统有队列和发布-订阅两种模型,队列模型中,一组consumer在队列出口消费数据,每条消息只被其中一个consumer消费,这种方式允许你将对数据的处理过程分配给一组consumer处理,从而扩展处理速度。在发布-订阅模型中,每条消息将被广播给每个consumer,消息被每个订阅者接收并消费,这意味着,发布-订阅模型支持多用户消费。那么consumer group模型是如何同时具备两者的优势呢? 在kafka 中,一个topic的消息将被广播给所有订阅该主题的consumer group(kafka的消息订阅是以consumer group为单位的),在consumer group 内部,消息将以队列的模式被group 内的多个consumer分别消费。也就是说,以group的形式实现多用户订阅,在group内部,允许规模扩充consumer,分别消费消息提升处理效率。
4.1 PS : 第4小点所说的,在group内部,消息以队列的模式被group内的多个consumer分别消费,其中,是以partition为最小的消费单位,也就是说,同一时间,一个partition只允许被一个consumer消费。这样做的目的是为了保证消息被消费时的顺序性,同时、这也意味着group内的consumer成员数量应当小于等于 topic 的 partition数量,否则必定造成总有consumer处于空闲状态无法处理消息。