
Kafka到底是个啥?用来干嘛的?
官方定义如下:
翻译过来,大致的意思就是,这是一个实时数据处理系统,可以横向扩展,并高可靠!
实时数据处理 ,从名字上看,很好理解,就是将数据进行实时处理,在现在流行的微服务开发中,最常用实时数据处理平台有 RabbitMQ、RocketMQ 等消息中间件。
这些中间件,最大的特点主要有两个:
在早期的 web 应用程序开发中,当请求量突然上来了时候,我们会将要处理的数据推送到一个队列通道中,然后另起一个线程来不断轮训拉取队列中的数据,从而加快程序的运行效率。
但是随着请求量不断的增大,并且队列通道的数据一致处于高负载,在这种情况下,应用程序的内存占用率会非常高,稍有不慎,会出现内存不足,造成程序内存溢出,从而导致服务不可用。
随着业务量的不断扩张,在一个应用程序内,使用这种模式已然无法满足需求,因此之后,就诞生了各种消息中间件,例如 ActiveMQ、RabbitMQ、RocketMQ等中间件。
采用这种模型,本质就是将要推送的数据,不在存放在当前应用程序的内存中,而是将数据存放到另一个专门负责数据处理的应用程序中,从而实现服务解耦。
消息中间件 :主要的职责就是保证能接受到消息,并将消息存储到磁盘,即使其他服务都挂了,数据也不会丢失,同时还可以对数据消费情况做好监控工作。
应用程序 :只需要将消息推送到消息中间件,然后启用一个线程来不断从消息中间件中拉取数据,进行消费确认即可!
引入消息中间件之后,整个服务开发会变得更加简单,各负其责。
Kafka 本质其实也是消息中间件的一种,Kafka 出自于 LinkedIn 公司,与 2010 年开源到 github。
LinkedIn 的开发团队,为了解决数据管道问题,起初采用了 ActiveMQ 来进行数据交换,大约是在 2010 年前后,那时的 ActiveMQ 还远远无法满足 LinkedIn 对数据传递系统的要求,经常由于各种缺陷而导致消息阻塞或者服务无法正常访问,为了能够解决这个问题,LinkedIn 决定研发自己的消息传递系统, Kafka 由此诞生 。
在 LinkedIn 公司,Kafka 可以有效地处理每天数十亿条消息的指标和用户活动跟踪,其强大的处理能力,已经被业界所认可,并成为大数据流水线的首选技术。
先来看一张图, 下面这张图就是 kafka 生产与消费的核心架构模型 !
如果你看不懂这些概念没关系,我会带着大家一起梳理一遍!
简而言之,kafka 本质就是一个消息系统,与大多数的消息系统一样,主要的特点如下:
与 ActiveMQ、RabbitMQ、RocketMQ 不同的地方在于,它有一个分区 Partition 的概念。
这个分区的意思就是说,如果你创建的 topic 有5个分区,当你一次性向 kafka 中推 1000 条数据时,这 1000 条数据默认会分配到 5 个分区中,其中每个分区存储 200 条数据。
这样做的目的,就是方便消费者从不同的分区拉取数据,假如你启动 5 个线程同时拉取数据,每个线程拉取一个分区,消费速度会非常非常快!
这是 kafka 与其他的消息系统最大的不同!
和其他的中间件一样,kafka 每次发送数据都是向 Leader 分区发送数据,并顺序写入到磁盘,然后 Leader 分区会将数据同步到各个从分区 Follower ,即使主分区挂了,也不会影响服务的正常运行。
那 kafka 是如何将数据写入到对应的分区呢?kafka中有以下几个原则:
与生产者一样,消费者主动的去kafka集群拉取消息时,也是从 Leader 分区去拉取数据。
这里我们需要重点了解一个名词: 消费组 !
考虑到多个消费者的场景,kafka 在设计的时候,可以由多个消费者组成一个消费组,同一个消费组者的消费者可以消费同一个 topic 下不同分区的数据,同一个分区只会被一个消费组内的某个消费者所消费,防止出现重复消费的问题!
但是不同的组,可以消费同一个分区的数据!
你可以这样理解,一个消费组就是一个客户端,一个客户端可以由很多个消费者组成,以便加快消息的消费能力。
但是,如果一个组下的消费者数量大于分区数量,就会出现很多的消费者闲置。
如果分区数量大于一个组下的消费者数量,会出现一个消费者负责多个分区的消费,会出现消费性能不均衡的情况。
因此,在实际的应用中,建议消费者组的 consumer 的数量与 partition 的数量保持一致!
光说理论可没用,下面我们就以 centos7 为例,介绍一下 kafka 的安装和使用。
kafka 需要 zookeeper 来保存服务实例的元信息,因此在安装 kafka 之前,我们需要先安装 zookeeper。
zookeeper 安装环境依赖于 jdk,因此我们需要事先安装 jdk
下载zookeeper,并解压文件包
创建数据、日志目录
配置zookeeper
重新配置 dataDir 和 dataLogDir 的存储路径
最后,启动 Zookeeper 服务
到官网 >
回顾 kafka极简入门(二)--安装
topic是kafka的生产者和消费者最小交互的单位,我们先从topic入手,创建第一个topic
或
所以执行上面命令将会创建一个名为mytest的topic,该topic下面有1个分区,并且该分区只有1个副本。
PS:除了手动创建主题外,还可以将代理配置为在发布不存在的主题时自动创建主题
Partition:0 表示该分区的id为0
leader: 9 表示分区的首领副本所在的broker(本例子中brokerid配置为9,所以这里显示9,具体在config/serverproperties配置。这里只有一个分区,所以首领分区也就是自己)
Replicas: 9 表示分区的跟随副本所在的broker
Isr: 9 表示分区的同步副本所在的broker(同步副本可以认为跟首领副本准实时同步的副本,可以配置判断条件,后面会讲,首领副本挂掉后,服务器会从同步副本中选举新的首领)
发送三个消息,分别是hello, world和!
注意: --from-beginning 表示从最开始的offset处开始消费。如果不写表示从最新的offset处消费,那么先发送了消息再开启消费者是收不到已发送的信息的
在章节二( >
kafka是一个高性能、低延迟的分布式发布-订阅消息系统,适用于在线、离线消息消费,为了防止数据丢失,kafka将消息持久化到磁盘上并在集群内复制
在深入了解kafka之前,先介绍kafka体系架构中的一些组件,包括Topic、Producer、Consumer、Consumer Group、Broker、Partition、Leader、Follower。
Topic
消息被发送到kafak中都有一个类别,这个类别叫做Topic,kafka中的消息都是通过主题进行组织的,一个Topic可以有1个或多个Partition。
Producer
生产者,即是将消息发送到kafka的过程,发送消息是需要指定Topic,并且可以指定Partition。Broker接收到消息后,将消息存放在partition中。
Consumer
消费者,从broker topic中读取消息,可以订阅一个或多个topic。
Consumer Group
消费者组由一个或多个消费者组成,消费者组中的消费者共同消费一个主题的分区,主题中每个分区只能被同一个消费者组中的一个消费者消费。
Broker
kafka集群包括一个或多个节点,每个节点就叫做Broker。
Partition
Topic中的数据可以分割为一个或多个Partition,Partition在底层逻辑是log文件,每个Partition由多个Segment组成,任何发送到kafka的消息最终都是会被追加到log文件的尾部。
Leader
Topic的Partition允许有若干个副本,每个分区都一个leader和多个follower,leader负责所有的读写 *** 作。
Follower
Follower追随Leader,所有的读写请求都是通过Leader路由,请求会广播给所有的Follower,Follower和Leader保持数据同步。如果Leader失效,通过Follower选举一个新的Leader
下面通过一张简单的UML图简要说明组件之间的交互和关联关系
主要关系说明如下
- kafka集群可以有1个或多个Broker
- Broker 可以包含多个副本(每个分区可以包含多个副本,通常每个分区副本数不会多于Broker数量,一个broker中包含很多个分区)
- Topic可以有1个或多个分区
- broker中的每个partition可以有0个或1个副本
- 一个partition有一个leader副本和0个或多个follower副本
- partition的每个副本都必须位于单独的broker上
- 每个partition副本位于一个broker上,并且一个partition不能划分多个broker。
Kafka架构
下面重点介绍Producer、Topic、Consumer的关系,一个简单生产消费的过程例子如下图所示
在这个例子中,一个生产者将消息发送给单个topic
上面这个图中,1个生产者发布消息到1个topic,一个消费者消费1个Topic,如上图中的Producer 1和Consumer 1;一个Topic可以是由多个生产者发布消息,如Topic4;1个消费者可以消费多个Topic,如图中的Consumer 2。
如上图的例子,一个生产者可以给多个Topic发布消息。一个消费者同一时间只能给一个topic发布消息,但是可以使用异步发布消息,生产者可以一次将多个消息发送给多个Topic
生产者负责将每条消息发送到分区,默认分区由消息key通过hash算法确定,如果没有指定消息key,则通过循环轮询来确定分区。但是在实际业务场景中,默认的分区行为并不能满足业务需要,比如需要确保消息的顺序或需要将消息平均分配给消费者等等。因此,生产者在发布消息的时候可以使用自定义分区方式,为消息指定分区key、重写分区算法或手动设置分区等方式将消息发布到特定分区。
kafka内部运作的基本逻辑大概为:每个主题都有1个或多个分区,这些分区分不在1个或多个Broker上,为了提高消息的可靠性不会丢失,可以配置多个副本因子,这样每个分区可以被复制到一个或多个Broker上,每个分区对应一个log文件,只能被一个消费组中的一个消费者消费,用于提高Topic的并发性。因此一般将消费组消费者数量设置为小于或者等于topic的分区数量,如果要增加消费者也相应的增加对应的分区数量。
同一个分区内的消息是由顺序的,每个分区仅能被同一个消费组中的一个消费者顺序消费。但是,当多个消费组订阅了同一个topic,则每个组中的消费者都会收到消息。
下面例子说明多分区情况下,消费者组和消费者消费的几种情况。
分区数和消费者数相同,如下图所示
这种情况,同一个消费组的每个消费者只消费一个分区。
另外一种情况,消费组中的消费者数量多于分区数,如下图所示
消费者数量多于分区数,则某些消费者就处于空闲状态,当有消费者down掉或添加新的分区情况时,空闲消费者将发挥作用。
另外一种情况,消费者数比分区数少,如下图所示
这种情况,导致某些分区需要负责更多的分区,处理更多的消息。
最后,多个消费组消费了同一个topic
topic消息被广播到每个消费组,每个消费组都可以接受同一个消息。这是kafka实现一个Topic广播的方式,一个Topic可以被多个Conumse Group的消费者同时消费;同一个消息只能被一个消费者组中的一个消费者消费。
如何决定kafka集群中topic,partition的数量,这是许多kafka用户经常遇到的问题。本文列举阐述几个重要的决定因素,以提供一些参考。
分区多吞吐量更高
一个话题topic的各个分区partiton之间是并行的。在producer和broker方面,写不同的分区是完全并行的。因此一些昂贵的 *** 作比如压缩,可以获得更多的资源,因为有多个进程。在consumer方面,一个分区的数据可以由一个consumer线程在拉去数据。分区多,并行的consumer(同一个消费组)也可以多。因此通常,分区越多吞吐量越高。
基于吞吐量可以获得一个粗略的计算公式。先测量得到在只有一个分区的情况下,Producer的吞吐量(P)和Consumer的吞吐量(C)。那如果总的目标吞吐量是T的话,max(T/P,T/C)就是需要的最小分区数。在单分区的情况下,Producer的吞吐量可以通过一些配置参数,比如bath的大小、副本的数量、压缩格式、ack类型来测得。而Consumer的吞吐量通常取决于应用程序处理每一天消息逻辑。这些都是需要切合实际测量。
随着时间推移数据量的增长可能会需要增加分区。有一点需要注意的是,Producer者发布消息通过key取哈希后映射分发到一个指定的分区,当分区数发生变化后,会带来key和分区映射关系发生变化。可能某些应用程序依赖key和分区映射关系,映射关系变化了,程序就需要做相应的调整。为了避免这种key和分区关系带来的应用程序修改。所以在分区的时候尽量提前考虑,未来一年或两年的对分区数据量的要求。
除了吞吐量,还有一些其他的因素,在定分区的数目时是值得考虑的。在某些情况下,太多的分区也可能会产生负面影响。
分区多需要的打开的文件句柄也多
每个分区都映射到broker上的一个目录,每个log片段都会有两个文件(一个是索引文件,另一个是实际的数据文件)。分区越多所需要的文件句柄也就越多,可以通过配置 *** 作系统的参数增加打开文件句柄数。
分区多增加了不可用风险
kafka支持主备复制,具备更高的可用性和持久性。一个分区(partition)可以有多个副本,这些副本保存在不同的broker上。每个分区的副本中都会有一个作为Leader。当一个broker失败时,Leader在这台broker上的分区都会变得不可用,kafka会自动移除Leader,再其他副本中选一个作为新的Leader。Producer和Consumer都只会与Leader相连。
一般情况下,当一个broker被正常关机时,controller主动地将Leader从正在关机的broker上移除。移动一个Leader只需要几毫秒。然当broker出现异常导致关机时,不可用会与分区数成正比。假设一个boker上有2000个分区,每个分区有2个副本,那这样一个boker大约有1000个Leader,当boker异常宕机,会同时有1000个分区变得不可用。假设恢复一个分区需要5ms,1000个分区就要5s。
分区越多,在broker异常宕机的情况,恢复所需时间会越长,不可用风险会增加。
分区多会增加点到点的延迟
这个延迟需要体现在两个boker间主备数据同步。在默认情况下,两个boker只有一个线程负责数据的复制。
根据经验,每个boker上的分区限制在100br内(b指集群内boker的数量,r指副本数量)。
分区多会增加客户端的内存消耗
kafka082后有个比较好的特色,新的Producer可以允许用户设置一个缓冲区,缓存一定量的数据。当缓冲区数据到达设定量或者到时间,数据会从缓存区删除发往broker。如果分区很多,每个分区都缓存一定量的数据量在缓冲区,很可能会占用大量的内存,甚至超过系统内存。
Consumer也存在同样的问题,会从每个分区拉一批数据回来,分区越多,所需内存也就越大。
根据经验,应该给每个分区分配至少几十KB的内存。
以上就是关于3分钟带你彻底搞懂 Kafka全部的内容,包括:3分钟带你彻底搞懂 Kafka、如何获取kafka某一topic中最新的offset、kafka极简入门(三)--创建topic等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)