<Zhuuu_ZZ>Apache Kafka原理&操作大全

本文详细介绍了Apache Kafka的配置步骤、消息队列原理、Kafka的工作流程、文件储存机制、生产者与消费者的特性和操作,以及如何在实际项目中使用Flume加载数据至Kafka和Hbase。文章深入探讨了Kafka的高吞吐量、数据可靠性、事务支持和监控等方面,还提供了丰富的面试题以检验对Kafka的理解。
摘要由CSDN通过智能技术生成

Apache Kafka原理&操作大全

一 Kafka配置

1、下载

链接: kafka download.

在这里插入图片描述

2、配置

  • 解压 tar -zxvf .....
  • 重命名为kafka
  • 进入cd /opt/kafka/config目录后,修改配置文件vi ./server.properties
//21行,broker 的全局唯一编号,不能重复
//搭建高可用kafka集群时,修改其余机器的机器id,可为broker.id=1或broker.id=2等等,最好与zookeeper中的myid对应
broker.id=0 
    
//36行,生产者消费者通信端口
//搭建集群时这里的ip地址也修改为各自的ip
advertised.listeners=PLAINTEXT://192.168.198.201:9092

//60行,消息储存目录
log.dirs=/opt/kafka/kafka-logs

//123行,配置连接zookeeper
//集群时,这里为:zookeeper.connect=192.168.198.201:2181,192.168.198.202:2181,192.168.198.203:2181
zookeeper.connect=192.168.198.201:2181

//137行,默认可删除topic为false,这里设置为true
delete.topic.enable=true

//集群时,分区数和副本数可以修改为机器数
//num.partitions=3
//offsets.topic.replication.factor=3
//transaction.state.log.replication.factor=3
//transaction.state.log.min.isr=3
  • 修改全局环境变量 vi /etc/profilesource /etc/profile
export KAFKA_HOEM=/opt/kafka
export PATH=$PATH:$KAFKA_HOME/bin

注:若是搭建kafka集群(需要zookeeper集群已搭建好),可一台机器搭建好,直接发送到其余机器:scp -r /opt/kafka root@hadoop202:$PWD,scp -r /opt/kafka root@hadoop203:$PWD。全局环境变量文件也可以同样发送过去,然后source /etc/profile即可。

二 Kafka原理解析

1、消息队列

在这里插入图片描述
(1)点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除)

  • 点对点模型通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消息推送到客户端。这个模型的特点是发送到队列的消息被一个且只有一个接收者接收处理,即使有多个消息监听者也是如此。

(2)发布/订阅模式(一对多,数据生产后,推送给所有订阅者)

  • 发布订阅模型则是一个基于推送的消息传送模型。发布订阅模型可以有多种不同的订阅者,临时订阅者只在主动监听主题时才接收消息,而持久订阅者则监听主题的所有消息,即使当前订阅者不可用,处于离线状态。

2、为什么需要消息队列

1)解耦:
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

2)冗余:
消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

3)扩展性:
因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。

4)灵活性 & 峰值处理能力:
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。

5)可恢复性:
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

6)顺序保证:
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。(Kafka 保证一个 Partition 内的消息的有序性)

7)缓冲:
有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。

8)异步通信:
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

3、什么是Kafka

在流式计算中,Kafka 一般用来缓存数据,Storm 通过消费 Kafka 的数据进行计算。

1)Apache Kafka 是一个开源消息系统,由 Scala 写成。是由 Apache 软件基金会开发的一个开源消息系统项目。

2)Kafka 最初是由 LinkedIn 公司开发,并于 2011 年初开源。2012 年 10 月从 Apache Incubator 毕业。该项目的目标是为处理实时数据提供一个统一、高通量、低等待的平台。

3)Kafka 是一个分布式消息队列。Kafka 对消息保存时根据 Topic 进行归类,发送消息者称为 Producer,消息接受者称为 Consumer,此外 kafka 集群有多个 kafka 实例组成,每个实例(server)称为 broker。

4)无论是 kafka 集群,还是 consumer 都依赖于 zookeeper 集群保存一些 meta 信息,来保证系统可用性。

3、Kafka体系架构

在这里插入图片描述
如上图所示,一个典型的Kafka体系架构包括若干Producer(可以是服务器日志,业务数据,页面前端产生的page view等等),若干broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干Consumer (Group),以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在consumer group发生变化时进行rebalance。Producer使用push(推)模式将消息发布到broker,Consumer使用pull(拉)模式从broker订阅并消费消息。

含义:

名称 解释
Broker 消息中间件处理节点,一个Kafka节点就是一个broker,一个或者多个Broker可以组成一个Kafka集群
Topic Kafka根据topic对消息进行归类,发布到Kafka集群的每条消息都需要指定一个topic
Producer 消息生产者,向Broker发送消息的客户端
Consumer 消息消费者,从Broker读取消息的客户端
ConsumerGroup 每个Consumer属于一个特定的Consumer Group,一条消息可以发送到多个不同的Consumer Group,但是一个Consumer Group中只能有一个Consumer能够消费该消息
Partition 物理上的概念,一个topic可以分为多个partition,每个partition内部是有序的
Replica 副本,为保证集群中的某个节点发生故障时,该节点上的partition数据不丢失,且kafka仍然能够继续工作,kafka提供了副本机制,一个topic的每个分区都有若干个副本,一个leader和若干个follower。
leader 每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是leader。
follower 每个分区多个副本中的“从”,实时从leader中同步数据,保持和leader数据的同步。leader发生故障时,某个follower会成为新的leader。

4、Topic & Partition

一个topic可以认为一个一类消息,每个topic将被分成多个partition,每个partition在存储层面是append log文件。任何发布到此partition的消息都会被追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),offset为一个long型的数字,它唯一标记一条消息。每条消息都被append到partition中,是顺序写磁盘,因此效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是Kafka高吞吐率的一个很重要的保证)。
在这里插入图片描述
每一条消息被发送到broker中,会根据partition规则选择被存储到哪一个partition。如果partition规则设置的合理,所有消息可以均匀分布到不同的partition里,这样就实现了水平扩展。(如果一个topic对应一个文件,那这个文件所在的机器I/O将会成为这个topic的性能瓶颈,而partition解决了这个问题)。在创建topic时可以在$KAFKA_HOME/config/server.properties中指定这个partition的数量(如下所示)

# The default number of log partitions per topic. More partitions allow greater
# parallelism for consumption, but this will also result in more files across
# the brokers.
num.partitions=3

当然可以在topic创建时去修改partition的数量:

 kafka-topics.sh --create --zookeeper 192.168.198.201:2181 --topic kb09demo2 --partitions 3 --replication-factor 1

在发送一条消息时,可以指定这个消息的key,producer根据这个key和partition机制来判断这个消息发送到哪个partition。partition机制可以通过指定producer的partition.class这一参数来指定,该class必须实现kafka.producer.Partitioner接口。

三 Kafka工作流程及文件储存机制

1、Kafka工作流程

在这里插入图片描述

  • Kafka中消息是以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic的。
  • topic是逻辑上的概念,而partition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是producer生产的数据。Producer生产的数据会被不断追加到该log文件末端,且每条数据都有自己的offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个offset,以便出错恢复时,从上次的位置继续消费。

2、Kafka文件储存机制

在这里插入图片描述

  • 由于生产者生产的消息会不断追加到log文件末尾,为防止log文件过大导致数据定位效率低下,Kafka采取了分片和索引机制,将每个partition分为多个segment。每个segment对应两个文件——“.index”文件和“.log”文件。这些文件位于一个文件夹下,该文件夹的命名规则为:topic名称+分区序号。例如,first这个topic有三个分区,则其对应的文件夹为first-0,first-1,first-2。
00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log
  • index和log文件以当前segment的第一条消息的offset命名。下图为index文件和log文件的结构示意图。
    在这里插入图片描述
  • “.index”文件存储大量的索引信息,“.log”文件存储大量的数据,索引文件中的元数据指向对应数据文件中message的物理偏移地址。

四 Kafka生产者

1、分区策略

1)分区的原因
(1)方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;
(2)可以提高并发,因为可以以Partition为单位读写了。

2)分区的原则
我们需要将producer发送的数据封装成一个ProducerRecord对象。
在这里插入图片描述

(1)指明 partition 的情况下,直接将指明的值直接作为 partiton 值;
(2)没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值;
(3)既没有 partition 值又没有 key 值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与 topic 可用的 partition 总数取余得到 partition 值,也就是常说的 round-robin 算法。

2、数据可靠性保证

为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack(acknowledgement确认收到),如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。
在这里插入图片描述

1)副本数据同步策略

方案 优点 缺点
半数以上完成同步,就发送ack 延迟低 选举新的leader时,容忍n台节点的故障,需要2n+1个副本
全部完成同步,才发送ack 选举新的leader时,容忍n台节点的故障,需要n+1个副本 延迟高

Kafka选择了第二种方案,原因如下:
(1)同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余。
(2)虽然第二种方案的网络延迟会比较高,但网络延迟对Kafka的影响较小。

2)ISR

  • 采用第二种方案之后,设想以下情景:leader收到数据,所有follower都开始同步数据,但有一个follower,因为某种故障,迟迟不能与leader进行同步,那leader就要一直等下去,直到它完成同步,才能发送ack。这个问题怎么解决呢?
    • Leader维护了一个动态的in-sync replica set (ISR),意为和leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会给producer发送ack。如果follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms参数设定。Leader发生故障之后,就会从ISR中选举新的leader。

3)ack应答机制

  • 对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等ISR中的follower全部接收成功。

  • 所以Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下的配置。
    acks参数配置:

  • acks:

    • 0:producer不等待broker的ack,这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据;
    • 1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据;
    • -1(all):producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack。但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复。
      (当acks=-1时,只有集群中所有follower全都复制好数据,才会更新leader的HW,才会返回给producer OK.要是leader宕机,那么leader的HW就不会更新还是原来的,返回producerError,那么重写选取leader后,HW还是原来的,producer就会发送HW之后的信息)

4)故障处理细节
在这里插入图片描述
(1)follower故障
follower发生故障后会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步。等该follower的LEO大于等于该Partition的HW,即follower追上leader之后,就可以重新加入ISR了。
(2)leader故障
leader发生故障之后,会从ISR中选出一个新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据。
注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。

3、Exactly Once语义

  • 将服务器的ACK级别设置为-1,可以保证Producer到Server之间不会丢失数据,即At Least Once语义。相对的,将服务器ACK级别设置为0,可以保证生产者每条消息只会被发送一次,即At Most Once语义。
  • At Least Once可以保证数据不丢失,但是不能保证数据不重复;相对的,At Least Once可以保证数据不重复,但是不能保证数据不丢失。但是,对于一些非常重要的信息,比如说交易数据,下游数据消费者要求数据既不重复也不丢失,即Exactly Once语义。在0.11版本以前的Kafka,对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据做全局去重。对于多个下游应用的情况,每个都需要单独做全局去重,这就对性能造成了很大影响。
  • 0.11版本的Kafka,引入了一项重大特性:幂等性。所谓的幂等性就是指Producer不论向Server发送多少次重复数据,Server端都只会持久化一条。幂等性结合At Least Once语义,就构成了Kafka的Exactly Once语义。即:
  • At Least Once + 幂等性 = Exactly Once
  • 要启用幂等性,只需要将Producer的参数中enable.idompotence设置为true即可。Kafka的幂等性实现其实就是将原来下游需要做的去重放在了数据上游。开启幂等性的Producer在初始化的时候会被分配一个PID,发往同一Partition的消息会附带Sequence Number。而Broker端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时,Broker只会持久化一条。
  • 但是PID重启就会变化,同时不同的Partition也具有不同主键,所以幂等性无法保证跨分区跨会话的Exactly Once。

五 Kafka消费者

1、消费方式

  • consumer采用pull(拉)模式从broker中读取数据
  • push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而push模式则可以根据consumer的消费能力以适当的速率消费消息。
  • pull模式不足之处是,如果kafka没有数据,消费者可能会陷入循环中,一直返回空数据。针对这一点,kafka的消费者在消费数据时会传入一个时长参数timeout,如果当前没有数据可供消费,consumer会等待一段时间之后再返回,这段时长即为timeout。

2、分区分配策略

  • 一个consumer group中有多个consumer,一个 topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由哪个consumer来消费。
  • Kafka有两种分配策略,一是roundrobin,一是range。
    • roundrobin
      在这里插入图片描述

      • range
        在这里插入图片描述

3、offset的维护

  • 由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置的继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费。
  • Kafka 0.9版本之前,consumer默认将offset保存在Zookeeper中,从0.9版本开始,consumer默认将offset保存在Kafka一个内置的topic中,该topic为__consumer_offsets。

六 Kafka高效读写数据

1、顺序写磁盘

  • Kafka的producer生产数据,要写入到log文件中,写的过程是一直追加到文件末端,为顺序写。官网有数据表明,同样的磁盘,顺序写能到到600M/s,而随机写只有100k/s。这与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间。

2、应用Pagecache

  • Kafka数据持久化是直接持久化到Pagecache中,这样会产生以下几个好处:
    • I/O Scheduler 会将连续的小块写组装成大块的物理写从而提高性能
    • I/O Scheduler 会尝试将一些写操作重新按顺序排好,从而减少磁盘头的移动时间
    • 充分利用所有空闲内存(非 JVM 内存)。如果使用应用层 Cache(即 JVM 堆内存),会增加 GC 负担
    • 读操作可直接在 Page Cache 内进行。如果消费和生产速度相当,甚至不需要通过物理磁盘(直接通过 Page Cache)交换数据
    • 如果进程重启,JVM 内的 Cache 会失效,但 Page Cache 仍然可用
  • 尽管持久化到Pagecache上可能会造成宕机丢失数据的情况,但这可以被Kafka的Replication机制解决。如果为了保证这种情况下数据不丢失而强制将 Page Cache 中的数据 Flush 到磁盘,反而会降低性能。

3、零复制技术

在这里插入图片描述
在这里插入图片描述

七 Kafka事务

Kafka从0.11版本开始引入了事务支持。事务可以保证Kafka在Exactly Once语义的基础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败。

1、Producer事务

  • 为了实现跨分区跨会话的事务,需要引入一个全局唯一的Transaction ID,并将Producer获得的PID和Transaction ID绑定。这样当Producer重启后就可以通过正在进行的Transaction ID获得原来的PID。
  • 为了管理Transaction,Kafka引入了一个新的组件Transaction Coordinator。Producer就是通过和Transaction Coordinator交互获得Transaction ID对应的任务状态。Transaction Coordinator还负责将事务所有写入Kafka的一个内部Topic,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行。

2、Consumer事务(精准一次性消费)

  • 上述事务机制主要是从Producer方面考虑,对于Consumer而言,事务的保证就会相对较弱,尤其时无法保证Commit的信息被精确消费。这是由于Consumer可以通过offset访问任意信息,而且不同的Segment File生命周期不同,同一事务的消息可能会出现重启后被删除的情况。
  • 如果想完成Consumer端的精准一次性消费,那么需要kafka消费端将消费过程和提交offset过程做原子绑定。此时我们需要将kafka的offset保存到支持事务的自定义介质中(比如mysql)。

八 Kafka测试

1、启动

//首先启动zookeeper,注意这里为单台节点kafka,所以zookeeper里的zoo.cfg配置的服务映射只能有1个,即只有server.1=hadoopwei:2888:3888
zkServer.sh start

//启动kafka服务,-daemon为后台启动
kafka-server-start.sh -daemon  /opt/kafka/config/server.properties

//创建软链接
ln -s /opt/kafka/config/server.properties /opt/server.properties

//软链接启动
kafka-server-start.sh -daemon /opt/server.properties

2、创建topic

[root@hadoopwei opt]# kafka-topics.sh --create --zookeeper 192.168.198.201:2181 --topic kb09demo --partitions 1 --replication-factor 1
Created topic "kb09demo".

3、创建多个分区数的topic

[root@hadoopwei opt]# kafka-topics.sh --create --zookeeper 192.168.198.201:2181 --topic kb09demo2 --partitions 5 --replication-factor 1
Created topic "kb09demo".
[root@hadoopwei opt]# kafka-topics.sh --zookeeper 192.168.198.201:2181 --topic kb09demo2 --describe                     
Topic:kb09demo2 PartitionCount:5        ReplicationFactor:1     Configs:
        Topic: kb09demo2        Partition: 0    Leader: 0       Replicas: 0     Isr: 0
        Topic: kb09demo2        Partition: 1    Leader: 0       Replicas: 0     Isr: 0
        Topic: kb09demo2        Partition: 2    Leader: 0       Replicas: 0     Isr: 0
        Topic: kb09demo2        Partition: 3    Leader: 0       Replicas: 0     Isr: 0
        Topic: kb09demo2        Partition: 4    Leader: 0       Replicas: 0     Isr: 0

4、修改分区数

[root@hadoopwei opt]# kafka-topics.sh --zookeeper hadoopwei:2181 --alter --topic first --partitions 6

5、查看topic列表

[root@hadoopwei opt]# kafka-topics.sh --zookeeper 192.168.198.201:2181 --list
kb09demo
kb09demo2

6、具体描述topic

[root@hadoopwei opt]# kafka-topics.sh --zookeeper 192.168.198.201:2181 --topic kb09demo --describe
Topic:kb09demo  PartitionCount:1        ReplicationFactor:1     Configs:
        Topic: kb09demo Partition: 0    Leader: 0       Replicas: 0     Isr: 0

7、创建多个副本数的topic

//分区数随便,但是副本数一定要小于等于集群的机器数
[root@hadoopwei opt]# kafka-topics.sh --create --zookeeper 192.168.198.201:2181 --topic kb09demo3 --partitions 5 --replication-factor 2
Error while executing topic command : Replication factor: 2 larger than available brokers: 1.
[2020-12-02 16:23:51,531] ERROR org.apache.kafka.common.errors.InvalidReplicationFactorException: Replication factor: 2 larger than available brokers: 1.
 (kafka.admin.TopicCommand$)

8、删除topic

[root@hadoopwei opt]# kafka-topics.sh --delete --zookeeper 192.168.198.201:2181 --topic kb09demo2
Topic kb09demo2 is marked for deletion.
Note: This will have no impact if delete.topic.enable is not set to true.

9、生产消费实现通信

创建生产者信息

[root@hadoopwei opt]# kafka-console-producer.sh --topic kb09demo --broker-list 192.168.198.201:9092
>hello
>how are you
>thank you
>

另开一个窗口创建消费者信息

[root@hadoopwei ~]# kafka-console-consumer.sh --topic kb09demo --bootstrap-server 192.168.198.201:9092 --from-beginn                                                              ing
hello
how are you
thank you

10、查看kafka的信息储存位置

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值