Kafka

Author Avatar
kevin
发表:2024-07-17 17:07:00
修改:2024-10-09 17:07:34

Kafka 是一个分布式的基于发布/订阅模式的消息队列

Kafka介绍

目前有两种模式

  • 点对点
    • 消费者消费数据之后,发送收到,然后清除信息
  • 发布,订阅模式
    • 有多个主题(流量,点赞,收藏,评论等)
    • 消费之后不删除数据(类似于广播模式)
  • 信息默认保留7天
  • offset保证不重复消费

kafka基本概念

名称解释
Broker消息中间件处理节点,⼀个Kafka节点就是⼀个broker,⼀个或者多个Broker可以组成⼀个Kafka集群
TopicKafka根据topic对消息进⾏归类,发布到Kafka集群的每条消息都需要指定⼀个topic
Producer消息⽣产者,向Broker发送消息的客户端
Consumer消息消费者,从Broker读取消息的客户端
ConsumerGroup每个Consumer属于⼀个特定的Consumer Group,⼀条消息可以被多个不同的Consumer Group消费,但是⼀个Consumer Group中只能有⼀个Consumer能够消费该消息
Partition物理上的概念,⼀个topic可以分为多个partition,每个partition内部消息是有序的

Broker

因为kafka通常时进行分布式部署,所以一个物理服务器(一个操作系统)通常只部署启动一个kafka实例,所以在这种场景下Broker代理就可以理解是一台服务器

主题与主题分区

topic国内叫做主题,可以理解为一个MQ消息队列的名字
topic可以实现消息的分类,不同消费者订阅不同的topic

为了实现扩展性,一个非常大的topic可以分布到多个 broker(即服务器)上,一个topic(主题)可以分为多个partition(分区)

每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体 (多个partition间)的顺序

分区的作用

  • 可以分布式存储
  • 可以并行写

分区只能增加,不能减少

分区是一个实实在在的物理存在的队列数据结构用于存放数据,占用系统内存以及磁盘数据存储等资源

消费者组

为了配合分区,就有了消费者组,同一组内每个消费者并行消费(比如一个消费者只能消费其中一个分区)

多个消费同一主题Topic数据的消费者线程,可以组成一个消费者组

一个消费者组可以订阅多个主题,消费多个主题下的数据

但是别的消费者组也能对这些分区进行消费(广播模式)

形成一个组的条件,所有消费者的分组id相同

  • 组内消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费
  • 消费者组之间互不影响,消费者组是逻辑上的一个订阅者

分区副本与高可用

分区可以设置备份,叫做副本

副本可以分布到多个broker上

为了高可用,给分区添加副本

默认生产和消费主分区(leader),主分区挂了,副本(follower)成为主分区

  • kafka集群中由多个broker组成
  • 一个broker中存放一个topic的不同partition——副本

分区副本的数据同步

生产者和消费者只和主分区进行数据通信,那么从副本的数据从哪里来的?从副本( Follower )的数据是从主副本(Leader)那里同步过来的

一般生产环境只分配2个副本,保证磁盘不浪费 ,也保证了高可用

2.8版本之前,kafak元数据存储到zookeeper中,需要zookeeper集群

zookeeper作用

  • 记录了哪些分区上线了
  • 记录每个分区,哪个是leader

2.8版本之后,官方宣告4.0正式弃用zookeeper,可以配置不采用zookeeper

  • kraft模式替代zookeeper

isr,ar,osr

Ar = 所有副本统称

isr = 和leader保持同步的follower集合

isr中如果follower长时间未向leader发送通信请求或同步数据,将被提出isr放到osr中,默认是30秒

osr = follower和leader副本同步时,延迟过多的副本

故障处理细节

LEO(long end offset):多个副本最后一个offset,leo其实就是最新的offset+1

HW(hign watermark高水位线):isr中最小的leo(木桶原理),每个副本都有的

follower挂掉之后:

  • 被踢出isr
  • leader和其他follower继续接受数据
  • 故障follower恢复后,读取本地磁盘记录的上次hw线,并将log文件高于hw的部分截取掉,从hw开始进行同步
  • 等故障的leo大于等于分区的hw线时,重新加入isr

leader挂掉:

  • 从isr选出新的leader
  • 为了保证副本之间数据的一致性,其余的follower先将各自的log文件高于hw的部分截取掉,从新的leader同步

文件存储机制

topic是逻辑概念,partition是物理概念,每个分区对应一个log文件,

存储的是producer生产的数据,会不断的追加到log文件末尾,

为了防止log文件过大导致数据定位效率低下,采取了分片和索引机制

将每个分区分为多个segment(分段),

每个分段包括(默认是1g大小)

  • .index文件,为了快速定位数据,创建索引
    • index为稀疏索引,大约每往log文件写入4kb数据,会往index文件写入一条索引
  • .log文件等 真正存储数据的文件
  • index和log文件以当前segment的第一条消息的offset命名
  • 这些文件都放在一个文件夹下,topic名称+分区序号,比如first-0

高效读写

kafka天生是分布式集群,采用分区技术,并行度高

数据采用稀疏索引,可以快速定位要消费的数据

顺序写磁盘

  • 写的过程是一直追加到文件末端,官网数据表明,顺序写能达到600m一秒,随机写只有100k,因为省去了大量磁头寻址时间

零拷贝技术

  • 数据加工处理交给生产者和消费者处理,broker应用层不关心存储的数据,所以不用走应用层,效率高

非零拷贝工作流程

  • 生产者发送到kafka,然后交给内核,内核进行页缓存
  • 依赖底层操作系统的pageCache功能,有写操作时,将数据写入pagecache,读操作时,先从pageCache查找,找不到,在去磁盘中读取
  • 消费者拉取数据,走了用户态
  • 然后内核态再通过网卡发送给消费者

零拷贝

  • 生产者发送到kafka,然后交给内核,内核进行页缓存
  • 依赖底层操作系统的pageCache功能,有写操作时,将数据写入pagecache,读操作时,先从pageCache查找,找不到,在去磁盘中读取
  • 然后内核态再通过网卡发送给消费者

kraft模式

2.8之前

元数据存在zookeeper中,动态选举controller,由controller进行kafak集群管理

2.8之后

kraft,不依赖zookeeper集群,使用三台controller节点代替zookeeper,元数据保存在controller中,由controller直接进行kafak集群管理

RabbitMq和kafak区别

同样是消息队列,之前都是用的RabbitMq,现在做一个比较

Rabbit配置少,kafka需要依赖zookeeper集群,配置多

看业务,假设需要延迟消息的功能

  • RabbitMq有ttl机制,可以很方便的完成这个功能

  • Kafka 要实现延迟队列就很麻烦了。

    • 你先需要把消息先放入一个临时的 topic。

    • 然后得自己开发一个做中转的消费者。让这个中间的消费者先去把消息从这个临时的 topic 取出来。

    • 取出来,这消息还不能马上处理啊,因为没到时间呢。也没法保存在自己的内存里,怕崩溃了,消息没了。所以,就得把没有到时间的消息存入到数据库里。

    • 存入数据库中的消息需要在时间到了之后再放入到 Kafka 里,以便真正的消费者去执行真正的业务逻辑。

数据的处理

  • RabbitMQ消息消费之后就会被删除
  • Kafka 消息会被持久化一个专门的日志文件里。不会因为被消费了就被删除。可以根据offset选择位置消费

消息监控

  • RabbitMQ自带监控
  • Kafka 需要安装Efak进行一个监控
评论