当前位置: 首页 > 后端技术 > Java

kafka(上):基本结构和消息存储

时间:2023-04-01 13:34:37 Java

不同于传统的mq(如rabbitmq),kafka以文件的形式存储和传输消息,官方定义为事件流处理平台,天然具有分布式属性。在2.8版本之前,kafka需要zk来存储broker和consumer的一些信息(注意:producer不依赖zk);2.8之后kafka不再依赖kafka。但是现在的生产环境(kafka3.1版本)还是需要使用zk的。复制一份官方文档:现在可以不用ApacheZooKeeper跑ApacheKafka了!我们称之为KafkaRaft元数据模式,通常简称为KRaft模式。KRaft旨在发音为craft(如工艺)。它目前是预览版,不应在生产中使用,但它可用于在Kafka3.1版本中进行测试。基本结构制作人无话可说。它是一个服务节点,负责向代理推送消息。多个broker组成一个Kafka集群;broker一般部署在不同的物理机上,相同类型消息的topic放在同一个topic中。比如订单属于一个topic,支付属于另一个topic;但需要注意的是,topic只是一个逻辑概念,消息实际上存在于分区partition|中。--topic1-0-->这个文件夹是分区|--00000000000000000000.index|--00000000000000000000.log|--00000000000000368769.index|--00000000000000368769.log|--topic2-0|看到分区的序号是从0开始的。分区实际上是服务器磁盘上的一个文件夹,同一个主题可以包含多个分区。增加partition可以有效提高吞吐量,类似于nginx下增加tomcat可以有效提高吞吐量。比如上图中的topic1,有5个partition,平均分布在3个broker上。如果发送消息时指定的topic为topic1,则消息会按照一定的规则推送到某个partition。当然你也可以在发送的时候指定消息在一个partition中排序,但是在多个partition中不能保证顺序。segmentpartition里面有两种文件,*.index和*.log文件。日志文件存放消息,索引文件存放索引,成对出现;一对同名的log??+index文件称为段,是kafka文件存储的最小单位。段是概念上的东西,没有实际意义。replicationpartition的副本不作为数据备份对外提供服务。Replication和partition一般不在同一个broker上,以增加容错性,类似上图的分布。消费者负责消费消息并通过维护偏移来确定消息。offset可以理解为指向当前消费消息的指针;同时offset也和partition有关,后面会详细介绍。消息被消费后,offset会增加,但消息本身仍然存在于partition中,不会被清理。分区消息只会定期清除,默认保存7天。消费端有一个群体的概念。一个组可以有一个消费者或多个消费者。一条消息只会发送给同一组下的其中一个消费者。多个partition可以对应一个consumer(上图中的group2);但是一个分区不能对应多个消费者,最多一个(上图中的group1)。如果一个group中的consumer数量大于partition数量,就会有空闲的consumer(上图中的consumer3)。我们来看看kafka的消息存储方式|--topic1-0-->这个文件夹是分区|--00000000000000000000.index|--00000000000000000000.log|0000000000000744271.index|--00000000000000744271.log|--topic2-0|--topic2-1消息按顺序写入.log文件。当文件大小达到阈值时,将生成新的日志和索引文件。一开始只有00000000000000000000.log。当文件大小达到500m(默认)时,将生成00000000000000368769.log。数字368769恰好是00000000000000000000.log文件中偏移量的最大值。日志使用这样的命名方式有一个好处。如果搜索offset=728378的消息,可以快速锁定所在文件,必须在00000000000000744271.log文件中。再看索引索引文件,Kafka采用了稀疏索引的方式——不为每条数据建立索引,索引是不连续的。(上图已经为第1、3、6、8、N条数据建立了索引,2、4、5没有建立索引)根据日志文件名(00000000000000368769.log),是容易知道第一个数据对应的offset是368769+1=368770。我们看一下这个分区中数据offset=368776的消息的查找过程:368769<368776<744271,所以定位到00000000000000368769.log文件368776-368769=7,于是找到文件中的第7条数据,到00000000000000368769。索引查找,7不在索引中,但是6和8都有索引。根据索引<6,1407>的值,定位到00000000000000368769.log中的物理偏移地址1407,定位到消息Message368775;不过这是第6条数据数据应该是找到它的下一篇文章,找到Message368776附录P6-P7知识合集