Kafka入门知识总结

Kafka概述

Kafka是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于大数据实时处理领域。

消息队列

在这里插入图片描述
使用消息队列的好处;

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

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

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

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

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

消息队列的两种方式

 (1)点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除)消息生产者生产消息发送到Queue中,然后消息消费者从Queue中取出并且消费消息。消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
 (2)发布/订阅模式(一对多,消费者消费数据之后不会清除消息)消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。

这样的好处是:

  • 支持多个消费者
  • 消费者端决定消费速度,这样的弊端是需要维护一个服务。长轮询监控消息队列是否有消息,这样比较浪费资源。

什么是Kafka?

Kafka是一个分布式的数据流式传输平台。
在流式计算中,Kafka一般用来缓存数据,Spark通过消费Kafka的数据进行计算。

  • Apache Kafka是一个开源消息系统,由Scala写成。是由Apache软件基金会开发的一个开源消息系统项目。
  • Kafka最初是由LinkedIn公司开发,并于2011年初开源。2012年10月从Apache
    Incubator毕业。该项目的目标是为处理实时数据提供一个统一、高通量、低等待的平台。
  • Kafka是一个分布式消息队列。Kafka对消息保存时根据Topic进行归类,发送消息者称为Producer,消息接受者称为Consumer,此外kafka集群有多个kafka实例组成,每个实例(server)称为broker。
  • 无论是kafka集群,还是consumer都依赖于zookeeper集群保存一些meta信息,来保证系统可用性。

Kafka的特点

  • 类似于消息队列和商业的消息系统,kafka提供对流式数据的发布和订阅
  • kafka提供一种持久的容错的方式存储流式数据
  • kafka拥有良好的性能,可以及时地处理流式数据
  • Kafka主要集群方式运行在一个或多个可跨多个数据中心的服务器上
  • Kafka集群将数据按照类别记录存储,这种类别在kafka中称为主题
  • 每条记录由一个键,一个值和一个时间戳组成

核心概念

Broker:一台kafka服务器就是一个broker。一个集群由多个broker组成。
Topic:Topic 就是数据主题,kafka建议根据业务系统将不同的数据存放在不同的topic中!Kafka中的Topics总是多订阅者模式,一个topic可以拥有一个或者多个消费者来订阅它的数据。一个大的Topic可以分布式存储在多个kafka broker中!Topic可以类比为数据库中的库

Partition:每个topic可以有多个分区,通过分区的设计,topic可以不断进行扩展!即一个Topic的多个分区分布式存储在多个broker!
此外通过分区还可以让一个topic被多个consumer进行消费!以达到并行处理!分区可以类比为数据库中的表!
kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序。
Offset:数据会按照时间顺序被不断第追加到分区的一个结构化的commit log中!每个分区中存储的记录都是有序的,且顺序不可变!这个顺序是通过一个称之为offset的id来唯一标识!因此也可以认为offset是有序且不可变的
Producer:消息生产者,就是向kafka broker发消息的客户端。生产者负责将记录分配到topic的指定 partition(分区)中
Consumer:消息消费者,向kafka broker取到消息的客户端。每个消费者都要维护自己读取数据的offset。低版本0.9之前将offset默认保存在Zookeeper中,0.9及之后默认保存在Kafka的“__consumer_offsets”主题中。
Consumer Group :一个topic可以有多个consumer group。topic的消息会复制(不是真的复制,是概念上的)到所有的CG,但每个partion只会把消息发给该CG中的一个consumer。每个消费者都会使用一个消费组名称来进行标识。同一个组中的不同的消费者实例,可以分布在多个进程或多个机器上

kafka的持久化

Kafka 集群保留所有发布的记录—无论他们是否已被消费—并通过一个可配置的参数——保留期限来控制。举个例子, 如果保留策略设置为2天,一条记录发布后两天内,可以随时被消费,两天过后这条记录会被清除并释放磁盘空间。
Kafka的性能和数据大小无关,所以长时间存储数据没有什么问题。

kafka副本机制

日志的分区partition (分布)在Kafka集群的服务器上。每个服务器在处理数据和请求时,共享这些分区。每一个分区都会在已配置的服务器上进行备份,确保容错性。
每个分区都有一台 server 作为 “leader”,零台或者多台server作为 follwers 。leader server 处理一切对 partition (分区)的读写请求,而follwers只需被动的同步leader上的数据。当leader宕机了,followers 中的一台服务器会自动成为新的 leader。通过这种机制,既可以保证数据有多个副本,也实现了一个高可用的机制
基于安全考虑/负载均衡的考虑,每个分区的Leader和follower不会分到一个broker上.

kafka基础架构

在这里插入图片描述

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

在这里插入图片描述
Kafka中消息是以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic的。
topic是逻辑上的概念,而partition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是producer生产的数据。Producer生产的数据会被不断追加到该log文件末端,且每条数据都有自己的offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个offset,以便出错恢复时,从上次的位置继续消费。
在这里插入图片描述
由于生产者生产的消息会不断追加到log文件末尾,为防止log文件过大导致数据定位效率低下,Kafka采取了分片和索引机制,将每个partition分为多个segment。

Kafka生产者

kafka分区
原因

  • 方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;
  • 可以提高并发,因为可以以Partition为单位读写了。
    分区的原则
  • 指明 partition 的情况下,直接将指明的值直接作为 partiton 值;
  • 没有指明 partition 值但有
    key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值;
    既没有 partition 值又没有 key 值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与topic 可用的 partition 总数取余得到 partition 值,也就是常说的 round-robin 算法。

数据可靠性保证

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

  • ISR
    Leader维护了一个动态的in-sync replica set (ISR),意为和leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会给follower发送ack。如果follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms参数设定。Leader发生故障之后,就会从ISR中选举新的leader

  • 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发生故障,那么会造成数据重复。注意,如果isr里面只有一个leader,即便是为1,也可能丢失数据。

故障处理细节

LEO:指的是每个副本最大的offset;
HW:指的是消费者能见到的最大的offset,ISR队列中最小的LEO。
(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同步数据。

Exactly Once语义

  • 最多一次:at most once
  • 最少一次:at least once:
  • 有且仅有一次:exactly once

如果我们使用-1,那么就能保证数据不丢失,但是不能保证数据不重复,如果需要保证有且仅有一次,那么消费者消费数据之后,我们需要开发代码,对数据去重,而且一个topic可以让多个消费者组订阅,每个组在订阅的时候都得做去重…

对于某些比较重要的消息,我们需要保证exactly once语义,即保证每条消息被发送且仅被发送一次。

在0.11版本之后,Kafka Producer引入了幂等性机制(idempotent),配合acks = -1时的at least once语义,实现了producer到broker的exactly once语义

kafka消费者

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

分区分配策略

Kafka有两种分配策略,一是RoundRobin,一是Range。

  • 采用RoundRobin是面向组的,可能导致的问题是,同一个组里面的不同的消费者可以订阅不同的主题,因为是采用轮询的策略,这样配置会导致无效
  • 考虑range是面向主题的,这种策略的问题是可能会导致负载不均。

采用RoundRobin是面向组的,可能导致的问题是,同一个组里面的不同的消费者可以订阅不同的主题,因为是采用轮询的策略,这样配置会导致无效
考虑range是面向主题的,这种策略的问题是可能会导致负载不均。

  • 同一个 Consumer Group 内新增消费者
  • 消费者离开当前所属的Consumer Group,包括shuts down 或 crashes
  • 订阅的主题新增分区

offset的维护(重点)

  • 需要明白offset存放在哪里,在0.9之前offset默认存放在zk,0.9之后默认存放在kafka的主题。
  • offset和消费者没有关系,和消费者组,topic,分区有关系,我们可以假设如果和消费者有关系,我们考虑的是如果消费者挂了,这个offset难道就丢失或者改变了吗,这样显然不合理,也就是当这个消费者挂了之后,给消费者组重新分区,这个分区可能会分到新的消费者,但是会继续从这个offset之后继续分区。

Kafka 高效读写数据

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

Zookeeper在Kafka中的作用

Kafka集群中有一个broker会被选举为Controller,选举的机制就是抢占资源,谁先启动谁就是Controller,负责管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作。
Controller的管理工作都是依赖于Zookeeper的

Kafka的API

Producer API

消息发送流程
Kafka的Producer发送消息采用的是异步发送的方式。在消息发送的过程中,涉及到了两个线程——main线程和Sender线程,以及一个线程共享变量——RecordAccumulator。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka broker。
相关参数:

  • batch.size:只有数据积累到batch.size之后,sender才会发送数据。
  • linger.ms:如果数据迟迟未达到batch.size,sender等待linger.time之后就会发送数据。

Consumer API

Consumer消费数据时的可靠性是很容易保证的,因为数据在Kafka中是持久化的,故不用担心数据丢失问题。
由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置的继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费。
所以offset的维护是Consumer消费数据是必须考虑的问题

猜你喜欢

转载自blog.csdn.net/Poolweet_/article/details/109246515
今日推荐