kafka详细整理

博客介绍了Kafka文件的存储机制,重点阐述了Kafka位移管理。包括自动和手动提交位移的方式,Kafka默认自动提交,也可手动控制。还提到老版本位移提交到Zookeeper,因不适合大量读写,Kafka增加_consumeroffsets topic保存offset信息。
  1. Kafka文件的存储机制
同一个topic下有多个不同的partition,每个partition为一个目录,partition命名的规则是topic的名称加上一个序号,序号从0开始。

每一个partition目录下的文件被平均切割成大小相等(默认一个文件是500兆,可以手动去设置)的数据文件,
每一个数据文件都被称为一个段(segment file),但每个段消息数量不一定相等,这种特性能够使得老的segment可以被快速清除。
默认保留7天的数据。

 

每个partition下都会有这些每500兆一个每500兆一个(当然在上面的测试中我们将它设置为了1G一个)的segment段。

 

另外每个partition只需要支持顺序读写就可以了,partition中的每一个segment端的生命周期是由我们在配置文件中指定的一个参数觉得的。
比如它在默认情况下,每满500兆就会创建新的segment段(segment file),每满7天就会清理之前的数据。
它的一个特点就是支持顺序写。如下图所示:

 

首先00000000000000000000.log文件是最早产生的文件,该文件达到1G(因为我们在配置文件里面指定的1G大小,默认情况下是500兆)
之后又产生了新的0000000000000672348.log文件,新的数据会往这个新的文件里面写,这个文件达到1G之后,数据就会再往下一个文件里面写,
也就是说它只会往文件的末尾追加数据,这就是顺序写的过程,生产者只会对每一个partition做数据的追加(写)的操作。

复制代码

问题:如何保证消息消费的有序性呢?比如说生产者生产了0到100个商品,那么消费者在消费的时候安装0到100这个从小到大的顺序消费,
那么kafka如何保证这种有序性呢?难度就在于,生产者生产出0到100这100条数据之后,通过一定的分组策略存储到broker的partition中的时候,
比如0到10这10条消息被存到了这个partition中,10到20这10条消息被存到了那个partition中,这样的话,消息在分组存到partition中的时候就已经被分组策略搞得无序了。
那么能否做到消费者在消费消息的时候全局有序呢?遇到这个问题,我们可以回答,在大多数情况下是做不到全局有序的。但在某些情况下是可以做到的。

比如我的partition只有一个,这种情况下是可以全局有序的。那么可能有人又要问了,只有一个partition的话,哪里来的分布式呢?哪里来的负载均衡呢?
所以说,全局有序是一个伪命题!全局有序根本没有办法在kafka要实现的大数据的场景来做到。但是我们只能保证当前这个partition内部消息消费的有序性。

结论:一个partition中的数据是有序的吗?回答:间隔有序,不连续。

针对一个topic里面的数据,只能做到partition内部有序,不能做到全局有序。特别是加入消费者的场景后,如何保证消费者的消费的消息的全局有序性,
这是一个伪命题,只有在一种情况下才能保证消费的消息的全局有序性,那就是只有一个partition!。

复制代码

Segment file是什么?

生产者生产的消息按照一定的分组策略被发送到broker中partition中的时候,这些消息如果在内存中放不下了,就会放在文件中,
partition在磁盘上就是一个目录,该目录名是topic的名称加上一个序号,在这个partition目录下,有两类文件,一类是以log为后缀的文件,
一类是以index为后缀的文件,每一个log文件和一个index文件相对应,这一对文件就是一个segment file,也就是一个段。
其中的log文件就是数据文件,里面存放的就是消息,而index文件是索引文件,索引文件记录了元数据信息。
说到segment file的索引文件和数据文件的一一对应,我们应该能想到storm中的Ack File机制,在spout发出去的时候要发一个Ack Tuple,
在下游的bolt处理完之后,它也要发一个Ack Tuple,这两个Ack Tuple里面包含了同样一份数据,这个数据叫做MessageId,它是一个对象,
这个对象里面包含两个比较重要的字段,一个是RootId,另一个是TupleId(也叫锚点Id),这个锚点Id会在我们发送数据的时候进行异或一下,
异或的结果才会发送给Ack那个Bolt。

复制代码

Segment文件命名的规则:partition全局的第一个segment从0(20个0)开始,后续的每一个segment文件名是上一个segment文件中最后一条消息的offset值。

那么这样命令有什么好处呢?假如我们有一个消费者已经消费到了368776(offset值为368776),那么现在我们要继续消费的话,怎么做呢?
看上图,分2个步骤,第1步是从所有文件log文件的的文件名中找到对应的log文件,第368776条数据位于上图中的“00000000000000368769.log”这个文件中,
这一步涉及到一个常用的算法叫做“二分查找法”(假如我现在给你一个offset值让你去找,你首先是将所有的log的文件名进行排序,然后通过二分查找法进行查找,
很快就能定位到某一个文件,紧接着拿着这个offset值到其索引文件中找这条数据究竟存在哪里);第2步是到index文件中去找第368776条数据所在的位置。

索引文件(index文件)中存储这大量的元数据,而数据文件(log文件)中存储这大量的消息。

索引文件(index文件)中的元数据指向对应的数据文件(log文件)中消息的物理偏移地址。

复制代码

复制代码

上图的左半部分是索引文件,里面存储的是一对一对的key-value,其中key是消息在数据文件(对应的log文件)中的编号,比如“1,3,6,8……”,
分别表示在log文件中的第1条消息、第3条消息、第6条消息、第8条消息……,那么为什么在index文件中这些编号不是连续的呢?
这是因为index文件中并没有为数据文件中的每条消息都建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。
这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。
但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。

其中以索引文件中元数据3,497为例,其中3代表在右边log数据文件中从上到下第3个消息(在全局partiton表示第368772个消息),
其中497表示该消息的物理偏移地址(位置)为497。

2. kafka位移管理

   2.1自动VS手动

kafka默认是定期帮你自动提交位移的(enable.auto.commit=true),你当然可以选择手动提交位移实现自己控制。另外kafka会定期把group消费情况保存起来,做成一个offset map,如下图所示:

上图中表明了test-group这个组当前的消费情况。

2.2 位移提交

老版本的位移是提交到zookeeper中的,目录结构是:/consumers/<group.id>/offsets/<topic>/<partitionId>,但是zookeeper其实并不适合进行大批量的读写操作,尤其是写操作。因此kafka提供了另一种解决方案:增加_consumeroffsets topic,将offset信息写入这个topic,摆脱对zookeeper的依赖(指保存offset这件事情)。_consumer_offsets中的消息保存了每个consumer group某一时刻提交的offset信息。依然以上图中的consumer group为例,格式大概如下:

 

<think>好的,用户需要了解Kafka详细技术架构和工作原理。根据用户提供的引用内容,我需要整理Kafka的核心组件、工作原理以及相关机制。首先,Kafka的主要组件包括Producer、Broker、Consumer、Topic和Partition。每个部分的作用需要解释清楚,比如Producer负责发布消息,Broker作为消息代理存储消息等。接下来是工作原理,需要描述消息如何从Producer到Broker,再被Consumer订阅消费的过程。要提到发布-订阅模式,以及分区和副本机制的重要性,比如如何实现高吞吐和高可用。还要涉及Offset管理,说明消费者如何追踪消息位置。此外,用户可能关心Kafka的高性能设计,比如顺序读写、零拷贝技术,这些内容需要包含进去。用户提供的引用中提到了分布式架构、可靠性机制,以及应用场景如实时流处理,这些也要整合到回答中。最后,根据引用中的信息,确保使用正确的术语,比如Partition的分区策略、副本的Leader-Follower机制。需要检查是否有遗漏的重要点,比如ZooKeeper的作用,但在引用中没有提到,可能用户提供的资料有限,所以暂时不深入。同时,生成的相关问题要围绕架构、性能优化、应用场景等,帮助用户进一步学习。确保回答结构清晰,分点说明,符合用户要求的详细技术介绍。</think>### Kafka架构与工作原理详解 #### 一、核心架构组件 1. **Producer(生产者)** 负责将消息发布到指定主题(Topic),支持异步/同步发送模式,可自定义分区策略(如轮询、哈希等)[^2]。 2. **Broker(消息代理)** 组成Kafka集群的节点,负责消息存储、转发和管理。每个Broker可处理多个主题分区(Partition),通过副本机制实现容灾[^1][^2]。 3. **Consumer(消费者)** 以消费者组(Consumer Group)形式订阅主题,每个分区仅能被组内一个消费者消费。Offset记录消费进度,支持手动/自动提交[^5]。 4. **Topic(主题)** 逻辑上的消息类别,分为多个分区(Partition)以实现并行处理。例如,主题`logs`可划分为10个分区,提升吞吐量[^3]。 5. **Partition(分区)** 每个分区是**有序、不可变**的消息队列,数据以追加方式写入。分区在物理上对应多个副本(Replica),包含一个Leader和多个Follower,Leader处理读写请求,Follower同步数据[^5]。 #### 二、工作原理 1. **消息发布流程** - Producer根据分区策略(如`key.hashCode() % partitions`)将消息发送到特定分区。 - Broker将消息持久化到磁盘(顺序写入,性能高),同时复制到其他副本[^3][^5]。 2. **消息消费流程** - Consumer通过订阅Topic加入消费者组,由Broker协调分配分区。 - 消费者从分区Leader拉取消息,并更新Offset(存储于内部主题`__consumer_offsets`)[^2][^4]。 3. **高可用机制** - **副本同步**:Follower定期从Leader拉取数据,若Leader故障,Controller(通过ZooKeeper选举)重新选举新Leader[^2][^5]。 - **ISR集合**:仅处于In-Sync状态的副本可参与Leader选举,确保数据一致性。 #### 三、关键技术特性 1. **高性能设计** - 顺序磁盘I/O:通过追加写入和分段(Segment)存储优化磁盘访问[^3]。 - 零拷贝(Zero-Copy):使用`sendfile`系统调用减少内核态与用户态数据拷贝[^5]。 2. **水平扩展** 通过增加Broker和分区数量,可线性提升吞吐量。例如,将主题分区从3扩展到6,并行处理能力翻倍。 3. **持久化与保留策略** 消息默认保留7天(可配置),支持基于时间或大小的清理策略。例如: ```properties log.retention.hours=168 # 7天 log.retention.bytes=1073741824 # 1GB ``` #### 四、典型应用场景 1. **日志聚合**:集中收集分布式系统日志(如ELK结合Kafka)[^2]。 2. **实时流处理**:作为数据管道连接Spark/Flink进行实时分析[^1]。 3. **事件溯源**:存储应用状态变化事件,支持回放与审计。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值