资讯专栏INFORMATION COLUMN

kafka

Half / 3507人阅读

摘要:生产者和消费者生产者将数据发布到他们选择的。如果领导者失败,其中一个粉丝将自动成为新的领导者。每过,消费者会自动把从方法接收的最大提交上去。在回应之前一直阻塞,限制了应用程序的吞吐量。只有同步的才能在当前宕机时被选定为新的。

该博客迁移到github:https://github.com/dackh/blog
基础架构及术语

主题和分区

topic是发布记录的类别或订阅源名称。 Kafka的topic总是多用户; 也就是说,一个主题可以有零个,一个或多个消费者订阅写入它的数据。

对于每个主题,Kafka群集都维护一个如下所示的分区日志:

每个分区都是一个有序的,不可变的记录序列,不断附加到结构化的提交日志中。 分区中的记录每个都分配了一个称为offset的顺序ID号,它唯一地标识分区中的每个记录。

Kafka集群持久保存所有已发布的记录 - 无论是否已使用 - 使用可配置的保留期。 例如,如果保留策略设置为两天,则在发布记录后的两天内,它可供使用,之后将被丢弃以释放空间。 Kafka的性能在数据大小方面实际上是恒定的,因此长时间存储数据不是问题。

实际上,基于每个消费者保留的唯一元数据是该消费者在日志中的偏移或位置。 这种偏移由消费者控制:通常消费者在读取记录时会线性地提高其偏移量,但事实上,由于该位置由消费者控制,因此它可以按照自己喜欢的任何顺序消费记录。 例如,消费者可以重置为较旧的偏移量来重新处理过去的数据,或者跳到最近的记录并从“现在”开始消费。(offset由comsumer决定,comsumer可以决定offset的数据)。

生产者和消费者

生产者将数据发布到他们选择的topic。 生产者负责选择分配给topic中哪个partition的记录。 这可以以round-robin方式完成,仅仅是为了balance load,或者可以根据一些语义分区功能(例如基于记录中的某些键)来完成。

消费者使用消费者组名称标记自己,并且发布到主题的每个记录被传递到每个订阅消费者组中的一个消费者实例。 消费者实例可以在不同的进程中,也可以在不同的机器。

如果所有使用者实例具有相同的使用者组,则记录将有效地在使用者实例上进行负载平衡。

如果所有消费者实例具有不同的消费者组,则每个记录将广播到所有消费者进程。

broker和集群

一个独立的Kafka服务器被称为broker,broker是集群的组成部分,每个集群都有一个broker充当了集群控制者的角色(自动从集群活跃成员中选举出来),控制者负责管理工作,包括将分区分配给broker和监控broker。

容错

日志的分区分布在Kafka集群中的服务器上,每个服务器处理数据并请求分区的共享。 每个分区都在可配置数量的服务器上进行复制,以实现容错。(多个服务器保存partition数据,实现容错)

每个分区都有一个服务器充当“领导者”,零个或多个服务器充当“追随者”。 领导者处理分区的所有读取和写入请求,而关注者被动地复制领导者。 如果领导者失败,其中一个粉丝将自动成为新的领导者。 每个服务器都充当其某些分区的领导者和其他服务器的追随者,因此负载在群集中得到很好的平衡。(高性能实现)

再均衡

在kafka中,当消费者发生崩溃或者有新的消费者加入时,将会触发再均衡

消费者会像叫做_consumer_offset的特殊主题发送消息,消息内包含灭个分区的偏移量。

再均衡之后,消费者可能分配到新的分区,为了能够继续之前的工作,消费者需要读取每个分区最后一次提交的offset,但如果提交的offset小于客户端处理的最后一个offset,那么消息将会被重复处理。

KafkaConsumer API提供了很多种方式来提交偏移量。

自动提交

最简单的提交方式,将enable.auto.commit设为true,提交时间为auto.commit.interval.ms设置的值,默认为5s。每过5s,消费者会自动把从poll()方法接收的最大offset提交上去。

这种方式虽然简单,但是并没有避免重复处理消息的问题。(在5s内发生再均衡)

提交当前offset

消费者API提供了另一种提交偏移量的方式,开发者可以在必要的时候提交当前的偏移量而不是基于时间间隔。通过调用commitSync()或者commitAsync()方法进行提交。

commitSync()在broker回应之前一直阻塞,限制了应用程序的吞吐量。

commitAsync()是异步提交的方式,但是commitAsync()无法保证一定成功,commitSync()在成功提交或者遇到无法恢复的错误之前会一直重试,但是commitAsync()不会。之所以不进行重试是因为它收到响应之前可能另一个更大的offset提交成功了。commitAsync同时也支持回调。

集群成员之间的关系

kafka通过zookeeper来维护集群成员之间的关系,每个broker都有一个唯一标识符,这个标识符可以配置里指定,也可以自动生成。在broker启动的时候,通过创建zookeeper的临时节点把自己的ID注册到zookeeper。kafka组件订阅zookeeper的/brokers/ids路径,当有broker加入集群或者退出集群时,这个组件就会获得通知。

在broker停机、出现网络分区或长时间垃圾回收停顿时,broker会从zookeeper上断开连接,此时broker在启动时创建的临时节点会自动从zookeeper移除,监听broker列表的kafka组件会被告知该broker已移除。

在broker关闭之后,它的节点会消息,但是ID会继续存在于其他数据结构中,在之后如果使用相同ID启动一个全新的broker,它会立刻加入集群并且拥有与旧broker相同的分区和主题。

控制器

控制器也是broker,同时还负责分区首领的选举。集群中第一个启动的broker通过在zookeeper里创建一个临时节点/controller让自己成为控制器。其他节点在该节点上创建watch对象,通过这种方式确保集群里只有一个控制器存在。

如果控制器断开连接,其他监听的节点收到变更通知之后将会尝试创建controller节点成为控制器,只有第一个创建成功的才能成为控制器。

分区复制

kafka中的每个分区都有多个副本,这些副本保存在broker中,副本可以分为:

首领副本(leader):所有生产者消费者请求都会经过这个副本。

跟随者副本(follower):从首领复制消息,保持与首领一致。

leader通过查看每个follower请求的最新offset了解follower进度,如果follower在10s(通过replica.lag.time.max.ms配值)内没有请求最新消息,那么它被认为不同步。只有同步的follower才能在当前leader宕机时被选定为新的leader。

每个分区都会有一个首选leader——创建主题时选定的首领就是分区的首选首领,默认情况下,kafka的auto.leader.rebalance.enable被设为true,它会检查首选首领是不是当前首领,如果不是,并且该副本同步,那么就会触发首领选举,让首选首领成为当前首领。

幂等性

为了实现Producer的幂等性,kafka引入了Producer ID(即PID)和Sequence Number

PID

每个producer在初始化的时候都会被分配一个唯一的PID,这个PID对应用透明,完全没有暴露给用户,对于一个给定的PID,sequence number将会从0开始自增,每个topic-partition都会有一个独立的sequence number,producer在发送数据时,将会给msg标识一个sequence number,Server也就是通过这个验证数据是否重复,这里的PID是全局唯一,producer故障后重新启动后会被分配一个新的PID,这也是幂等性无法做到夸会话的一个原因。

Sequence Number

有PID之后,在PID+topic-partition级别上添加一个sequence numbers信息,就可以实现producer的幂等性。

幂等性前后对比

持久化

kafka很大程度上依赖文件系统来存储和缓存消息,有一普遍的认识:磁盘很慢。但是其实顺序的磁盘读写比任意内存读写都快。

基于JVM内存有一下缺点:

对象的内存开销很大,通常会让存储数据的大小加倍

随着堆内数据的增加,GC的速度越来越慢,而且可能导致错误

基于OS的文件系统设计有一下好处:

可以通过os的pagecache来有效利用主内存空间,由于数据紧凑,可以cache大量数据,并且没有gc的压力

即使服务重启,缓存中的数据也是热的(不需要预热)。而基于进程的缓存,需要程序进行预热,而且会消耗很长的时间。(10G大概需要10分钟)

大大简化了代码。因为在缓存和文件系统之间保持一致性的所有逻辑都在OS中。以上建议和设计使得代码实现起来十分简单,不需要尽力想办法去维护内存中的数据,数据会立即写入磁盘。

数据持久化

发现线性的访问磁盘(即:按顺序的访问磁盘),很多时候比随机的内存访问快得多,而且有利于持久化

传统的使用内存做为磁盘的缓存

Kafka直接将数据写入到日志文件中,以追加的形式写入

日志数据持久化

写操作:通过将数据追加到文件中实现

读操作:读的时候从文件中读就好了

优势

读操作不会阻塞写操作和其他操作(因为读和写都是追加的形式,都是顺序的,不会乱,所以不会发生阻塞),数据大小不对性能产生影响;

没有容量限制(相对于内存来说)的硬盘空间建立消息系统;

线性访问磁盘,速度快,可以保存任意一段时间!

kafka为什么这么快

为什么kafka那么快

什么是Zero-Copy?

Kafka副本同步机制理解

Kafka深度解析

参考

kafka权威指南

http://kafka.apache.org/intro

Kafka的内部机制深入(持久化,分布式,通讯协议)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/34015.html

相关文章

  • Kafka集群部署指南

    摘要:另外,也是目前性能最好的消息中间件。架构在集群中,一个节点就是一个,消息由来承载,可以存储在个或多个中。发布消息的应用为消费消息的应用为,多个可以促成共同消费一个中的消息。 一、前言 1、Kafka简介 Kafka是一个开源的分布式消息引擎/消息中间件,同时Kafka也是一个流处理平台。Kakfa支持以发布/订阅的方式在应用间传递消息,同时并基于消息功能添加了Kafka Connect...

    qc1iu 评论0 收藏0
  • 在Ubuntu机器上部署Kafka消息队列

    摘要:在机器上部署消息队列步骤安装依赖安装配置启动和停止测试依赖安装配置文件在目录下如果是单机不需要额外配置,有多个请配置地址。使用两个不同终端消费终端发布终端发布终端的输出没有这个,会自动创建一个。消费终端的输出收到消息了。 在Ubuntu机器上部署Kafka消息队列 步骤 安装依赖 ZooKeeper 安装Kafka 配置Kafka 启动和停止Kafka 测试Kafka 1 依赖: ...

    Euphoria 评论0 收藏0
  • 搭建高吞吐量 Kafka 分布式发布订阅消息 集群

    摘要:搭建高吞吐量分布式发布订阅消息集群简介是一种高吞吐的分布式发布订阅消息系统,能够替代传统的消息队列用于解耦合数据处理,缓存未处理消息等,同时具有更高的吞吐率,支持分区多副本冗余,因此被广泛用于大规模消息数据处理应用。 搭建高吞吐量 Kafka 分布式发布订阅消息 集群 简介 Kafka 是一种高吞吐的分布式发布订阅消息系统,能够替代传统的消息队列用于解耦合数据处理,缓存未处理消息等,同...

    toddmark 评论0 收藏0
  • Kafka 权威指南】初识 Kafka

    摘要:生产者创建消息的主体。消费组中的消费者和主题中的分区的队列关系,被称为消费者所有权。如根据消息的大小达到特定大小后失效根据时间指定时间后过期配置。借助进行消息序列化,能够做到大规模的消息处理。 发布-订阅模型 通过发布-订阅模型,各个子模块之间做到解耦。各个子模块只需要知道自己需要往中间件——Kafka 里取值还是存值即可。简单的抽象模型如下图所示: showImg(https://s...

    printempw 评论0 收藏0
  • spring for kafka自动配置及配置属性

    摘要:序本文主要列一下的一些以及属性配置这个版本使用的是版本使用的是版本几个关键配置类配置属性公共配置配置属性配置 序 本文主要列一下spring for apache kafka的一些auto config以及属性配置 maven org.springframework.kafka spring-kafka 1.2.3.RELEASE 这个版本使用的是kafka clien...

    Hancock_Xu 评论0 收藏0
  • kafka docker

    摘要:基本概念介绍可以简单理解为一个节点多个节点构成整个集群某种类型的消息的合集它是在物理上的分组多个会被分散地存储在不同的节点上单个的消息是保证有序的但整个的消息就不一定是有序的包含消息内容的指定大小的文件由文件和文件组成一个由多个文件组成文件 基本概念介绍 Broker 可以简单理解为一个 Kafka 节点, 多个 Broker 节点构成整个 Kafka 集群;Topic 某种类型的消息...

    Towers 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<