1.首先一个kafka集群有很多个kafka的服务器,每个kafka服务器就是一个broker,每一类消息有一个topic,生产者将一个消息发送给broker。
2.每个topic会有一个或者多个分区,broker根据分发机制将这个消息分给这个topic下的某个分区的leader,
分发机制:
- 1.发的消息指定了分区就发到特定分区下
- 2.指定了key,就根据murmur2 哈希算法对key计算得到一个哈希值,将哈希值与分区数量取余,得到分区。
- 3.没有指定分区,也没有指定key,那么就根据一个自增计数与分区数取余得到分区,这样可以让消息分发在每个分区更加均匀。
3.每个分区就是一个目录,目录名是topic+分区编号,在收到消息后会将消息写入到日志文件中,如果一个分区的消息都有存放在一个日志文件中,那么文件会比较大,查询时会比较慢,而且也不便于之后删除旧的消息。所以每个分区对应多个大小相等的segment文件,每个segment的名称是上一个segment最后一条消息的offset,一个segment有两个文件,一个是.index文件,记录了消息的offset及这条消息数据在log文件中的偏移量。一个是.log文件,实际存储每个消息数据,每条消息数据大小不一,每条消息数据包含offset,消息体大小,消息体等等内容。查的时候根据offset先去index文件找到偏移量,然后去log文件中读。
(具体的segment切分有很多个触发条件:
当log文件>log.segment.bytes时切分,默认是1G。
或者是segment文件中最早的消息距离现在的时间>log.roll.ms配置的时间,默认是7天。
或者是索引文件index>log.index.size.max.bytes的大小,默认是10M。)
4.分区leader将消息存储到日志文件中后还不能算是写成功,会把消息同步给所有follower,当follower同步好消息之后就会给leader发ack,leader收到所有follower返回的ack之后,这条才算是写成功,然后才会给生产者返回写成功。(依据ACK配置来决定多少follower同步成功才算生产者发送消息成功)
5.消费者读数据时就去分区的leader中去读,一个消费者可以消费多个分区,但是一个分区只能一个消费者来消费,默认消费者取完数据就会自动提交,一般会关闭自动提交,消费者消费成功后,进行手动提交,分区的offset才会向后移动。(默认是会自动提交,一般会关闭自动提交)
注意事项:
1.replication.factor>=2,也就是一个分区至少会有两个副本。
2.min.insync.replicas默认是1,leader至少要有一个follow跟自己保持联系没有掉线。(这个配置只有在ack为all或者-1时有用,也就是ack为all也只是要求生产者发送的消息,被leader以及ISR集合里面的从节点接收到,就算所有节点都接收到了。)
3.一般设置了ack=all就不会丢数据。因为会保证所有的follower都收到消息,才算broker接收成功,默认ack=1。
4.retries=,生产者写入消息失败后的重试次数。
5.每个partition有一个offset,
6.生产者ACK配置:
1(默认) 数据发送到Kafka后,经过leader成功接收消息的的确认,就算是发送成功了。在这种情况下,如果leader宕机了,则会丢失数据。
0 生产者将数据发送出去就不管了,不去等待任何返回。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
-1 也就是all,producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成,可靠性最高;