Kafka

一、初识Kafka

  Kafka是一种发布订阅消息系统,主要用于处理活跃的流式数据。

  Kafka的特点:

  1. 同时为发布和订阅提供高吞吐量。Kafka每秒可以生产约25万消息(50MB),每秒处理55万消息(110MB)。
  2. 可进行持久化操作。将消息持久化到磁盘,因此可用于批量消费,例如ETL,以及实时应用程序。通过将数据持久化到硬盘以及replication防止数据丢失。当收到的消息时先buffer起来,等到了一定的阀值再写入磁盘文件,减少磁盘IO。
  3. 分布式系统,易于向外扩展。所有的producer、broker和consumer都会有多个,均为分布式的。无需停机即可扩展机器。它以集群的方式运行,可以灵活伸缩,在内部通过复制数据提升容错能力和高可用性。
  4. 消息被处理的状态是在consumer端维护,而不是由server端维护。当失败时能自动平衡。
  5. 支持online和offline的场景。
  6. Kafka支持实时的流式处理。

  相比传统的消息系统,Kafka可以很好的保证有序性,也可以在多个消费者组并发的情况下提供较好的负载均衡。

1.1 Kafka架构*


  Kafka是分布式架构,Producer、Broker和Consumer都可以有多个。
  Kafka将消息以Topic为单位进行归纳,向Topic发布消息的程序就是Producer,预订Topic并消费消息的程序是Consumer。
  Kafka以集群的方式运行,可以由一个或多个服务组成,每个服务叫做一个 Broker。Producer通过网络将消息发送到Kafka集群,集群向消费者提供消息。

  Broker:负责消息存储和转发,Kafka集群中的一台或多台服务器统称为Broker。
  Topic:消息类别,Kafka按照Topic来分类消息。
  Partition:Topic物理上的分组,一个Topic可以分为多个Partition,每个Partition是一个有序的队列。Partition中的每条消息都会被分配一个有序的id(offset)。每个分区都由一系列有序的、不可变的消息组成,这些消息被连续的追加到分区中。分区中的每个消息都有一个连续的序列号叫做offset,用来在分区中唯一的标识这个消息。
  offset消息在日志中的位置,可以理解是消息在Partition上的偏移量,也是代表该消息的唯一序号。
  Segment:一个partition当中存在多个segment文件段,每个segment分为两部分,.log文件和.index文件,其中.index文件是索引文件,主要用于快速查询,.log存放数据文件。
  Producer:消息生产者,向Kafka的Topic发布消息。Producer将消息发布到它指定的Topic中,并负责决定发布到哪个分区。通常简单的由负载均衡机制随机选择分区,但也可以通过特定的分区函数选择分区。
  Consumer:消息消费者,订阅Topic并处理发布的消息。实际上每个Consumer唯一需要维护的数据是消息在日志中的位置,也就是offset。这个offset有Consumer来维护:一般情况下随着Consumer不断的读取消息,这offset的值不断增加,但其实Consumer可以以任意的顺序读取消息,比如它可以将offset设置成为一个旧的值来重读之前的消息。
  Consumer Group:消费者组,每一个 consumer 属于一个特定的 consumer group(可以为每个consumer指定 groupName).。
  Zookeeper:保存着集群Broker、Topic、Partition等meta数据;另外,还负责Broker故障发现,partition leader选举,负载均衡等功能。

  • 1、Producer
      Producer主要是用于生产消息,是Kafka当中的消息生产者,生产的消息通过Topic进行归类,保存到Kafka的Broker里面去。
  • 2、Topic
      Kafka将消息以Topic为单位进行归类;
      Topic是一种分类或者发布的一些列记录的名义上的名字。Kafka主题始终是支持多用户订阅的;也就是说,一 个主题可以有零个、一个或者多个消费者订阅写入的数据;
      在Kafka集群中,可以有无数的主题;
      生产者和消费者消费数据一般以主题为单位。更细粒度可以到分区级别。
  • 3、Partition
      Topic是消息的归类,一个Topic可以有多个分区(Partition),每个分区保存部分Topic的数据。
      一个Broker服务下,可以创建多个分区,Broker数与分区数没有关系; 在Kafka中,每一个分区会有一个编号:编号从0开始。 每一个分区内的数据是有序的,但全局的数据不能保证是有序的。
  • 4、Consumer
      Consumer是Kafka当中的消费者,主要用于消费Kafka当中的数据,消费者一定是归属于某个消费组中的。
  • 5、Consumer Group
      消费者组由一个或者多个消费者组成,同一个组中的消费者对于同一条消息只消费一次。每个消费者都属于某个消费者组,如果不指定,那么所有的消费者都属于默认的组。
      每个消费者组都有一个ID,即group ID。组内的所有消费者协调在一起来消费一个订阅主题( Topic)的所有分区(Partition)。当然,每个分区只能由同一个消费组内的一个消费者(Consumer)来消费,可以由不同的消费组来消费。
      Partition数量决定了每个Consumer Group中并发消费者的最大数量。

      如果只有两个分区,即使一个组内的消费者有4个,也会有两个空闲的。 右图所示,有4个分区,每个消费者消费一个分区,并发量达到最大4。

      上图所示,不同的消费者组消费同一个Topic,这个Topic有4个分区,分布在两个节点上。左边的消费组1有两个消费者,每个消费者就要消费两个分区才能把消息完整的消费完,右边的消费组2有四个消费者,每个消费者消费一个分区即可。
    【分区与消费组的关系】
      消费组: 由一个或者多个消费者组成,同一个组中的消费者对于同一条消息只消费一次。 某一个主题下的分区数,对于消费该主题的同一个消费组下的消费者数量,应该小于等于该主题下的分区数。

如:某一个主题有4个分区,那么消费组中的消费者应该小于等于4,而且最好与分区数成整数倍1/2/4这样。同一个分区下的数据,在同一时刻,不能同一个消费组的不同消费者消费。

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

  • 6、分区副本

      副本数:控制消息保存在几个Broker(服务器)上,一般情况下副本数等于bBrokeroker的个数。
      一个Broker服务下,不可以创建多个副本因子。创建主题时,副本因子应该小于等于可用的Broker数。
      副本因子操作以分区为单位的。每个分区都有各自的主副本和从副本。
      主副本叫做Leader,从副本叫做Follower(在有多个副本的情况下,Kafka会为同一个分区下的所有分区,设定角色关系:一个Leader和N个Follower),处于同步状态的副本叫做in-sync-replicas(ISR)。
      Follower通过拉的方式从Leader同步数据。 消费者和生产者都是从Leader读写数据,不与Follower交互。
      副本因子的作用:让Kafka读取数据和写入数据时的可靠性。
      副本因子是包含本身,同一个副本因子不能放在同一个Broker中。
      如果某一个分区有三个副本因子,就算其中一个挂掉,那么只会剩下的两个中,选择一个Leader,但不会在其他的Broker中,另启动一个副本(因为在另一台启动的话,存在数据传递,只要在机器之间有数据传递,就会长时间占用网络IO,Kafka是一个高吞吐量的消息系统,这个情况不允许发生)所以不会在另一个broker中启动。
      如果所有的副本都挂了,生产者如果生产数据到指定分区的话,将写入不成功。
      lsr:当前可用的副本。
  • 7、Segment文件
      Topic是逻辑上的概念,物理上存储的其实是Partition,每一个Partition最终对应一个目录,里面存储所有的消息和索引文件。默认情况下,每一个Topic在创建时如果不指定Partition数量时只会创建1个Partition。比如,创建了一个Topic名字为 test ,没有指定Partition的数量,那么会默认创建一个test-0的文件夹,这里的命名规则是: <topic_name>-<partition_id> 。

      任何发布到Partition的消息,都会被追加到Partition数据文件的尾部,这样的顺序写磁盘操作让Kafka的效率非常高。
      每一条消息被发送到Broker 中,会根据Partition规则选择被存储到哪一个Partition。如果Partition规则设置的合理,所有消息可以均匀分布到不同的Partition中。

  假设现在Kafka集群只有一个 Broker,创建2个Topic名称分别为:topic1、topic2,Partition数量分别为1、2,根目录下就会创建如下三个文件夹:

 | --topic1-0
 | --topic2-0
 | --topic2-1

  在Kafka的文件存储中,同一个Topic下有多个不同的Partition,每个Partition都为一个目录,而每一个目录又被平均分配成多个大小相等的Segment File中,Segment File又由index file和data file组成,他们总是成对出现,后缀 “.index” 和 “.log” 分表表示Segment索引文件和数据文件。
  假设设置每个Segment大小为500MB,并启动生产者向topic1中写入大量数据,topic1-0文件夹中就会产生类似如下的一些文件:

 | --topic1-0
   | --00000000000000000000.index
   | --00000000000000000000.log
   | --00000000000000368769.index
   | --00000000000000368769.log
   | --00000000000000737337.index
   | --00000000000000737337.log
   | --00000000000001105814.index | --00000000000001105814.log
 | --topic2-0
 | --topic2-1

  Segment是Kafka文件存储的最小单位。Segment文件命名规则:Partition全局的第一个Segment从0开始,后续每个Segment文件名为上一个Segment文件最后一条消息的offset值。数值最大为64位long大小,19 位数字字符长度,没有数字用0填充。如 00000000000000368769.index和00000000000000368769.log。

  segment index file 采取稀疏索引存储方式,减少索引文件大小,通过mmap(内存映射)可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。

  一个Partition当中由多个Segment文件组成,每个Segment文件,包含两部分,一个是.log文件,另外一个是.index文件,其中 .log 文件包含了我们发送的数据存储,.index 文件,记录的是我们.log文件的数据索引值,以便于我们加快数据的查询速度。
  索引文件中元数据指向对应数据文件中message的物理偏移地址。

  其中以索引文件中元数据 ❤️, 497> 为例,依次在数据文件中表示第 3 个 message(在全局 Partition表示第 368769 + 3 = 368772 个 message)以及该消息的物理偏移地址为 497。
  上图左半部分是索引文件,里面存储的是一对一对的key-value,其中key是消息在数据文件(对应的log文件)中的编号,比如“1,3,6,8……”, 分别表示在log文件中的第1条消息、第3条消息、第6条消息、第8条消息……
  为什么在index文件中这些编号不是连续的呢? 这是因为index文件中并没有为数据文件中的每条消息都建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。 这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。 但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。
  value代表的是在全局partiton中的第几个消息。以索引文件中元数据 3,497 为例,其中3代表在右边log数据文件中从上到下第3个消息, 497表示该消息的物理偏移地址(位置)为497(也表示在全局partiton表示第497个消息-顺序写入特性)。
  注意该 index 文件并不是从0开始,也不是每次递增1的,这是因为 Kafka 采取稀疏索引存储的方式,每隔一定字节的数据建立一条索引,它减少了索引文件大小,使得能够把 index 映射到内存,降低了查询时的磁盘 IO 开销,同时也并没有给查询带来太多的时间消耗。
  因为其文件名为上一个 Segment 最后一条消息的 offset ,所以当需要查找一个指定 offset 的message 时,通过在所有 segment 的文件名中进行二分查找就能找到它归属的 segment ,再在其index 文件中找到其对应到文件上的物理位置,就能拿出该 message 。
  由于消息在 Partition 的 Segment 数据文件中是顺序读写的&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值