kafka from--kafka document

一.kafka是什么

ApacheKafka®是一个分布式流媒体平台

流媒体平台有三个关键功能:

  • 发布和订阅记录流,类似于消息队列或企业消息传递系统。
  • 以容错的持久方式存储记录流。
  • 记录发生时处理流。

也可以把他看作一个分布式文件系统       

       由于认真对待存储并允许客户端控制其读取位置,您可以将Kafka视为一种专用于高性能,低延迟提交日志存储,复制和传播的专用分布式文件系统。

二.为什么需要kafka

将数据转为流,可构建实时流数据管道、实时流数据应用程序

因为kafka是一个分布式集群,可以按主题存储记录到多个分区、多个节点,并可配置保留期,所以它有更高的吞吐量,支持多次消费重复数据,多个消费者组消费数据,因为其支持副本备份,所以其支持容错。消费者通过设置消费的偏移量可以从任意地方开始消费数据。

每个分区都有一个领导者和0个或多个跟随者,当一个领导者挂了,支持另外一个跟随者升级为领导者,以实现高可用保证kafka的正常工作。每个服务器都充当其某些分区的领导者和其他服务器的追随者,因此负载在群集中得到很好的平衡。

  • “leader”是负责给定分区的所有读取和写入的节点。每个节点将成为随机选择的分区部分的领导者。
  • “replicas”是复制此分区日志的节点列表,无论它们是否为领导者,或者即使它们当前处于活动状态。
  • “isr”是“同步”复制品的集合。这是副本列表的子集,该列表当前处于活跃状态并且已经被领导者捕获。

三. kafka集群、服务器节点、消费者组、消费者、分区 与数据的关系

四.四大api

生产者api  允许应用程序发布的记录流至一个或多个卡夫卡的话题。

消费者api  允许应用程序订阅一个或多个主题,并处理所产生的对他们记录的数据流。

流api  允许应用程序充当流处理器,从一个或多个主题消耗的输入流,并产生一个输出流至一个或多个输出的主题,有效地变换所述输入流,以输出流。

连接器api  允许构建和运行卡夫卡主题连接到现有的应用程序或数据系统中重用生产者或消费者。例如,关系数据库的连接器可能捕获对表的每个更改。

 

五.生产者新建topic 并设置分区、设置副本的shell命令

让我们创建一个名为“test”的主题,它只包含一个分区,只有一个副本(leader副本):

1

> bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test

如果我们运行list topic命令,我们现在可以看到该主题:

1

2

> bin/kafka-topics.sh --list --zookeeper localhost:2181

test

或者,您也可以将代理配置为在发布不存在的主题时自动创建主题,而不是手动创建主题。

 

 

生产者:生产数据(在内存中以字节的形式存在),然后将字节转为socect(套接字 NIO 节点io通信的最小单元),然后直接将从套接口转移到磁盘上设定好的kafka分区的leader副本中,并记录好offset 。写入kafka分区中的数据是以副本的形式保存的,先写到leader副本,再将leader副本中的数据同步(复制)到follewer副本中,以留作高可用。(leader副本,follewer副本)。(采用dicrectIO通信) (

dicrectIO:是一种NIO(new IO)既不需要经过操作系统缓存,又不需要经过cpu move操作,以0拷贝的方式将数据从内存拉到用户空间的(buffer)磁盘文件上。速度比传统IO快得多 。

采用dicrectIO的组件:kafka,netty通信框架,最新spark io,hadoop io 等分布式组件 。

消费者:dicrectStream 会并行拉取同一个topic 下的多个分区内 的数据,kafka-topic分区和spark 的rdd 中的分区数 是一一对应的;且拉取的数据不进行WAL日志写入;需要手动维护偏移量(以保证kafka broker中的偏移量和rdd中的偏移量的一致性),最新版kafka的偏移量是保存在topic中的(以前是自动保存在zookeeper中的)。

ISR:kafka中总消息副本的子集,若某个topic中有10个副本,ISR为其中5个副本(<=10),则leader副本一定在ISR中,如果leader副本某时刻不可用了,则它会从剩下的4个ISR(foller副本),选一个作为新的leader副本.

每个节点上的每个分区只能有一个副本(要么是leader副本,要么是follewer副本),例如:节点A上有4个分区,则节点A上也只有4个分区副本(有的是leader副本,有的是follewer副本)。

 kafka-topics --zookeeper hadoop1:2181 --create --replication-factor 1 --partition 3 --topic user-behavior-topic

上面这条语句的意思是:在一个kafka broker节点上,创建一个topic,其有3个分区 ,并为每个分区设置副本,因为--replication-factor 1 所以这3个分区只在1个节点上,又因为每个节点上的每个分区只能有一个副本,所以设置的3个分区的副本都是leader副本 (leader副本用来存储生产者发过来的数据,follewer副本是特殊的消费者,从leader副本同步(备份)数据),又因为每个分区只有一个leader副本,在其他节点上没有follewer副本,所以该设置不支持高可用,如果leader副本所在节点挂了,则kafka不能继续正常工作。

将所有分区都放在同一个broker上,设--replication-factor 1 为每个分区创建1个leader副本,不可能在一个节点为1个分区创建两个副本。

如果将所有分区不都放在同一个broker上,如设--replication-factor 2 --partiton 3 ,则在两个broker节点 上分别创建3个分区,每个分区有1个副本,一共6个副本,其中3个leader副本,3个follewer副本(一个leader副本,一个follewer副本),这样设置的好处:保证高可用(一个leader副本挂了,可以自动选举产生另一个leader副本来负责处理producer和consumer请求),是针对有多个broker的情况)

 

应该怎么确定分区?:视情况而定,通过一系列实验和测试来确定,测试的依据是吞吐量(消费者和生产者的吞吐量) n=总目标吞吐量/max(producer吞吐量Tt,consumer吞吐量Tc)   roducer吞吐量consumer吞吐量:通过先创建一个只有1个分区的topic,然后测试求得。Tp的值只需发msg到kafka即可,Tc的值取决于拿到消息后执行什么操作

 

例子:在5个kafka节点上 执行以下命令创建topic:

 kafka-topics --zookeeper hadoop1:2181 --create --replication-factor 2 --partition 3 --topic user-behavior-topic

 

 

 

 

 

 

 

 

 

 

 

由上图可知:

最终在5个节点的其中4个节点创建了6个分区(3个leader分区,3个follewer分区),6个副本(其中3个Leader副本,3个follewer副本) 。(也可以说 创建了3个分区,3个Leader副本,3个follewer副本,每个分区对应一个Leader副本和follewer副本)

在403节点上 有leader分区0和follewer分区2

在287节点上 有leader分区1

在277节点上 有有leader分区2和follewer分区1

在397节点上有follewer分区0

(leader副本和follewer副本分配同上)

创建follewer副本的原因是:

如果leader副本所在节点挂了,可以通过选举(zookeeper分布式锁机制)从1个或多个follewer副本(follewer副本在其他节点上)选举一个,来作为新的leader副本与producer进行通信(存储producer发过来的消息)

 

注意:

副本因子不能大于 Broker 的个数;

第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的;

其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推;

剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的;

 

消费者消费:

1个topic ,3个分区,1个消费者组里有1个消费者:

生产者发送如下数据:1,2,3,4,5,6,7,8,9====》分区1:1,2,3  ;分区2:4,5,6;分区3:7,8,9

这个消费者会 起一个线程同时拉取3个分区的数据,对拉取到的数据只保证分区内是有序的,不同分区没办法保证有序。

消费者拉取结果可能为:1,4,7,2,8,5,9,6,3

1个topic ,3个分区,1个消费者组里有2个消费者:

这2个消费者会分别起一个线程,一个消费者线程拉取一个分区的数据(随机),另一个消费者拉取其他两个分区的数据,一旦开始拉取就会固定下来,比如消费者A消费分区1,消费者B消费消费分区2,3,就会永远保持这样的分区消费者关系。对拉取到的数据只保证分区内是有序的,不同分区没办法保证有序。

消费者拉取结果可能为:

消费者A:1,2,3

消费者B:4,7,8,5,6,9

最佳实践:

1个topic ,3个分区,1个消费者组里有3个消费者:(一个消费者对应一个分区)

消费者拉取结果可能为:

消费者A:4,5,6(对应分区2)

消费者B:1,2,3(对应分区1)

消费者C:7,8,9(对应分区3)

不建议:一个消费者启动多个线程;建议多个消费者,每个消费者只启动一个线程进行消费。

其实这个也是有待商榷的,因为多个消费者,消费时会有多个tcp连接,如果有1000个分区,那将会有1000个tcp连接会

同时创建,会极大的消耗网络I/O,反而1个消费者启动多个线程消费更有优势。

最佳实践:如果需要做实时处理且要保证拉取的数据是顺序的,那么建议:kafka只设一个分区,以保证消费时的顺序和发送到kafka的顺序一致,且在同一个消费者组中只要1个消费者,如果多个则会浪费其他消费者(只会有一个消费者启动一个线程工作);如果不对消费时数据的顺序有要求,只是做一些简单的数据清洗然后入库的话,kafka可以设多个分区(以提高速率,降低数据延迟),具体设多少个分区要看只入kafka单个分区的速率来定,一个消费者组中不管是用一个消费者还是多个消费者,最终启动的线程数最好是要等于kafka的分区个数。(如果只有1个消费者则默认会启动与kafka分区数相等的线程数),每个分区的偏移量都是从0开始的,且消费时只能保证消费到的各个分区内的数据是有序的,消费到的分区之间的数据是无序的。

如果要保证拉取的数据是顺序的:

1.将所有数据只发送到其中一个分区

2.对拉取后的数据重新排序 按:1,2,3,4,5,6,7,8,9的

3.使拉取后的数据保持部分有序,生产者按key放到不同分区,同一个消费者组 建立与分区数一样多的消费者数。

分区分配策略:

1.range:分区排序,消费者排序,按分区数/消费者线程数 分配,且多余的分区会多分配给消费者ABC上(默认策略)

如有10个分区,3个消费者(线程):

消费者A:分区1-4;消费者B:5-7;消费者C:8-10

 

2.roundRobin: 按hash 分区 (适用于有多个key,分区数量过多的情况,因为1没有实现真正的rebalence)

3.一个消费者可以消费多个topic的。

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值