kafka基础知识3:机制,特性,场景

参考:

https://blog.csdn.net/weixin_44318830/article/details/105072995(CSDN:超全kafka知识点总结)

https://www.jianshu.com/p/b5df30e750df(简书:kafka知识点总结)

https://www.cnblogs.com/sujing/p/10960832.html(博客园:kafka的工作原理)

https://www.cnblogs.com/cyfonly/p/5954614.html(博客园:kafka学习笔记)

1,基础知识

什么是Kafka

kafka是一个分布式,分区的,多副本的,多订阅者的消息发布订阅系统

Kafka的使用场景

应有解耦、异步处理、限流削峰、消息驱动的系统。

副本数与broker之间的关系

数据副本(包含本身)数一般情况下小于等于broker的个数

分区和消费组内的消费者之间的关系有哪些情况?

  Partition = 消费任务的并发度=刚刚好,每个任务读取一个partition数据

  Partition > 消费任务的并发度=有部分消费任务读取多个分区的数据

  Partition < 消费任务的并发度=有部分消费任务空闲(可以创建多于分区的消费者数量)

Kafka中的数据删除机制是什么?

        1、时间:默认存储168小时(一周)

        2、数据的大小:默认 -1 (不删除),可以自行设置。

分区数、消费者与读取效率之间的关系

分区数越多,同一时间可以有越多的消费者来进行消费,消费数据的速度就会越快,提高消费的性能

2,重要知识

Kafka如何保证数据不丢失

从大体上来看的话,Kafka中主要的角色有数据生产者(Producer),Kafka集群中负责存储数据的Broker,数据消费者(Consumer),

因此这个问题需要从三个角度来进行回答!

1、生产者如何保证数据不丢失? 通过ack 机制确保数据不丢失。

2、kafka集群如何保证数据不丢失? 通过数据副本保证数据不丢失。

3、消费者如何保证数据不丢失?通过维护数据的offset 保证数据不丢失。

Kafka 是如何实现高吞吐率的?

#写操作
1. 写入内核区内存: 直接写入os cache里,也就是写入内存中,接下来由操作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中,相当于写内存而不是写磁盘;
2. 顺序写:仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。

#分发操作
3. 零拷贝: 直接让操作系统的cache中的数据发送到网卡后传输给下游的消费者,中间跳过了两次拷贝数据的步骤,Socket缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到Socket缓存。
4. 批量压缩:Producer端可以通过GZIP或Snappy格式对消息集合进行压缩。Producer端进行压缩之后,在 Consumer 端需进行解压。压缩的好处就是减少传输的数据量,减轻对网络传输的压力,在对大数据处理上,瓶颈往往体现在网络上而不是CPU(压缩和解压会耗掉部分CPU资源)。
5. 批量发送: 提高消息吞吐量重要的方式,Producer 端可以在内存中合并多条消息后,以一次请求的方式发送了批量的消息给 broker,从而大大减少 broker 存储消息的 IO 操作次数。但也一定程度上影响 了消息的实时性,相当于以时延代价,换取更好的吞吐量。

#存储
6. 分区patition分段segment + 索引index
分布式系统分区分桶的设计思想:Kafka 的 message 是按 topic 分类存储的,topic 中的数据又是按照一个一个的 partition 即分区存储到不同broker节点。每个partition对应了操作系统上的一个文件夹,partition实际上又是按照segment分段存储的。为了进一步的查询优化,Kafka又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。 这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度。

Partition 结构

每个topic都可以分为一个或多个partition,partition在服务器上的表现形式就是一个一个的文件夹,

每个partition的文件夹下面会有多组segment文件,每组segment文件又包含.index文件、.log文件、.timeindex文件(早期版本中没有)三个文件,

log文件就实际是存储message的地方,而index和timeindex文件为索引文件,用于检索消息。

  

如上图,这个partition有三组segment文件,每个log文件的大小是一样的,但是存储的message数量是不一定相等的(每条的message大小不一致)。

文件的命名是以该segment最小offset来命名的,如000.index存储offset为0~368795的消息,kafka就是利用分段+索引的方式来解决查找效率的问题。

Message结构

上面说到log文件就实际是存储message的地方,我们在producer往kafka写入的也是一条一条的message,那存储在log中的message是什么样子的呢?消息主要包含消息体、消息大小、offset、压缩类型……等等!我们重点需要知道的是下面三个:

1、 offset:offset是一个占8byte的有序id号,它可以唯一确定每条消息在parition内的位置!
2、 消息大小:消息大小占用4byte,用于描述消息的大小。
3、 消息体:消息体存放的是实际的消息数据(被压缩过),占用的空间根据具体的消息而不一样。

Zookeeper汇总保留了哪些数据?

1、消费者提交的偏移量。
2、leader检测、分布式同步、配置管理、识别新节点何时离开或连接、集群、节点实时状态
3、分区和消费者的所有者关
4、broker id

3,难点知识

数据传输的事物定义有哪三种?

1、最多一次:消息不会被重复发送,最多被传输一次,但也有可能一次不传输,可能会造成数据丢失。

2、最少一次: 消息不会被漏发送,最少被传输一次,但也有可能被重复传输。可能会造成数据的重复消费。

3、精确的一次(Exactly once):不会漏传输也不会重复传输,每个消息都传输被一次而且仅仅被传输一次,这是大家所期望的。

kafka的ack机制

kafka producer 打数据,ack  为 0, 1, -1 的时候表明啥, 设置 -1 的时候,什么状况下,leader 会认为一条消息 commit了

1(默认)数据发送到Kafka后,通过leader成功接收消息的的确认,就算是发送成功了。在这种状况下,若是leader宕机了,则会丢失数据。
0 生产者将数据发送出去就无论了,不去等待任何返回。这种状况下数据传输效率最高,可是数据可靠性确是最低的。
-1 producer须要等待ISR中的全部follower都确认接收到数据后才算一次发送完成,可靠性最高。当ISR中全部Replica都向Leader发送ACK时,leader才commit,这时候producer才能认为一个请求中的消息都commit了。

数据消费

参考:https://blog.csdn.net/shudaqi2010/article/details/90815675(kafka的索引机制)

消息存储在log文件后,消费者就可以进行消费了。与生产消息相同的是,消费者在拉取消息的时候也是找leader去拉取。

多个消费者可以组成一个消费者组(consumer group),每个消费者组都有一个组id!同一个消费组者的消费者可以消费同一topic下不同分区的数据,但是不会组内多个消费者消费同一分区的数据!!!是不是有点绕。我们看下图:

  

图示是消费者组内的消费者小于partition数量的情况,所以会出现某个消费者消费多个partition数据的情况,消费的速度也就不及只处理一个partition的消费者的处理速度!如果是消费者组的消费者多于partition的数量,那会不会出现多个消费者消费同一个partition的数据呢?上面已经提到过不会出现这种情况!多出来的消费者不消费任何partition的数据。所以在实际的应用中,建议消费者组的consumer的数量与partition的数量一致


在保存数据的小节里面,我们聊到了partition划分为多组segment,每个segment又包含.log、.index、.timeindex文件,存放的每条message包含offset、消息大小、消息体……我们多次提到segment和offset,查找消息的时候是怎么利用segment+offset配合查找的呢?假如现在需要查找一个offset为368801的message是什么样的过程呢?我们先看看下面的图:

1、 先找到offset的368801message所在的segment文件(利用二分法查找),这里找到的就是在第二个segment文件。
2、 打开找到的segment中的.index文件(也就是368796.index文件,该文件起始偏移量为368796+1,我们要查找的offset为368801的message在该index内的偏移量为368796+5=368801,所以这里要查找的相对offset为5)。
  由于该文件采用的是稀疏索引的方式存储着相对offset及对应message物理偏移量的关系,所以直接找相对offset为5的索引找不到,
  这里同样利用二分法查找相对offset小于或者等于指定的相对offset的索引条目中最大的那个相对offset,所以找到的是相对offset为4的这个索引。
3、 根据找到的相对offset为4的索引确定message存储的物理偏移位置为256。打开数据文件,从位置为256的那个地方开始顺序扫描直到找到offset为368801的那条Message。

这套机制是建立在offset为有序的基础上,利用segment(分段)+有序offset稀疏索引(.index文件)+二分查找+顺序查找等多种手段来高效的查找数据!至此,消费者就能拿到需要处理的数据进行处理了。

那每个消费者又是怎么记录自己消费的位置呢?

在早期的版本中,消费者将消费到的offset维护zookeeper中,consumer每间隔一段时间上报一次,这里容易导致重复消费,且性能不好!在新的版本中消费者消费到的offset已经直接维护在kafk集群的__consumer_offsets这个topic中!

原文地址:https://www.cnblogs.com/tkzc2013/p/15396715.html