kafka基础

109 阅读18分钟

一 什么是kafka

  • kafka是由Linkedin公司开发的,它是一个分布式的,支持多分区,多副本,基于Zookeeper的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统

二 kafka基本数据

  1. 消息:kafka中的数据单元被称为消息,也被称为记录,可以把它看作数据库表中某一行的记录
  2. 批次:为了提高效率,消息会分批次写入kafka,批次就指代一组消息
  3. 主题:消息的种类称为主题,一个主题代表着一类消息。相当于对消息进行分类。类似于数据库中的表
  4. 分区:主题可以被分为若干个分区,同一主题中的分区可以不在一个机器上,有可能会部署在多台机器上,由此来实现kafka的伸缩性,单一主题中的分区有序,无法保证主题中的所有分区都有序
  5. 生产者:向主题发布消息的客户端应用程序称为生产者,生产者用于持续不断的向某个主题发送消息
  6. 消费者:订阅主题消息的客户端称为消费者,消费者用于处理生产者产生的消息
  7. 消费者群组:由一个或多个消费者组成的群体
  8. 偏移量:偏移量是一种元数据,它是一个不断递增的整数值,用来记录消费者发生重平衡时的位置,以便用来恢复数据
  9. broker:一个独立的kafka服务器就被称为broker,broker接受来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存
  10. broker集群:broker集群由一个或多个broker组成,每个集群都有一个broker同时充当集群控制器的角色,自动从集群的活跃成员中选举而来
  11. 副本:kafka中消息的备份又叫做副本,副本的数量时可以配置的,kafka定义了两类副本:领导者副本和追随者副本。前者对外提供服务,后者只是被动跟随
  12. 重平衡:消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。Rebalance是kafka消费者端实现高可用的重要手段

三 kafka特性(设计原则)

  1. 高吞吐,低延迟:kafka最大的特点就是收发消息非常快,kafka每秒可以处理几十万条消息,他的最低延迟只有几毫秒
  2. 高伸缩性:每个主题包含多个分区,主题中的分区可以分布在不同的主机中
  3. 持久性,可靠性:kafka能够允许数据的持久化存储,消息被持久化到磁盘,并支持数据备份防止数据丢失,kafka底层的数据存储是基于Zookeeper存储的
  4. 容错性:允许集群中的节点失败,某个节点宕机时,kafka集群能够正常工作
  5. 高并发:支持数千个客户端同时读写

四 kafka使用场景

  1. 活动跟踪:kafka可以用来跟踪用户行为,比如在淘宝购物,打开淘宝的同时,登录信息,登录次数会作为消息传输到kafka,当浏览商品时,浏览信息,搜索指数,购物爱好都会作为消息传递给kafka,这样可以用来生成报告,做只能推荐
  2. 传递消息:kafka可以用来传递消息,应用程序向用户发送通知就是通过传递消息来实现的,这些应用组件可以生成消息,不需要关心消息格式,不需要关心消息如何发送
  3. 度量指标:kafka可以用来记录运营监控数据。包括收集各种分布式应用数据,生产各种操作的集中反馈,比如报警和报告
  4. 日志记录:kafka的基本概念来源于提交日志
  5. 流式处理:流式处理是一个能够提供多种应用程序的领域
  6. 限流削峰:kafka多用于互联网领域某一时刻请求特别多的情况下,可以把请求写入kafka,避免直接请求后端程序导致服务崩溃

五 kafka消息队列

  • kafka消息队列一般分为两种模式:点对点模式和发布订阅模式
  • kafka支持消费者群组,也就是说kafka中会有一个或多个消费者。点对点模式是指一个生产者生产的消息由一个消费者进行消费
  • 如果一个生产者或多个生产者生产的消息能够被多个消费者同时消费的情况,发布订阅模式

六 kafka系统架构

  1. 一个典型的kafka集群包含若干个生产者,若干个broker,若干个消费者群组,以及一个Zookeeper集群。kafka通过zookeeper管理集群配置,选举leader,以及在消费者群组发生变化时进行Rebalance。生产者通过push模式将消息发送到broker,Consumer通过pull模式从broker订阅并消费消息

七 核心API

  • kafka由四个核心API,他们分别是
    1. Producer API:它允许应用程序向一个或多个topics上发送消息
    2. Consumer API:它允许应用程序订阅一个或多个topics并处理为其生成的记录流
    3. Streams API:它允许应用程序作为流处理器,从一个或多个主题中消费输入流并为其生成输出流,有效的将输入流转换为输出流
    4. Connector API:它允许构建和运行将kafka主题连接到现有应用程序或数据系统的可用身缠这和消费者。例如,关系数据库的连接器可能会捕获对表的所有更改

八 kafka为何快

  • kafka实现了零拷贝原理来快速移动数据,避免了内核间的切换。kafka可以将数据记录分批发送,从生产者到文件系统到消费者,可以端到端的查看这些批次的数据
  • 批处理能够进行更有效地数据压缩并减少I/O延迟,kafka采取顺序写入磁盘的方式,避免了随机磁盘寻址的浪费
  • 总结以下,如下所示:
    1. 顺序读写
    2. 零拷贝
    3. 消息压缩
    4. 分批发送

九 kafka安装

十 kafka配置

十一 kafka生产者

  • 在kafka中,生产消息的一方称为生产者,
  • 消息的发送过程
    1. 首先创建一个ProducerRecord对象,ProducerRecord是kafka中的一个核心类,它代表了一组kafka需要发送的k/v键值对,它由记录要发送到的主题名称(topic),可选的分区号(partition)以及可选的键值对组成
      • topic
      • partition
      • key
      • value
    2. 在发送ProducerRecord时,需要将键值对对象由序列化器转化为字节数组,这样才能在网络上传输
    3. 消息到达分区器
    4. 如果发送过程中制定了有效的分区好,那么在发送记录时将使用该分区。如果发送过程中未指定分区,则将使用key的hash函数映射指定一个分区。如果发送的过程中既没有分区号也没有key,那么将以循环的方式分配一个分区。选好分区后,生产者就知道往哪个主题和哪个分区发送数据了
    5. ProducerRecord还有关联的时间戳,如果用户没有提供时间戳,那么生产者将会在记录中使用当前时间作为时间戳。kafka最终使用的时间戳取决于topic主题配置的时间戳类型
      • 如果将主题配置为使用createTime,则生产者记录中的时间戳将由broker使用
      • 如果将主题配置为使用LogAppendTime,则生产者记录中的时间戳在将消息添加到其日志中时,将由broker重写
    6. 然后这条消息被存放在一个记录批次里,这个批次里的所有消息会被发送到相同的主题和分区上。有一个独立的线程负责把他们发送到kafka broker上
    7. kafka broker在收到消息时会返回一个响应。如果写入成功,会返回一个RecordMetaData对象,它包含了主题和分区信息,以及记录在分区里的偏移量,上面两种时间戳类型也会返回给用户。如果写入失败,会返回一个错误。生产者在收到错误之后会尝试重新发送消息,几次之后如果还是白的话,就返回错误消息
  • 创建kafka生产者
  • kafka消息发送
    • 发送消息主要有下面几种形式
      1. 简单消息发送
      2. 同步消息发送
      3. 异步消息发送
  • 生产者分区机制
    1. kafka对于数据的读写是以分区为力度的,分区可以分布在多个主机(broker)中,这样每个节点能够实现独立的数据写入和读取,并且能够通过增加新的节点来增加kafka集群的吞吐量,通过分区部署在多个broker来实现负载均衡效果
    2. 由于消息是存在主题的分区中的,所以当生产者发送一条消息给主题的时候,如何判断这条消息在哪个分区中就使用到了kafka分区机制
  • 分区策略
    1. kafka的分区策略是指将生产者发送到哪个分区的算法。kafka为我们提供了默认的分区策略,同时也支持自定义分区策略
    2. 阿嘎
    3. 分区策略有如下几种
      • 顺序轮询:顺序分配,消息是均匀的分配给每个分区,即每个分区存储一次消息。轮询策略是kafka生产者提供的默认策略
      • 随机轮询:随机轮询就是随机的向分区中保存消息。本质上看随机策略也力求将数据均匀打散到各个分区,但是实际表现来看,它要劣于轮询策略。所以,如果追求数据的均匀分布,还是使用轮询策略比较好
      • 按照key进行消息保存。这个策略也叫key-ordering策略,kafka中每条消息都有自己的key,一旦消息被定义了key,那么就可以保证同一个key的所有消息都进入到相同的分区里面,由于每个分区下的消息处理都是有顺序的,故这个策略被称为按消息键保存策略
  • 生产者压缩机制
    1. 压缩的本质就是一种互换思想。比如使用CPU时间换磁盘空间,希望以较小的CPU开销带来跟梢的磁盘占用或者网络I/O
  • kafka压缩是什么
    1. kafka消息分为两层:消息集合和消息。一个消息集合中包含若干条日志项,而日志项才是真正封装消息的地方。kafka底层的消息日志由一系列消息集合日志项组成。kafka通常不会直接操作具体的一条条消息,它总是在消息集合这个层面上进行写入操作
    2. 在kafka中,压缩会发生在两个地方:生产者和消费者。使用压缩是想让消息变小一点,是消息发送更快一点
    3. 有压缩必有解压缩,生产者使用压缩算法压缩消息后发送给服务器,由消费者进行解压缩,因为采用何种压缩算法是随着k/v一起发送过去的,所以消费者知道采用何种压缩算法
  • kafka重要参数配置

十二 kafka消费者

  • 应用程序使用kafka消费者从kafka中订阅主题并接受来自这些主题的消息,然后再把他们保存起来。应用程序首先需要创建一个KafkaConsumer对象,订阅主题并开始接受消息,验证消息并保存结果。一段时间后,生产者往主题写入的速度超过了应用程序验证数据的速度,这时候该如何处理?如果只使用单个消费者的话,应用程序会跟不上消息生成的速度,就像多个生产者向相同主题写入消息一样,这时候就需要多个消费者同时参与消费主题中的消息,对消息进行分流处理
  • kafka消费者从属于消费者群组。一个群组中的消费者订阅都是相同的主题,每个消费者接收主题一部分分区的消息
  • 向群组中增加消费者是横向伸缩消费能力的主要方式。总而言之,我们可以通过增加消费者组的消费者来进行水平扩展提高消费能力。这也是为什么建议创建主题时使用比较多的分区数,这样可以再消费负载高的情况下增加消费者来提升性能。另外消费者数量不应该比分区数量多,因为多出来的消费者是空闲的,没有任何帮助
  • kafka一个很重要的特性就是,只需要写入一次消息,可以支持人一多的应用程序读取这个消息。换句话说,每个应用程序都可以读到全量的消息。为了使得每个应用都能读到全量的消息,应用需要由不同的消费组。
  • 总结起来就是如果应用需要读取全量消息,那么请为该应用设置一个消费组。如果该应用消费能力不足,那么可以考虑在这个消费组里增加消费者
  • 消费者组和分区重平衡
    1. 消费者组是什么
      • 消费者组是由一个或多个消费者实例组成的群组,具有可扩展性和可容错性的一种机制。消费者组内的消费者共享一个消费者组ID,这个ID也叫做Group ID,组内的消费者共同对一个主题进行订阅和消费,同一个族中的消费者只能消费一个分区的消息,多余的消费者会限制
      • 两种消费模式
        1. 一个消费者群组消费一个主题中的消息,这种消费模式又称为点对点消费模式,点对点的消费模式又被称为消息队列
        2. 一个主题中的消息被多个消费者群组共同消费,这种消费模式又称为发布订阅模式
    2. 消费重平衡
    • 存在这样一个过程:最初是一个消费者订阅一个主题并消费全部分区的消息,后来有一个消费者加入群组,随后又有更多的消费者加入群组,但是新加入的消费者实例分摊了最初消费者的部分消息,这种把分区所有权通过一个消费者转到其他消费者的行为称为重平衡
    • 重平衡非常重要,他为消费者群组带来了高可用性和伸缩性,可以放心的添加消费者或移除消费者,不过正常情况下我并并不希望这样。在重平衡期间,消费者无法读取消息,造成整个消费者组在重平衡期间都不可用。另外,当分区重新分配给另一个消费者时,消息当前读取状态会丢失,它有可能还需要去刷新缓存,在它恢复状态前会拖慢应用程序
    • 消费者通过向组织协调这(kafka broker)发送心跳来维护自己时消费者组的一员并确认其拥有分区。对于不同的消费者群体来说,其组织协调者可以是不同的。只要消费者定期发送心跳,就会认为消费者时存活的并处理其分区中的消息。当消费者检索记录或者提交它锁消费的记录时就会发送心跳
    • 过一段时间kafka停止发送心跳了,会话就过期了,组织协调这就会认为这个consumer已经死亡,就会触发一次重平衡。如果消费者宕机并停止发送消息,组织协调者会等待几秒钟,确认它死亡了才会触发重平衡。在这段时间里,死亡的消费者将不处理任何消息。在清理消费者时,消费者将通知协调者他要离开群组,组织协调者会触发一次重平衡,尽量降低处理停顿
    • 重平衡是一把双刃剑,它为消费者群组带来高可用性和伸缩性的同hi还有一些明显的缺点
    • 重平衡的过程对消费者组由极大的影响。每次重平衡都会导致消费者组中的消费者实例停止消费等待重平衡的完成。而且重平衡过程很慢
  • 创建消费者
  • 主题订阅
  • 轮询
    1. kafka是支持发布订阅模式的。生产者发送数据给kafka broker,那么消费者是如何知道生产者发送了数据呢?消费者通过轮询的凡是定期去kafka broker中进行数据的检索,如果有数据来就消费,如果没有就再继续等待
  • 线程安全性
    1. 在同一个群组中,我们无法让一个线程运行多个消费者,也无法让多个线程安全的共享一个消费者。按照这个规则的话,一个消费者使用一个线程,如果一个消费者群组中多个消费者都想运行的话,那么必须让下佛欸这在自己的线程中运行,可以使用java中的Executro Service启动多个消费者进行处理
  • 消费者配置
  • 提交和偏移量
    1. 特殊偏移
      • 消费者在每次调用poll方法进行轮询时,会返回由生产者写入kafka但是还没有被消费者消费的记录,由此我们可以追踪到哪些记录是被群组里的哪个消费者读取的。消费者可以使用kafka来追踪消息在分区中的位置(偏移量)
      • 消费者会向一个叫做_consumer_offset的特殊主题中发送消息,这个主题会保存每次发送消息中的偏移量,这个主题的主要作用是消费者触发重平衡后记录偏移使用的,消费者每次像这个主题发送消息,正常情况下不触发重平衡,这个主题是不起作用的,当触发重平衡后,消费者停止工作,每个消费者可能会分到对应的分区,这个主题就是让消费者能够继续处理消息所设置的
      • 如果提交的偏移量小于客户端最后一次处理的偏移量,那么位于两个偏移量之间的消息就会被重复处理,重平衡之后,消费者重复消费。如果提交的偏移量大于最后一次消费时的偏移量,那么处于啷个偏移量中间的消息将会丢失,重平衡之后消费者丢失数据。Consumer API提供了多种方式来提交偏移量:如下
    2. 自动提交
      • 最简单的方式就是让消费者自动提交偏移量
    3. 提交当前偏移量
      • 把 auto.commit.offset 设置为 false,可以让应用程序决定何时提交偏移量。使用 commitSync() 提交偏移量。这个 API 会提交由 poll() 方法返回的最新偏移量,提交成功后马上返回,如果提交失败就抛出异常。commitSync() 将会提交由 poll() 返回的最新偏移量,如果处理完所有记录后要确保调用了 commitSync(),否则还是会有丢失消息的风险,如果发生了在均衡,从最近一批消息到发生在均衡之间的所有消息都将被重复处理
    4. 异步提交
      • 异步提交 commitAsync() 与同步提交 commitSync() 最大的区别在于异步提交不会进行重试,同步提交会一致进行重试
    5. 同步和异步组合提交
      • 一般情况下,针对偶尔出现的提交失败,不进行重试不会有太大的问题,因为如果提交失败是因为临时问题导致的,那么后续的提交总会有成功的。但是如果在关闭消费者或再均衡前的最后一次提交,就要确保提交成功。因此,在消费者关闭之前一般会组合使用commitAsync和commitSync提交偏移量
    6. 提交特定的偏移量
      • 消费者API允许调用 commitSync() 和 commitAsync() 方法时传入希望提交的 partition 和 offset 的 map,即提交特定的偏移量