kafka中文文档(0.10.0)

来源:互联网 发布:私募排排网数据申报 编辑:程序博客网 时间:2024/06/02 02:07

kafka中文文档(0.10.0)


作者:链上研发-老杨叔叔
时间:2016-07-22
版本:Apache Kafka 0.10.0 (2016年5月底发布)

.目录

  • kafka中文文档0100
  • 目录
  • 相关资料
  • 入门
    • 1 介绍
      • 主题和日志
      • 分布式
      • 生产者
      • 消费者
      • 保证此处翻译偏差较大待重新翻译
    • 2 使用案例
      • 消息处理
      • 网站活动跟踪
      • 度量
      • 日志收集
      • 流处理
      • Event Sourcing
      • 提交日志
    • 3 快速开始
      • 步骤1 下载代码
      • 步骤2 启动服务
      • 步骤3 创建一个主题
      • 步骤4 发送消息
      • 步骤5 启动消费者
      • 步骤6 设置服务器集群
      • 步骤7 使用kafka connect 导入导出数据
    • 4 生态
    • 5 版本升级
  • API
    • 1 生产者api
    • 2 消费者api
      • 22 Old Simple Consumer API
      • 23 新版消费者 Api
    • 3 streams api
  • 配置
    • 1 代理broker服务器配置
      • 最核心最必须最基础的配置如下
    • 2 生产者producer配置
    • 3 消费者consumer配置
      • 31 旧版消费者配置
      • 32 新版消费者配置
    • 4 kafka Connect 配置
  • 设计
    • 1 动机
    • 2 持久化
      • 恒定的时间复杂度
    • 3 效率
      • 点到点的批量压缩
    • 4 生成者
      • 负载均衡
      • 异步发送
    • 5 消费者
      • 推送 vs 拉取
      • 消费者位置
      • 离线数据加载
    • 6 消息传递语义
    • 7 复制
      • 不纯洁的leader选举如果所有副本都失效了怎么办
      • 可用性和持久性
      • 副本管理
    • 8 日志压缩
    • 9 配额限额
  • 实现
    • 1 api 设计
      • 生产者APIs
      • Consumer APIs
    • 2 网络层
    • 3 消息
    • 4 消息格式
    • 5 日志
    • 6 分布
  • 操作
    • 1 kafka基本操作
      • 平滑关闭
      • 通过机架平衡副本机架就是机房中的机架01000版本新增加了机架感知功能
      • 管理消费者组
    • 2 数据中心
    • 3 重要配置
    • 4 java版本
    • 5 硬件和操作系统
    • 6 监控
    • 7 zookeeper
  • 安全
    • 1 安全概述
    • 2 Encryption and Authentication using SSL
    • 3 Authentication using SASL
    • 4 Authorization and ACLs
    • 5 Incorporating Security Features in a Running Cluster
    • 6 ZooKeeper Authentication
      • New Clusters
      • Migrating Clusters
      • Migrating the ZooKeeper Ensemble
  • kafka Connect
    • 1 概述
    • 2 用户指南
    • 3 Connector开发指南
  • kafka Streams
    • 1 概述
    • 2 开发者指南
      • 核心概念
      • Low-Level Processor API
      • High-Level Streams DSL

英文版

api doc

0.相关资料

代理服务器集群搭建

环境搭建另一

各种MQ比较

1.入门

  • 1.1 介绍

    Kafka是分布式、分区、可复制的提交日志服务。它采用独特的设计来实现消息服务系统。

    这意味着什么呢?

    首先,让我们回顾一些基本的消息传递术语:

    • 主题:维护的一组消息分类;
    • 生产者:向kafka的主题中发布消息
    • 消费者:订阅并消费主题中的消息
    • 代理:kafka集群由一个或多个服务端组成。每个服务端称为代理

    因此,生产者通过网络发送消息给kafka集群,同时,kafka集群把消息转发给消费者,如下:

    结构图

    客户和服务器之间的通信是通过一个简单的、高性能的、语言无关的TCP协议。我们不仅提供java 客户端,同时提供其它多种语言版本的客户端

    主题和日志

    一个主题就是一个用来发布消息的目录或订阅的名字,对于每个topic,Kafka维护一个分区日志,看起来如下
    主题结构图

    每个分区是一个有序的,可以不断追加消息的消息序列。分区中的每个消息都会分配一个在分区内是唯一的序列号,这个序列号叫做偏移量(offset)。

    kafka集群保留所有已经发布的消息(无论这些消息是否已经被消费)一段时间。我们可以配置这个时间来决定集群维护消息的时间长短。比如:如果消息被设置保存两天,那么两天内,消息都是可以被消费的。但是两天后为了节省磁盘空间就会删除消息。

    kafka性能对数据大小不敏感,因此保留大量数据毫无压力。

    事实上,每个消费者仅仅需要保存的元数据是消费者在日志中的消费位置(偏移量),这个偏移量是由消费者控制:通常,消费者读取消息后会线性递增偏移量,但是,消费者可以按任意顺序消费消息。比如:消费者可以重置偏移量到老版本。

    以上特性的组合使得consumer的代价很小。consumer数量可以增加或减少而对整个集群影响很小。例如:略。

    日志分区的目的:第一:允许日志规模超出一台服务器的文件大小限止。每个单独的分区都必须受限于主机的文件限止,但一个主题可有多个分区,因此可以处理无限数量的数据。

    分布式

    日志的所有有分区被分发到集群中的服务器上,每个服务器处理全部分区中的部分分区数据和请求。为了容错,每个分区都被复制到一定数量(可配置)的不同服务器上。

    每个分区(有多个副本)都有一台服务器作为“leader”,大于等于0台服务器做为”followers”。”leader”服务器处理分区的所有读写操作。”followers”服务器对当前分区做为旁观者,什么都不做。当”leader”服务器不可用时,那么”followers”中的一台将自动成为”leader”。每台服务器都即做为一些分区的”leader”,又做为其它分区的“followers”。

    生产者

    生产者向所选的主题发布数据。生产者负责选择哪些消息应该分配到主题内的哪个分区。这种选择分区方式,可以使用简单的循环方式负载均衡; 也可以通过一些语义分区函数实现(如:基于消息的key的hash等)

    消费者

    传统的消息处理有两种模型:队列和发布订阅。队列模式,消费者池中的消费者可以从一台服务器读数据,并且每个消息只被其中一个消费者消费。发布订阅模式,消息通过广播方式发送给所有消费者。kafka提供了一个单一的抽象概念,可以满足这两种(队列、发布订阅)模式--消费者组。

    消费者通过分组名标识自己,每条消息被发布到主题,并只会分发给消费者组中的 唯一个 消费者实例(即只被组中的一个消费者消费)。这些消费者即可以是同一台服务器上不同的进程,也可以是位于不同服务器上进程。

    如果所有的消费者实例属于同一分组(相同的分组名),那么这就是传统的队列模式(相同topic,只有一个消费者能抢到消息)。

    如果所有的消费者实例不属于同一分组,那么这就是发布订阅模式(每个消费者都能收到消息)

    通常,主题有少量称为逻辑订阅者的分组。为了可扩展性和容错每个分组是由许多消费者实例组成。

    kafka 也比传统消息系统拥有更强的顺序性。

    传统队列维护消息顺序性。如果多个消费者从队列中消费消息,那么服务器以存储的顺序分发消息。虽然消息从服务器出队列是按顺序的,但是被分发给消费者时,是通过异步的方式,因此消息到达不同消费者时可能是乱序的。这意味者并发消费时,消费是乱序的。消息系统为了做到这点,会采用只有一个消费者消费的理念,但这也意味是无法并行操作。

    kafka这点做的更好,通过称为分区(主题内)的并行概念,kafka即可以提供顺序又可以负载均衡。这是通过给主题内的相同分组下的消费者提供多个分区的架构,来实现每个分区只能被一个消费者消费。通过这种方式,可以确保同一分区只有一个消费者,因此一个分区消费消息是顺序的; 同时,由于有多个分区,因此可以负载均衡。注意:一个分组内,消费者数量不能多于分区数量。此处的:不能多于,应该不绝对。即:一个应用集群(有消费者)可能远远多于分区数量,只能说超出的消费者永远都无分区消费,但并不影响其它消费者正常使用(我瞎猜的,需要确认-todo)

    kafka仅仅支持分区内的消息顺序消费,并不支持全局(同一主题的不同分区之间)的消息顺序。这处方式下,通过按消息key隔离数据的方式足够满足大部分应用; 但是,如果你需要一个全局顺序消费消息,你可以通过一个主题只有一个分区的方法实现,但是这也意味着一个分组只有一消费者;

    保证(此处翻译偏差较大,待重新翻译)

    • 同一个生产者发送的不同消息在分区中的存储是顺序的。
    • 同一个消费者看的消息顺序与这些消息的存储顺序是一致的。
    • 对一个拥有N个复制因子(N个分区),最多允许N-1台server故障还能保证消息不丢失。
      (是最多,并不代表一定。因为每个分区可以位于不同机器,也可以同时位于一台机器)
  • 1.2 使用案例

    消息处理

    kafka是一个很好的传统消息代理替代产品。消息代理有几种原因:解耦生产者与消息处理、缓存消息等。与大多数消息系统相比,kafka有更好的吞吐量,内置分区,复制和容错性,这使它成为大规模消息处理应用很好的解决方案。

    XXXX

    网站活动跟踪

    kafka的原始用例(为此而生)是能重建一套可以实时发布,实时订阅消息,用于处理用户活动轨迹跟踪的管道。也就是说网站的活动(页面浏览、搜索、用户其它行为)可以按活动类型分别发布到各自的主题;这些订阅可以被用于后续各种用途:包括实时处理、实时监控、加载到hadoop、离线数据仓库。

    因为每个用户浏览页面都会产生活动消息,因此,活动跟踪数据量非常大。

    度量

    kafka经常被用于处理监控数据。这涉及到从分布式应用收集统计数据,并且做为后续分析的一个统一的数据源。(即分布式统计数据查询入口或代理)

    日志收集

    很多人把kafka做为日志收集解决方案。日志收集是从服务器上采集日志文件并把它们放入一个集中位置(如:文件服务器或hdfs)统一处理。kafka抽象了文件细节,并给出一个日志或事件消息流。这允许更低的延时处理,更容易支持多数据源以及分布式消息处理。与Scribe和Flume相比,kafka提供同样的良好性能,并提供更好的可用性(因为多个副本),和更低的延时。

    流处理

    很多kafka用户,通过把数据处理分成多个步骤,每个步骤处理数据的不同功能并放入此步骤的topic中,并通过kafka topics串联起所有步骤,形成一个数据处理通道。
    如:一个处理新闻的流程:首先通过RSS收集新闻,并发布到”articles”主题中;第二步,从“articles”主题中取新闻并清洗重复内容,然后发布一个新的主题中;最后,从上步的主题中取数据并推荐给用户。
    这样的处理管道是基于单个主题的实时数据流程图。从0.10.0.0版本开始,一个轻量但强大的,被称为kafka stream的功能用于处理这样的数据。除了Kafka stream还有另外相似的开源工具:Apache Storm / Apache Samza。

    Event Sourcing

    提交日志

    kafka可以做为分布式系统的外部提交日志服务器。可以帮助分布式节点存储数据失败时,做为重新同步机制,在节点与操作之间复制日志,以恢复数据。

    这种情况,kafka与Apache BookKeeper 非常相似。

  • 1.3 快速开始

    本教程,假设你没有任何kafka知识。并且没有现成的kafka和zookeeper数据。

    步骤1: 下载代码

    下载0.10.0.0版本代码,并且解压

      tar -xzf kafka_2.11-0.10.0.0.tgz  cd kafka_2.11-0.10.0.0

    步骤2: 启动服务

    kafka依赖zookeeper,因此首先要启动zookeeper;如果没有安装独立的zookeeper,可以使用kafka内嵌的zookepper。虽然这种方式快速但不是很好。

    启动zookeeper

      > bin/zookeeper-server-start.sh config/zookeeper.properties

    启动 kafka

       bin/kafka-server-start.sh config/server.properties

    步骤3: 创建一个主题

    手动创建一个名为“test”的主题

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

    查看刚创建的主题

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

    可以通过配置“自动创建主题”,这样如果没有提前创建主题,那么在发布消息时,如果此消息对应的主题不存在,会自动创建。

    步骤4: 发送消息

    通过命令行客户端,可以通过文件或标准输入(命令行)向kafka集群发送消息。默认每行都是一条消息。

    启动生产者(启动成功进入命令行阻塞状态,可以输入数据,回车发送)

      bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test

    步骤5: 启动消费者

    启动消费者命令行(启动后命令行处于阻塞状态,生产者发布的消息会在此显示)

    “`

    bin/kafka-console-consumer.sh –zookeeper localhost:2181 –topic test –from-beginning

    “`

    步骤6: 设置服务器集群

    单个服务器挺没劲的,现在扩展到3台服务器(伪3台,在同一台机器上模拟)。
    现在配置服务器,让三台服务彼此联系

      > cp config/server.properties config/server-1.properties  > cp config/server.properties config/server-2.properties

    修改上面配置文件,两个都修改

    config/server-1.properties:    broker.id=1    listeners=PLAINTEXT://:9093    log.dir=/tmp/kafka-logs-1config/server-2.properties:    broker.id=2    listeners=PLAINTEXT://:9094    log.dir=/tmp/kafka-logs-2

    broker.id是唯一的,为的是让服务器知道自己是谁,以及自己的配置是哪个。在不同机器上,会配置zookeeper的所有机器。通过这个id,可以知道自己的配置。
    配置了日志和端口,由于是在同一台机器模拟,所以日志路径和端口不能重了。

    启动新增的两台kafka(zookeeper已经启动,同一台只需要启动一个即可)

    > bin/kafka-server-start.sh config/server-1.properties &> bin/kafka-server-start.sh config/server-2.properties &

    创建一个新的的主题:

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

    现在我们已经创建一个集群,但是我们怎么知道每个broker都做了什么?执行如下命令:”describe toics”:

    > bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic my-replicated-topic  Topic:my-replicated-topic PartitionCount:1    ReplicationFactor:3 Configs:   Topic: my-replicated-topic   Partition: 0    Leader: 1   Replicas: 1,2,0 Isr: 1,2,0

    第一行是所有分区的简介,其它行是每个具体分区的说明。因为我们只有一个分区,因此总共只有两行。

    • ”leader”: 是负责处理一个指定分区的所有读写操作。每个leader都是随机选择的。
    • “replicas”:副本是一个用来复制分区日志的节点列表。无论这些分区对应的服务器是leader还是处于激活状态,都会被复制。
    • “isr”

    注意:在我们的例子中,节点1是我们主题中唯一分区的leader;

    我们可以运行相同的命令,来查看我们最早创建的主题”test”的信息:

    > bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic test  Topic:test    PartitionCount:1    ReplicationFactor:1 Configs:    Topic: test Partition: 0    Leader: 0   Replicas: 0 Isr: 0

    遗憾的是:这个主题没有副本;

    让我们向新主题发布一些消息:

    > bin/kafka-console-producer.sh --broker-list localhost:9092 --topic my-replicated-topic...my test message 1my test message 2

    现在让我们消费这些消息:

    > bin/kafka-console-consumer.sh --zookeeper localhost:2181 --from-beginning --topic my-replicated-topic...my test message 1my test message 2

    现在让我们来测试容错。broker 1 正在充当leader,我们先干掉它:

      > ps | grep server-1.properties  7564 ttys002    0:15.91 /System/Library/Frameworks/JavaVM.framework/Versions/1.8/Home/bin/java...  > kill -9 7564

    领袖已经由奴隶节点中的一个充当。节点1已经不再是xxxx

      > bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic my-replicated-topic  Topic:my-replicated-topic PartitionCount:1    ReplicationFactor:3 Configs:    Topic: my-replicated-topic  Partition: 0    Leader: 2   Replicas: 1,2,0 Isr: 2,0

    现在,即使原先那个写操作的leader已经仙逝,但消息仍然能被正常消费。

    > bin/kafka-console-consumer.sh --zookeeper localhost:2181 --from-beginning --topic my-replicated-topic...my test message 1my test message 2

    步骤7: 使用kafka connect 导入/导出数据

    通过命令行读写数据是一个方便简单的开始。但是你可能希望通过其它数据源或者从kafka导出数据到其它系统。对大多数系统,你不需要写定制化的代码,只需要使用kafka connect 就可以导入或导出数据。kafka connect是一个可以运行多个connectors的扩展工具集。这些connectors实现了与外部系统交互的逻辑。在这个示例中,我们将体验怎么运行kafka connect ,并通过简单的connectors从文件把数据导入到主题,并从主题中把数据导出到文件。首先,我们创建一些种子数据,如下:
    ““

    echo -e “foo\nbar” > test.txt

    接着,我们以独立模式启动两个connectors。所谓独立模式,即这两个connectors运行在一个单一的、本地的、专有的进程中。我们提供三个配置文件做为后续命令的参数。第一个是用于普通的连接进程,包括broker,以及数据序列化格式。剩于的两个配置文件,每个都指定了一个需要创建的connector。这些文件包含一个唯一的connector名字,

    bin/connect-standalone.sh config/connect-standalone.properties config/connect-file-source.properties config/connect-file-sink.properties

    “`

kafka使用这些简单的配置文件启动,并创建两个connectors:第一个connector是一个从文件中按行读取数据,并把数据发布到主题的数据源connecotr。第二个是一个从主题消费消息,并把消息存到文件里的接收Connector。在启动过程中,你会看到许多日志信息,包括connetors实例化的一些指标信息。一旦kafka connect 进程启动,数据源connector就会开始从text.txt文件中读取数据。并且把数据发到connect-test主题。然后接收者connector开始从connect-test主题中读取数据,并且把数据写到test.sink.txt文件中。
我们可以检查test.sink.txt文件,来验证数据是否已经被传递到事个管道中。
“`

cat test.sink.txt
foo
bar

注意:数据正在被存储到
connect-test主题中,因此我们可以运行一个命令行消费者来查看主题中的数据。

bin/kafka-console-consumer.sh –zookeeper localhost:2181 –topic connect-test –from-beginning
{“schema”:{“type”:”string”,”optional”:false},”payload”:”foo”}
{“schema”:{“type”:”string”,”optional”:false},”payload”:”bar”}


我们可以向源文件中添加数据来检查数据在管道中的流动:

echo “Another line” >> test.txt
“`
你是不是惊奇的发现,”Another line”这条数据已经保存到test.sink.txt文件中了。我的天哪,这太神奇了。

### 步骤8: 使用 kafka Streams处理数据
kafka stream是一个处理实时的流式操作和数据分析的客户端库。 下面的快速入门示例将演示如何使用这个库去运行一个流式应用代码。下面是WordCountDemo示例的关键代码(使用的是java8 lamda表达式)。

```KTable wordCounts = textLines// Split each text line, by whitespace, into words..flatMapValues(value -> Arrays.asList(value.toLowerCase().split("\\W+")))// Ensure the words are available as record keys for the next aggregate operation..map((key, value) -> new KeyValue<>(value, value))// Count the occurrences of each word (record key) and store the results into a table named "Counts"..countByKey("Counts")```

它实现了 WordCount(单词计数)算法,用于计算一个单词在文本中出现的次数。但是跟其它你以前见过的WordCount算法有些许不同。因为它是被设计用来处理无限的流式数据。它是一个跟踪和更新单词计数的动态算法。由于必须假定输入数据是无限的,并且无法确定什么时候处理完“所有”数据,因此它会定期输入出当前状态和处理结果。

现在,我们准备向kafka 主题中输入一些数据,用于kafka Streams应用程序后续数据。```> echo -e "all streams lead to kafka\nhello kafka streams\njoin kafka summit" > file-input.txt```接着,我们把输入的数据通过命令行生产者发送到```streams-file-input```主题中(在实践中,流式数据会源源不断的发布到kafka中)。```  > bin/kafka-topics.sh --create \              --zookeeper localhost:2181 \              --replication-factor 1 \              --partitions 1 \              --topic streams-file-input  > cat file-input.txt | bin/kafka-console-producer.sh --broker-list localhost:9092 --topic streams-file-input```现在,我们可以启动WordCount示例应用来处理输入的数据。```  > bin/kafka-run-class.sh org.apache.kafka.streams.examples.wordcount.WordCountDemo```因为结果被写回到另一个主题,因此,除了日志条件,没有任何内容输出到“标准输出”。不像典型的流处理程序,示例代码运行几秒后会自动停止。我们现在可以通过读取输出主题的消息,来检查WordCount示例输出的数据:```> bin/kafka-console-consumer.sh --zookeeper localhost:2181 \        --topic streams-wordcount-output \        --from-beginning \        --formatter kafka.tools.DefaultMessageFormatter \        --property print.key=true \        --property print.value=true \        --property key.deserializer=org.apache.kafka.common.serialization.StringDeserializer \        --property value.deserializer=org.apache.kafka.common.serialization.LongDeserializer```程序运行后,会在命令行输出以下数据:```    all     1    streams 1    lead    1    to      1    kafka   1    hello   1    kafka   2    streams 2    join    1    kafka   3    summit  1```第一列是消息的key,第二列是消息的值。两列都使用了java.lang.String格式。注意,那个“输出”是一个持续的更新流。其中每条记录(原输出中的每一行)是一个单词的更新统计。对具有相同key的多条记录,以后的每条统计记录都是前一次的更新。现在,你可以向streams-file-input主题中写入更多的数据,你会发现,添加的数据会追加到“streams-wordcount-output”主题,并且体现到单词计数记录中(上述操作,可以通过命令行生产者和消费者来观察)
  • 1.4 生态

    除了上面描述的工具外,还有很多其它工具,如: stream processing system,Hadoop集成,monitoring,开发工具等。具体请看生态页;

  • 1.5 版本升级

2. API

apache kafka包含一个新的java客户端(位于org.apache.kafka.clients包中)。新的java客户端是为了替换旧的Scala客户端。但是一段时间内两个客户端会共存。同时这些客户端可以以单独的jar存在,而旧的Scala客户端仍然打包在server中。

  • 2.1 生产者api

    我们鼓励开发者使用新的java版客户端生产者api。这个客户端是经过生产环境测试,并且包含比Scala 客户端更快更全面的功能。你可以通过maven配置来加载客户端。

      <dependency>    <groupId>org.apache.kafka</groupId>    <artifactId>kafka-clients</artifactId>    <version>0.10.0.0</version>  </dependency>

    这里的api 文档中包含了一些示例。javadocs

    scala开发者看这里:scala example

  • 2.2 消费者api

    在0.90版本,我们已经提供了新的java 版本消息都客户端。目的是替换旧版基于zookeeper的上层(xxx???)consumer,以及低层的consumer apis。当前版本是测试版。为了让用户平滑升级,我们仍然维护0.8.0版本的客户端。下面我们即讲解0.8.0版,也讲解最新版。

    • ### 2.2.1 Old High Level Consumer API
    class Consumer {    /**     *  Create a ConsumerConnector     *     *  @param config  at the minimum, need to specify the groupid of the consumer and the zookeeper     *                 connection string zookeeper.connect.     */    public static kafka.javaapi.consumer.ConsumerConnector createJavaConsumerConnector(ConsumerConfig config);    }  /**    *  V: type of the message    *  K: type of the optional key associated with the message    */    public interface kafka.javaapi.consumer.ConsumerConnector {    /**     *  Create a list of message streams of type T for each topic.     *     *  @param topicCountMap  a map of (topic, #streams) pair     *  @param decoder a decoder that converts from Message to T     *  @return a map of (topic, list of  KafkaStream) pairs.     *          The number of items in the list is #streams. Each stream supports     *          an iterator over message/metadata pairs.     */    public <K,V> Map<String, List<KafkaStream<K,V>>>      createMessageStreams(Map<String, Integer> topicCountMap, Decoder<K> keyDecoder, Decoder<V> valueDecoder);    /**     *  Create a list of message streams of type T for each topic, using the default decoder.     */    public Map<String, List<KafkaStream<byte[], byte[]>>> createMessageStreams(Map<String, Integer> topicCountMap);    /**     *  Create a list of message streams for topics matching a wildcard.     *     *  @param topicFilter a TopicFilter that specifies which topics to     *                    subscribe to (encapsulates a whitelist or a blacklist).     *  @param numStreams the number of message streams to return.     *  @param keyDecoder a decoder that decodes the message key     *  @param valueDecoder a decoder that decodes the message itself     *  @return a list of KafkaStream. Each stream supports an     *          iterator over its MessageAndMetadata elements.     */    public <K,V> List<KafkaStream<K,V>>      createMessageStreamsByFilter(TopicFilter topicFilter, int numStreams, Decoder<K> keyDecoder, Decoder<V> valueDecoder);    /**     *  Create a list of message streams for topics matching a wildcard, using the default decoder.     */    public List<KafkaStream<byte[], byte[]>> createMessageStreamsByFilter(TopicFilter topicFilter, int numStreams);    /**     *  Create a list of message streams for topics matching a wildcard, using the default decoder, with one stream.     */    public List<KafkaStream<byte[], byte[]>> createMessageStreamsByFilter(TopicFilter topicFilter);    /**     *  Commit the offsets of all topic/partitions connected by this connector.     */    public void commitOffsets();    /**     *  Shut down the connector     */    public void shutdown();  }

    这里有一些示例

    • 2.2.2 Old Simple Consumer API

        class kafka.javaapi.consumer.SimpleConsumer {    /**     *  Fetch a set of messages from a topic.     *     *  @param request specifies the topic name, topic partition, starting byte offset, maximum bytes to be fetched.     *  @return a set of fetched messages     */    public FetchResponse fetch(kafka.javaapi.FetchRequest request);    /**     *  Fetch metadata for a sequence of topics.     *     *  @param request specifies the versionId, clientId, sequence of topics.     *  @return metadata for each topic in the request.     */    public kafka.javaapi.TopicMetadataResponse send(kafka.javaapi.TopicMetadataRequest request);    /**     *  Get a list of valid offsets (up to maxSize) before the given time.     *     *  @param request a [[kafka.javaapi.OffsetRequest]] object.     *  @return a [[kafka.javaapi.OffsetResponse]] object.     */    public kafka.javaapi.OffsetResponse getOffsetsBefore(OffsetRequest request);    /**     * Close the SimpleConsumer.     */    public void close();  }

      对大多数应用而言,上层consumer api就可以满足。但是有些应用可能需要一些没有暴露到上层consumer中的特性(如:当重启consumer时重置偏移量)。他们可以使用低层的SimpleConsumer api。这个逻辑有点复杂,你可以参考这里的示例;

    • 2.2.3 新版消费者 Api

      新版consumer api删除了0.8版中,高层api与底层api的区别,直接使用统一的api。你直接使用下面的maven配置加载新版客户端。

        <dependency>        <groupId>org.apache.kafka</groupId>        <artifactId>kafka-clients</artifactId>        <version>0.10.0.0</version>    </dependency>

    用法示例

  • 2.3 streams api

    在0.10.0版本中我们新增了一个称为”Kafka Stream”的新客户端库。它主要用于处理流式操作。特别注意,这个还是内测试版。有许多api在未来很可能有大的变动,因此使用需谨慎。你可以通过以下maven配置加载它。

      <dependency>        <groupId>org.apache.kafka</groupId>        <artifactId>kafka-streams</artifactId>        <version>0.10.0.0</version>    </dependency>

    这里的[javadocs]有一些示例(切记:标注了@InterfaceStability.Unstable注解的class,在未来很可能有大的变动,而且不会向后兼容。一句话:谁用谁填坑)。

3. 配置

kafka使用基于property文件格式的键值对配置程序。这些键值对即可以来自property文件,也可以来自编程方式。

  • 3.1 代理(broker)(服务器)配置

    最核心最必须最基础的配置如下

    • broker.id
    • log.dirs
    • zookeeper.connect
      主题级别的配置,以及具体的默认配置在下面有详情讨论:看这里
      以下表格可以左右滚动
    名称 说明 数据类型 默认值 有效值 重要程度 zookeeper.connect zookeeper集群地址(多个用英文逗号分隔).集群中所有zookeeper主机ip及端口配置。 string high advertised.host.name DEPRECATED: only used when `advertised.listeners` or `listeners` are not set. Use `advertised.listeners` instead. Hostname to publish to ZooKeeper for clients to use. In IaaS environments, this may need to be different from the interface to which the broker binds. If this is not set, it will use the value for `host.name` if configured. Otherwise it will use the value returned from java.net.InetAddress.getCanonicalHostName(). string null high advertised.listeners Listeners to publish to ZooKeeper for clients to use, if different than the listeners above. In IaaS environments, this may need to be different from the interface to which the broker binds. If this is not set, the value for `listeners` will be used. string null high advertised.port DEPRECATED: only used when `advertised.listeners` or `listeners` are not set. Use `advertised.listeners` instead. The port to publish to ZooKeeper for clients to use. In IaaS environments, this may need to be different from the port to which the broker binds. If this is not set, it will publish the same port that the broker binds to. int null high auto.create.topics.enable 发布消息,如果主题不存在,则自动创建主题。否则必须先创建主题。线上一般为false boolean true high auto.leader.rebalance.enable Enables auto leader balancing. A background thread checks and triggers leader balance if required at regular intervals boolean true high background.threads The number of threads to use for various background processing tasks int 10 [1,…] high broker.id The broker id for this server. If unset, a unique broker id will be generated.To avoid conflicts between zookeeper generated broker id’s and user configured broker id’s, generated broker idsstart from reserved.broker.max.id + 1. int -1 high compression.type Specify the final compression type for a given topic. This configuration accepts the standard compression codecs (‘gzip’, ‘snappy’, ‘lz4’). It additionally accepts ‘uncompressed’ which is equivalent to no compression; and ‘producer’ which means retain the original compression codec set by the producer. string producer high delete.topic.enable Enables delete topic. Delete topic through the admin tool will have no effect if this config is turned off boolean false high host.name DEPRECATED: only used when `listeners` is not set. Use `listeners` instead. hostname of broker. If this is set, it will only bind to this address. If this is not set, it will bind to all interfaces string "" high leader.imbalance.check.interval.seconds The frequency with which the partition rebalance check is triggered by the controller long 300 high leader.imbalance.per.broker.percentage The ratio of leader imbalance allowed per broker. The controller would trigger a leader balance if it goes above this value per broker. The value is specified in percentage. int 10 high listeners Listener List - Comma-separated list of URIs we will listen on and their protocols. Specify hostname as 0.0.0.0 to bind to all interfaces. Leave hostname empty to bind to default interface. Examples of legal listener lists: PLAINTEXT://myhost:9092,TRACE://:9091 PLAINTEXT://0.0.0.0:9092, TRACE://localhost:9093 string null high log.dir 日志(即数据)目录,其实是kafka的持久化文件目录。(log.dirs补充此配置) string /tmp/kafka-logs high log.dirs 日志(即数据)目录,其实是kafka的持久化文件目录(可以配置多个用逗号隔开). 如果未设置,将使用 log.dir 配置的目录 string null high log.flush.interval.messages The number of messages accumulated on a log partition before messages are flushed to disk long 9223372036854775807 [1,…] high log.flush.interval.ms The maximum time in ms that a message in any topic is kept in memory before flushed to disk. If not set, the value in log.flush.scheduler.interval.ms is used long null high log.flush.offset.checkpoint.interval.ms The frequency with which we update the persistent record of the last flush which acts as the log recovery point int 60000 [0,…] high log.flush.scheduler.interval.ms The frequency in ms that the log flusher checks whether any log needs to be flushed to disk long 9223372036854775807 high log.retention.bytes The maximum size of the log before deleting it long -1 high log.retention.hours The number of hours to keep a log file before deleting it (in hours), tertiary to log.retention.ms property int 168 high log.retention.minutes The number of minutes to keep a log file before deleting it (in minutes), secondary to log.retention.ms property. If not set, the value in log.retention.hours is used int null high log.retention.ms The number of milliseconds to keep a log file before deleting it (in milliseconds), If not set, the value in log.retention.minutes is used long null high log.roll.hours The maximum time before a new log segment is rolled out (in hours), secondary to log.roll.ms property int 168 [1,…] high log.roll.jitter.hours The maximum jitter to subtract from logRollTimeMillis (in hours), secondary to log.roll.jitter.ms property int 0 [0,…] high log.roll.jitter.ms The maximum jitter to subtract from logRollTimeMillis (in milliseconds). If not set, the value in log.roll.jitter.hours is used long null high log.roll.ms The maximum time before a new log segment is rolled out (in milliseconds). If not set, the value in log.roll.hours is used long null high log.segment.bytes The maximum size of a single log file int 1073741824 [14,…] high log.segment.delete.delay.ms The amount of time to wait before deleting a file from the filesystem long 60000 [0,…] high message.max.bytes The maximum size of message that the server can receive int 1000012 [0,…] high min.insync.replicas define the minimum number of replicas in ISR needed to satisfy a produce request with acks=all (or -1) int 1 [1,…] high num.io.threads The number of io threads that the server uses for carrying out network requests int 8 [1,…] high num.network.threads the number of network threads that the server uses for handling network requests int 3 [1,…] high num.recovery.threads.per.data.dir The number of threads per data directory to be used for log recovery at startup and flushing at shutdown int 1 [1,…] high num.replica.fetchers Number of fetcher threads used to replicate messages from a source broker. Increasing this value can increase the degree of I/O parallelism in the follower broker. int 1 high offset.metadata.max.bytes The maximum size for a metadata entry associated with an offset commit int 4096 high offsets.commit.required.acks The required acks before the commit can be accepted. In general, the default (-1) should not be overridden short -1 high offsets.commit.timeout.ms Offset commit will be delayed until all replicas for the offsets topic receive the commit or this timeout is reached. This is similar to the producer request timeout. int 5000 [1,…] high offsets.load.buffer.size Batch size for reading from the offsets segments when loading offsets into the cache. int 5242880 [1,…] high offsets.retention.check.interval.ms Frequency at which to check for stale offsets long 600000 [1,…] high offsets.retention.minutes Log retention window in minutes for offsets topic int 1440 [1,…] high offsets.topic.compression.codec Compression codec for the offsets topic - compression may be used to achieve "atomic" commits int 0 high offsets.topic.num.partitions The number of partitions for the offset commit topic (should not change after deployment) int 50 [1,…] high offsets.topic.replication.factor The replication factor for the offsets topic (set higher to ensure availability). To ensure that the effective replication factor of the offsets topic is the configured value, the number of alive brokers has to be at least the replication factor at the time of the first request for the offsets topic. If not, either the offsets topic creation will fail or it will get a replication factor of min(alive brokers, configured replication factor) short 3 [1,…] high offsets.topic.segment.bytes The offsets topic segment bytes should be kept relatively small in order to facilitate faster log compaction and cache loads int 104857600 [1,…] high port DEPRECATED: only used when `listeners` is not set. Use `listeners` instead. the port to listen and accept connections on int 9092 high queued.max.requests The number of queued requests allowed before blocking the network threads int 500 [1,…] high quota.consumer.default Any consumer distinguished by clientId/consumer group will get throttled if it fetches more bytes than this value per-second long 9223372036854775807 [1,…] high quota.producer.default Any producer distinguished by clientId will get throttled if it produces more bytes than this value per-second long 9223372036854775807 [1,…] high replica.fetch.max.bytes The number of bytes of messages to attempt to fetch int 1048576 high replica.fetch.min.bytes Minimum bytes expected for each fetch response. If not enough bytes, wait up to replicaMaxWaitTimeMs int 1 high replica.fetch.wait.max.ms max wait time for each fetcher request issued by follower replicas. This value should always be less than the replica.lag.time.max.ms at all times to prevent frequent shrinking of ISR for low throughput topics int 500 high replica.high.watermark.checkpoint.interval.ms The frequency with which the high watermark is saved out to disk long 5000 high replica.lag.time.max.ms If a follower hasn’t sent any fetch requests or hasn’t consumed up to the leaders log end offset for at least this time, the leader will remove the follower from isr long 10000 high replica.socket.receive.buffer.bytes The socket receive buffer for network requests int 65536 high replica.socket.timeout.ms The socket timeout for network requests. Its value should be at least replica.fetch.wait.max.ms int 30000 high request.timeout.ms The configuration controls the maximum amount of time the client will wait for the response of a request. If the response is not received before the timeout elapses the client will resend the request if necessary or fail the request if retries are exhausted. int 30000 high socket.receive.buffer.bytes The SO_RCVBUF buffer of the socket sever sockets int 102400 high socket.request.max.bytes The maximum number of bytes in a socket request int 104857600 [1,…] high socket.send.buffer.bytes The SO_SNDBUF buffer of the socket sever sockets int 102400 high unclean.leader.election.enable Indicates whether to enable replicas not in the ISR set to be elected as leader as a last resort, even though doing so may result in data loss boolean true high zookeeper.connection.timeout.ms The max time that the client waits to establish a connection to zookeeper. If not set, the value in zookeeper.session.timeout.ms is used int null high zookeeper.session.timeout.ms Zookeeper session timeout int 6000 high zookeeper.set.acl Set client to use secure ACLs boolean false high broker.id.generation.enable Enable automatic broker id generation on the server? When enabled the value configured for reserved.broker.max.id should be reviewed. boolean true medium broker.rack Rack of the broker. This will be used in rack aware replication assignment for fault tolerance. Examples: `RACK1`, `us-east-1d` string null medium connections.max.idle.ms Idle connections timeout: the server socket processor threads close the connections that idle more than this long 600000 medium controlled.shutdown.enable Enable controlled shutdown of the server boolean true medium controlled.shutdown.max.retries Controlled shutdown can fail for multiple reasons. This determines the number of retries when such failure happens int 3 medium controlled.shutdown.retry.backoff.ms Before each retry, the system needs time to recover from the state that caused the previous failure (Controller fail over, replica lag etc). This config determines the amount of time to wait before retrying. long 5000 medium controller.socket.timeout.ms The socket timeout for controller-to-broker channels int 30000 medium default.replication.factor 对自动创建的主题而言:默认副本数。默认值是1,即不复制。建议 int 1 medium fetch.purgatory.purge.interval.requests The purge interval (in number of requests) of the fetch request purgatory int 1000 medium group.max.session.timeout.ms The maximum allowed session timeout for registered consumers. Longer timeouts give consumers more time to process messages in between heartbeats at the cost of a longer time to detect failures. int 300000 medium group.min.session.timeout.ms The minimum allowed session timeout for registered consumers. Shorter timeouts leader to quicker failure detection at the cost of more frequent consumer heartbeating, which can overwhelm broker resources. int 6000 medium inter.broker.protocol.version Specify which version of the inter-broker protocol will be used. This is typically bumped after all brokers were upgraded to a new version. Example of some valid values are: 0.8.0, 0.8.1, 0.8.1.1, 0.8.2, 0.8.2.0, 0.8.2.1, 0.9.0.0, 0.9.0.1 Check ApiVersion for the full list. string 0.10.0-IV1 medium log.cleaner.backoff.ms The amount of time to sleep when there are no logs to clean long 15000 [0,…] medium log.cleaner.dedupe.buffer.size The total memory used for log deduplication across all cleaner threads long 134217728 medium log.cleaner.delete.retention.ms How long are delete records retained? long 86400000 medium log.cleaner.enable Enable the log cleaner process to run on the server? Should be enabled if using any topics with a cleanup.policy=compact including the internal offsets topic. If disabled those topics will not be compacted and continually grow in size. boolean true medium log.cleaner.io.buffer.load.factor Log cleaner dedupe buffer load factor. The percentage full the dedupe buffer can become. A higher value will allow more log to be cleaned at once but will lead to more hash collisions double 0.9 medium log.cleaner.io.buffer.size The total memory used for log cleaner I/O buffers across all cleaner threads int 524288 [0,…] medium log.cleaner.io.max.bytes.per.second The log cleaner will be throttled so that the sum of its read and write i/o will be less than this value on average double 1.7976931348623157E308 medium log.cleaner.min.cleanable.ratio The minimum ratio of dirty log to total log for a log to eligible for cleaning double 0.5 medium log.cleaner.threads The number of background threads to use for log cleaning int 1 [0,…] medium log.cleanup.policy The default cleanup policy for segments beyond the retention window, must be either "delete" or "compact" string delete [compact, delete] medium log.index.interval.bytes The interval with which we add an entry to the offset index int 4096 [0,…] medium log.index.size.max.bytes The maximum size in bytes of the offset index int 10485760 [4,…] medium log.message.format.version Specify the message format version the broker will use to append messages to the logs. The value should be a valid ApiVersion. Some examples are: 0.8.2, 0.9.0.0, 0.10.0, check ApiVersion for more details. By setting a particular message format version, the user is certifying that all the existing messages on disk are smaller or equal than the specified version. Setting this value incorrectly will cause consumers with older versions to break as they will receive messages with a format that they don’t understand. string 0.10.0-IV1 medium log.message.timestamp.difference.max.ms The maximum difference allowed between the timestamp when a broker receives a message and the timestamp specified in the message. If message.timestamp.type=CreateTime, a message will be rejected if the difference in timestamp exceeds this threshold. This configuration is ignored if message.timestamp.type=LogAppendTime. long 9223372036854775807 [0,…] medium log.message.timestamp.type Define whether the timestamp in the message is message create time or log append time. The value should be either `CreateTime` or `LogAppendTime` string CreateTime [CreateTime, LogAppendTime] medium log.preallocate Should pre allocate file when create new segment? If you are using Kafka on Windows, you probably need to set it to true. boolean false medium log.retention.check.interval.ms The frequency in milliseconds that the log cleaner checks whether any log is eligible for deletion long 300000 [1,…] medium max.connections.per.ip The maximum number of connections we allow from each ip address int 2147483647 [1,…] medium max.connections.per.ip.overrides Per-ip or hostname overrides to the default maximum number of connections string "" medium num.partitions 主题的默认分区数 int 1 [1,…] medium principal.builder.class The fully qualified name of a class that implements the PrincipalBuilder interface, which is currently used to build the Principal for connections with the SSL SecurityProtocol. class class org.apache.kafka.common.security.auth.DefaultPrincipalBuilder medium producer.purgatory.purge.interval.requests The purge interval (in number of requests) of the producer request purgatory int 1000 medium replica.fetch.backoff.ms The amount of time to sleep when fetch partition error occurs. int 1000 [0,…] medium reserved.broker.max.id Max number that can be used for a broker.id int 1000 [0,…] medium sasl.enabled.mechanisms The list of SASL mechanisms enabled in the Kafka server. The list may contain any mechanism for which a security provider is available. Only GSSAPI is enabled by default. list [GSSAPI] medium sasl.kerberos.kinit.cmd Kerberos kinit command path. string /usr/bin/kinit medium sasl.kerberos.min.time.before.relogin Login thread sleep time between refresh attempts. long 60000 medium sasl.kerberos.principal.to.local.rules A list of rules for mapping from principal names to short names (typically operating system usernames). The rules are evaluated in order and the first rule that matches a principal name is used to map it to a short name. Any later rules in the list are ignored. By default, principal names of the form {username}/{hostname}@{REALM} are mapped to {username}. For more details on the format please see security authorization and acls. list [DEFAULT] medium sasl.kerberos.service.name The Kerberos principal name that Kafka runs as. This can be defined either in Kafka’s JAAS config or in Kafka’s config. string null medium sasl.kerberos.ticket.renew.jitter Percentage of random jitter added to the renewal time. double 0.05 medium sasl.kerberos.ticket.renew.window.factor Login thread will sleep until the specified window factor of time from last refresh to ticket’s expiry has been reached, at which time it will try to renew the ticket. double 0.8 medium sasl.mechanism.inter.broker.protocol SASL mechanism used for inter-broker communication. Default is GSSAPI. string GSSAPI medium security.inter.broker.protocol Security protocol used to communicate between brokers. Valid values are: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL. string PLAINTEXT medium ssl.cipher.suites A list of cipher suites. This is a named combination of authentication, encryption, MAC and key exchange algorithm used to negotiate the security settings for a network connection using TLS or SSL network protocol.By default all the available cipher suites are supported. list null medium ssl.client.auth Configures kafka broker to request client authentication. The following settings are common:
    • ssl.client.auth=requiredIf set to required client authentication is required.
    • ssl.client.auth=requestedThis means client authentication is optional. unlike requested , if this option is set client can choose not to provide authentication information about itself
    • ssl.client.auth=noneThis means client authentication is not needed.
    string none [required, requested, none] medium ssl.enabled.protocols The list of protocols enabled for SSL connections. list [TLSv1.2, TLSv1.1, TLSv1] medium ssl.key.password The password of the private key in the key store file. This is optional for client. password null medium ssl.keymanager.algorithm The algorithm used by key manager factory for SSL connections. Default value is the key manager factory algorithm configured for the Java Virtual Machine. string SunX509 medium ssl.keystore.location The location of the key store file. This is optional for client and can be used for two-way authentication for client. string null medium ssl.keystore.password The store password for the key store file.This is optional for client and only needed if ssl.keystore.location is configured. password null medium ssl.keystore.type The file format of the key store file. This is optional for client. string JKS medium ssl.protocol The SSL protocol used to generate the SSLContext. Default setting is TLS, which is fine for most cases. Allowed values in recent JVMs are TLS, TLSv1.1 and TLSv1.2. SSL, SSLv2 and SSLv3 may be supported in older JVMs, but their usage is discouraged due to known security vulnerabilities. string TLS medium ssl.provider The name of the security provider used for SSL connections. Default value is the default security provider of the JVM. string null medium ssl.trustmanager.algorithm The algorithm used by trust manager factory for SSL connections. Default value is the trust manager factory algorithm configured for the Java Virtual Machine. string PKIX medium ssl.truststore.location The location of the trust store file. string null medium ssl.truststore.password The password for the trust store file. password null medium ssl.truststore.type The file format of the trust store file. string JKS medium authorizer.class.name The authorizer class that should be used for authorization string "" low metric.reporters A list of classes to use as metrics reporters. Implementing the MetricReporterinterface allows plugging in classes that will be notified of new metric creation. The JmxReporter is always included to register JMX statistics. list [] low metrics.num.samples The number of samples maintained to compute metrics. int 2 [1,…] low metrics.sample.window.ms The window of time a metrics sample is computed over. long 30000 [1,…] low quota.window.num The number of samples to retain in memory int 11 [1,…] low quota.window.size.seconds The time span of each sample int 1 [1,…] low ssl.endpoint.identification.algorithm The endpoint identification algorithm to validate server hostname using server certificate. string null low zookeeper.sync.time.ms How far a ZK follower can be behind a ZK leader int 2000 low

更多关于broker的配置细节,可以到类kafka.server.KafkaConfig中查看。

有关主题的配置,即可以使用全局默认值,也可以每个主题单独配置。如果给定的主题没有配置,那么将使用全局默认配置。创建主题时,可以通过给定配置参数,覆盖全局默认配置。下面的示例就是创建一个命名为“my-topic”的主题,并且设置消息最大大小和刷新频率。

> bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic my-topic --partitions 1             --replication-factor 1 --config max.message.bytes=64000 --config flush.messages=1

除了创建主题时设置配置,通过–alter命令也可以随时修改主题配置。如下,设置主题my-topic的最大消息大小:

        > bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic my-topic          --config max.message.bytes=128000
  也可以通过--delete-config来删除主题定制的配置,恢复到全局默认配置。如下:
        > bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic my-topic          --delete-config max.message.bytes

以下是主题级别的配置。服务器级的默认配置是全局配置。可以设置这个值用于配置没有自定义的主题。具体在“服务器配置属性列”
属性:主题属性名;
默认值:由服务器默认值指定。
服务器默认值:用于配置全局默认值。可修改

属性 默认值 服务器默认值 说明 cleanup.policy delete log.cleanup.policy A string that is either "delete" or "compact". This string designates the retention policy to use on old log segments. The default policy ("delete") will discard old segments when their retention time or size limit has been reached. The "compact" setting will enable log compaction on the topic. delete.retention.ms 86400000 (24 hours) log.cleaner.delete.retention.ms The amount of time to retain delete tombstone markers for log compacted topics. This setting also gives a bound on the time in which a consumer must complete a read if they begin from offset 0 to ensure that they get a valid snapshot of the final stage (otherwise delete tombstones may be collected before they complete their scan). flush.messages None log.flush.interval.messages This setting allows specifying an interval at which we will force an fsync of data written to the log. For example if this was set to 1 we would fsync after every message; if it were 5 we would fsync after every five messages. In general we recommend you not set this and use replication for durability and allow the operating system’s background flush capabilities as it is more efficient. This setting can be overridden on a per-topic basis (see the per-topic configuration section). flush.ms None log.flush.interval.ms This setting allows specifying a time interval at which we will force an fsync of data written to the log. For example if this was set to 1000 we would fsync after 1000 ms had passed. In general we recommend you not set this and use replication for durability and allow the operating system’s background flush capabilities as it is more efficient. index.interval.bytes 4096 log.index.interval.bytes This setting controls how frequently Kafka adds an index entry to it’s offset index. The default setting ensures that we index a message roughly every 4096 bytes. More indexing allows reads to jump closer to the exact position in the log but makes the index larger. You probably don’t need to change this. max.message.bytes 1,000,000 message.max.bytes This is largest message size Kafka will allow to be appended to this topic. Note that if you increase this size you must also increase your consumer’s fetch size so they can fetch messages this large. min.cleanable.dirty.ratio 0.5 log.cleaner.min.cleanable.ratio This configuration controls how frequently the log compactor will attempt to clean the log (assuming log compaction is enabled). By default we will avoid cleaning a log where more than 50% of the log has been compacted. This ratio bounds the maximum space wasted in the log by duplicates (at 50% at most 50% of the log could be duplicates). A higher ratio will mean fewer, more efficient cleanings but will mean more wasted space in the log. min.insync.replicas 1 min.insync.replicas When a producer sets acks to "all", min.insync.replicas specifies the minimum number of replicas that must acknowledge a write for the write to be considered successful. If this minimum cannot be met, then the producer will raise an exception (either NotEnoughReplicas or NotEnoughReplicasAfterAppend). When used together, min.insync.replicas and acks allow you to enforce greater durability guarantees. A typical scenario would be to create a topic with a replication factor of 3, set min.insync.replicas to 2, and produce with acks of "all". This will ensure that the producer raises an exception if a majority of replicas do not receive a write. retention.bytes None log.retention.bytes This configuration controls the maximum size a log can grow to before we will discard old log segments to free up space if we are using the "delete" retention policy. By default there is no size limit only a time limit. retention.ms 7 days log.retention.minutes This configuration controls the maximum time we will retain a log before we will discard old log segments to free up space if we are using the "delete" retention policy. This represents an SLA on how soon consumers must read their data. segment.bytes 1 GB log.segment.bytes This configuration controls the segment file size for the log. Retention and cleaning is always done a file at a time so a larger segment size means fewer files but less granular control over retention. segment.index.bytes 10 MB log.index.size.max.bytes This configuration controls the size of the index that maps offsets to file positions. We preallocate this index file and shrink it only after log rolls. You generally should not need to change this setting. segment.ms 7 days log.roll.hours This configuration controls the period of time after which Kafka will force the log to roll even if the segment file isn’t full to ensure that retention can delete or compact old data. segment.jitter.ms 0 log.roll.jitter.{ms,hours} The maximum jitter to subtract from logRollTimeMillis.
  • 3.2 生产者(producer)配置

    以下为生产者配置:

    名称 说明 数据类型 默认值 Valid Values 重要程度 bootstrap.servers 一个主机/端口对的集合列表。目的是为了初始与kafka集群建立连接。注意:客户端不需要把的集群中所有的主机都配置在这里。此处的目的仅仅时初始的时候建立与集群的连接,一旦建立,客户端可以使用使用集群中的任何一台机器,即此处没有配置。 配置的格式如下:host1:port1,host2:port2…。另外,此配置仅仅是为了与集群第一次建立连接,不需要全配置(会动态增加或删除机器,也没办法全配置),但至少配置两台,防止一台崩溃,就再也连不上集群了。 切记:是kafka集群主机,不是zookeeper主机。java客户端不直接与zookeeper交互) list high key.serializer key:实现了Serializer接口的序列化类。用于告诉kafka如何序列化key. class high value.serializer value:实现了Serializer接口的序列化类。用于告诉kafka如何序列化value. class high acks leader收到的来自所有follower复制成功的确认数量(比如:有10个follower,只要2个确认成功就认为整个发送成功[还有一个是leader自己],那么acks=3)。只有达到这个数量,生产者才认为消息成功发送。
    • acks=0 如果值为0 ,生产者不会等待服务器的任何确认。只要消息被立即发送到socket buffer中,就认为发送成功。 这种情况下,无法保证服务器已经收到了消息。同时retries(失败重试) 配置也会失效(因为客户端收不到任何错误)。 返回的offset(偏移量)也不是正确的值,永远都是-1. 注意:此时,通过Feture.get()会是怎样的结果呢?
    • acks=1 这意味着,leader把日志写入到本地日志(acks=1,代表它自己完成就可以),不等待任何其它follower的确认,就认为消息成功发送。 这种情况,如果在follower成功复制副本前,且leader已经告诉客户端已经成功后,leader崩溃了,那么这条消息就会丢失。
    • acks=all 这表示leader会等待所有“in-sync”台follower的复制确认。只要一台“in-sync” follower处于激活状态,数据就保证不会丢失。 这是最强的可用性保证。注:”in-sync”只是的有follower中的一部分,并不是所有follower. 同时:acks只能是:0,1,all,还是0,1,2…99999…,all ???todo
    string 1 [all, -1, 0, 1] high buffer.memory 生产者可以用来缓冲消息记录的总内存大小(单位:字节)。如果消息产生的速度超过发送的速度,那么生产会被阻塞”max.block.ms”时间,如果超过此时间会抛出异常。这个设置大体上与生产使用的全部内存相当。但是这不是一个硬性标准,因为生产者用的所有内存不是都用来缓冲。例如:一些附加的内存用来压缩(如:压缩被启用)或维护请求。 long 33554432 [0,…] high compression.type 生产者发送的数据压缩格式。默认不压缩。合法的值有: none, gzip, snappy, 或 lz4。 压缩是针对数据的所有批处理。因此批处理会影响压缩比(越大的批处理,压缩比越高)。 string none high retries 待:不知道此值是一个类似boolean弄的数据,还是重试次数。如果是boolean型,那么只重试一次?文档并没说清。待查看源码 如果此值大于0,那么客户端在接收到事务error时,会重新发送。注意:这种重试与异常重发没有区另(???)允许重试可能会改变记录的次序。因为如果两条消息发送到同一分区,那么第一条失败了并重试,但是第二条成功了,那第二条会出现在第一的位置。 int 0 [0,…,2147483647] high ssl.key.password The password of the private key in the key store file. This is optional for client. password null high ssl.keystore.location The location of the key store file. This is optional for client and can be used for two-way authentication for client. string null high ssl.keystore.password The store password for the key store file.This is optional for client and only needed if ssl.keystore.location is configured. password null high ssl.truststore.location The location of the trust store file. string null high ssl.truststore.password The password for the trust store file. password null high batch.size 无论何时消息记录发送到同一个分区时,生产者会试图批量把记录放在一起发送到服务器,以此来减少请求次数。这样会即帮助客户端也帮助服务器端的性能提升。此配置就是用来控制默认配置的(单位:字节)。 批处理的消息记录不会超过此配置。 小的批处理量会降低吞吐量(如果批处理量为0,那么将完全禁止批处理)。大的批处理量又会非常浪费内存。 int 16384 [0,…] medium client.id 是一个字符串类型的值,生产者向服务器发送消息时创建。目的是:能在服务器端的日志中保存一个应用的逻辑名称,比通过ip和端口更方便的方式来追踪请求源。 string "" medium connections.max.idle.ms 空闲链接存活时间。超过此配置的时间(毫秒),则关闭此空闲链接 long 540000 medium linger.ms 生产者会把linger.ms指定的时间间隔内的多次请求打包成一个批处理请求。 通常这只用于消息产生太快,以至于超过了向服务器传输速度的情况下。不过,在某些压力不是很大的负载下,仅仅为了降低请求次数也可以使用此配置。 通过此配置,消息不会立即发送,而是延迟指定的时间后再这送。这样在延迟的时间间隔内,还允许其它消息与当前消息做为一次批处理。 这跟TCP中的Nagle算法类似。这个配置给定了一次批处理的范围:一旦消息达到了batch.size指定的字节数,会立即发送,此时会忽略当前配置。如果没有达到 batch.size指定的值,那么消息会延迟linger.ms指定的时间后再发送。 说白了:batch.size是通过消息大小来触发批处理。linger.ms是通过时间来触发批处理。一方面可以防止消息延迟太久,另一方面可以防止消息积压太多。 long 0 [0,…] medium max.block.ms 此配置是用来控制KafkaProducer.send() 的时间,以及 KafkaProducer.partitionsFor() 的阻塞时间.缓冲慢了或者无数据不可用都会导致当前方法被阻塞。 Blocking in the user-supplied serializers or partitioner will not be counted against this timeout. long 60000 [0,…] medium max.request.size 一次请求的数据大小的上限(单位:字节)。这也影响最大的一条记录的大小上限。注意,服务器也有此配置,而且配置的值与当前值可能不相同。 此配置可以限止一次请求的批处理的消息条数,以防止发送过大的请求。 是否与:batch.size有冲突??? int 1048576 [0,…] medium partitioner.class Partitioner class that implements the Partitioner interface. class class org.apache.kafka.clients.producer.internals.DefaultPartitioner medium receive.buffer.bytes The size of the TCP receive buffer (SO_RCVBUF) to use when reading data. int 32768 [0,…] medium request.timeout.ms 配置超时时间。如果在此配置的时间内还没有收到服务器的返回值,那么可能会失败重发或者如果重发次数过多时就直接失败。 int 30000 [0,…] medium sasl.kerberos.service.name The Kerberos principal name that Kafka runs as. This can be defined either in Kafka’s JAAS config or in Kafka’s config. string null medium sasl.mechanism SASL mechanism used for client connections. This may be any mechanism for which a security provider is available. GSSAPI is the default mechanism. string GSSAPI medium security.protocol Protocol used to communicate with brokers. Valid values are: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL. string PLAINTEXT medium send.buffer.bytes TCP缓冲大小 (SO_SNDBUF)。与批处理缓冲不同。此处仅指TCP使用的缓冲 int 131072 [0,…] medium ssl.enabled.protocols The list of protocols enabled for SSL connections. list [TLSv1.2, TLSv1.1, TLSv1] medium ssl.keystore.type The file format of the key store file. This is optional for client. string JKS medium ssl.protocol The SSL protocol used to generate the SSLContext. Default setting is TLS, which is fine for most cases. Allowed values in recent JVMs are TLS, TLSv1.1 and TLSv1.2. SSL, SSLv2 and SSLv3 may be supported in older JVMs, but their usage is discouraged due to known security vulnerabilities. string TLS medium ssl.provider The name of the security provider used for SSL connections. Default value is the default security provider of the JVM. string null medium ssl.truststore.type The file format of the trust store file. string JKS medium timeout.ms The configuration controls the maximum amount of time the server will wait for acknowledgments from followers to meet the acknowledgment requirements the producer has specified with the acks configuration. If the requested number of acknowledgments are not met when the timeout elapses an error will be returned. This timeout is measured on the server side and does not include the network latency of the request. int 30000 [0,…] medium block.on.buffer.full When our memory buffer is exhausted we must either stop accepting new records (block) or throw errors. By default this setting is false and the producer will no longer throw a BufferExhaustException but instead will use the max.block.ms value to block, after which it will throw a TimeoutException. Setting this property to true will set the max.block.ms to Long.MAX_VALUE. Also if this property is set to true, parameter metadata.fetch.timeout.ms is not longer honored.

    This parameter is deprecated and will be removed in a future release. Parameter max.block.ms should be used instead.

    boolean false low interceptor.classes A list of classes to use as interceptors. Implementing the ProducerInterceptor interface allows you to intercept (and possibly mutate) the records received by the producer before they are published to the Kafka cluster. By default, there are no interceptors. list null low max.in.flight.requests.per.connection The maximum number of unacknowledged requests the client will send on a single connection before blocking. Note that if this setting is set to be greater than 1 and there are failed sends, there is a risk of message re-ordering due to retries (i.e., if retries are enabled). int 5 [1,…] low metadata.fetch.timeout.ms The first time data is sent to a topic we must fetch metadata about that topic to know which servers host the topic’s partitions. This fetch to succeed before throwing an exception back to the client. long 60000 [0,…] low metadata.max.age.ms The period of time in milliseconds after which we force a refresh of metadata even if we haven’t seen any partition leadership changes to proactively discover any new brokers or partitions. long 300000 [0,…] low metric.reporters A list of classes to use as metrics reporters. Implementing the MetricReporter interface allows plugging in classes that will be notified of new metric creation. The JmxReporter is always included to register JMX statistics. list [] low metrics.num.samples The number of samples maintained to compute metrics. int 2 [1,…] low metrics.sample.window.ms The window of time a metrics sample is computed over. long 30000 [0,…] low reconnect.backoff.ms The amount of time to wait before attempting to reconnect to a given host. This avoids repeatedly connecting to a host in a tight loop. This backoff applies to all requests sent by the consumer to the broker. long 50 [0,…] low retry.backoff.ms The amount of time to wait before attempting to retry a failed request to a given topic partition. This avoids repeatedly sending requests in a tight loop under some failure scenarios. long 100 [0,…] low sasl.kerberos.kinit.cmd Kerberos kinit command path. string /usr/bin/kinit low sasl.kerberos.min.time.before.relogin Login thread sleep time between refresh attempts. long 60000 low sasl.kerberos.ticket.renew.jitter Percentage of random jitter added to the renewal time. double 0.05 low sasl.kerberos.ticket.renew.window.factor Login thread will sleep until the specified window factor of time from last refresh to ticket’s expiry has been reached, at which time it will try to renew the ticket. double 0.8 low ssl.cipher.suites A list of cipher suites. This is a named combination of authentication, encryption, MAC and key exchange algorithm used to negotiate the security settings for a network connection using TLS or SSL network protocol.By default all the available cipher suites are supported. list null low ssl.endpoint.identification.algorithm The endpoint identification algorithm to validate server hostname using server certificate. string null low ssl.keymanager.algorithm The algorithm used by key manager factory for SSL connections. Default value is the key manager factory algorithm configured for the Java Virtual Machine. string SunX509 low ssl.trustmanager.algorithm The algorithm used by trust manager factory for SSL connections. Default value is the trust manager factory algorithm configured for the Java Virtual Machine. string PKIX low
  • 3.3 消费者(consumer)配置

    • 3.3.1 旧版消费者配置

    • 3.3.2 新版消费者配置

      新版还是beta版

Name Description Type Default Valid Values Importance bootstrap.servers 用于客户端向服务器建立初始连接的kafka broker ip及端口集。与producer中配置相同。 list high key.deserializer 实现了接口Deserializer 的类,用于反序列化key.与producer中的key.serialzer对应。 class high value.deserializer 实现了接口Deserializer 的类,用于反序列化value.与producer中的value.serialzer对应。 class high fetch.min.bytes 批量读,数据量最小限止。 一次拉取请求返回给客户端的最小数据量。如果数据小于此值,服务器不会立即返回请求,而是等待更多数据,至到超过此值。 默认值为1字节,也就是说每次请求都会立即返回。此配置可以提高吞吐量,不过会增加延迟。 int 1 [0,…] high group.id 一个标识多个consumer为一组,且为字符串类型的唯一值。对于集群环境此值非常有用,只有集群中一台机器可以消费,防止重复消费。 主题决定了哪些消费者可以消费。group.id决定了同一个主题的多个消费者同一消费只能被一个消费(互斥)。 A unique string that identifies the consumer group this consumer belongs to. This property is required if the consumer uses either the group management functionality by using subscribe(topic) or the Kafka-based offset management strategy. string "" high heartbeat.interval.ms The expected time between heartbeats to the consumer coordinator when using Kafka’s group management facilities. Heartbeats are used to ensure that the consumer’s session stays active and to facilitate rebalancing when new consumers join or leave the group. The value must be set lower than session.timeout.ms, but typically should be set no higher than 1/3 of that value. It can be adjusted even lower to control the expected time for normal rebalances. int 3000 high max.partition.fetch.bytes The maximum amount of data per-partition the server will return. The maximum total memory used for a request will be #partitions * max.partition.fetch.bytes.This size must be at least as large as the maximum message size the server allows or else it is possible for the producer to send messages larger than the consumer can fetch. If that happens, the consumer can get stuck trying to fetch a large message on a certain partition. int 1048576 [0,…] high session.timeout.ms The timeout used to detect failures when using Kafka’s group management facilities. When a consumer’s heartbeat is not received within the session timeout, the broker will mark the consumer as failed and rebalance the group. Since heartbeats are sent only when poll() is invoked, a higher session timeout allows more time for message processing in the consumer’s poll loop at the cost of a longer time to detect hard failures.See also max.poll.records for another option to control the processing time in the poll loop. Note that the value must be in the allowable range as configured in the broker configuration by group.min.session.timeout.ms and group.max.session.timeout.ms. int 30000 high ssl.key.password The password of the private key in the key store file. This is optional for client. password null high ssl.keystore.location The location of the key store file. This is optional for client and can be used for two-way authentication for client. string null high ssl.keystore.password The store password for the key store file.This is optional for client and only needed if ssl.keystore.location is configured. password null high ssl.truststore.location The location of the trust store file. string null high ssl.truststore.password The password for the trust store file. password null high auto.offset.reset What to do when there is no initial offset in Kafka or if the current offset does not exist any more on the server (e.g. because that data has been deleted):
  • earliest: automatically reset the offset to the earliest offset
  • latest: automatically reset the offset to the latest offset
  • none: throw exception to the consumer if no previous offset is found for the consumer’s group
  • anything else: throw exception to the consumer.
string latest [latest, earliest, none] medium connections.max.idle.ms Close idle connections after the number of milliseconds specified by this config. long 540000 medium enable.auto.commit 偏移量是由consumer维护,并不代表是存储在本客户端(客户端无处可存,且对于多个group消费者无法实现互斥消费),实际上是存储在zookeeper。 因此offset可以由服务器代为维护。 boolean true medium exclude.internal.topics Whether records from internal topics (such as offsets) should be exposed to the consumer. If set to true the only way to receive records from an internal topic is subscribing to it. boolean true medium max.poll.records 一次请求返回批量数据的上限。一次拉取,最多返回的消息条数。 此数据默认值过大,生产环境最好设置一个更小的值(我自己瞎猜的)。 int 2147483647 [1,…] medium partition.assignment.strategy The class name of the partition assignment strategy that the client will use to distribute partition ownership amongst consumer instances when group management is used list [org.apache.kafka.clients.consumer.RangeAssignor] medium receive.buffer.bytes 用于接收消费的TCP缓冲大小. int 65536 [0,…] medium request.timeout.ms 请求超时时间。超过时间,客户端会失败重发(客户端重发在哪里配置?),或者重发过多时失败。 int 40000 [0,…] medium sasl.kerberos.service.name The Kerberos principal name that Kafka runs as. This can be defined either in Kafka’s JAAS config or in Kafka’s config. string null medium sasl.mechanism SASL mechanism used for client connections. This may be any mechanism for which a security provider is available. GSSAPI is the default mechanism. string GSSAPI medium security.protocol Protocol used to communicate with brokers. Valid values are: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL. string PLAINTEXT medium send.buffer.bytes 发送数据的TCP缓冲大小。 int 131072 [0,…] medium ssl.enabled.protocols The list of protocols enabled for SSL connections. list [TLSv1.2, TLSv1.1, TLSv1] medium ssl.keystore.type The file format of the key store file. This is optional for client. string JKS medium ssl.protocol The SSL protocol used to generate the SSLContext. Default setting is TLS, which is fine for most cases. Allowed values in recent JVMs are TLS, TLSv1.1 and TLSv1.2. SSL, SSLv2 and SSLv3 may be supported in older JVMs, but their usage is discouraged due to known security vulnerabilities. string TLS medium ssl.provider The name of the security provider used for SSL connections. Default value is the default security provider of the JVM. string null medium ssl.truststore.type The file format of the trust store file. string JKS medium auto.commit.interval.ms 如果 enable.auto.commit 设置为 true,那么此值为自动提交的频率(单位:毫秒)。 即:每auto.commit.interval.ms自动提交一次offsets。 long 5000 [0,…] low check.crcs Automatically check the CRC32 of the records consumed. This ensures no on-the-wire or on-disk corruption to the messages occurred. This check adds some overhead, so it may be disabled in cases seeking extreme performance. boolean true low client.id 一个发送到服务器的id。目的是通过一个有意义的值用于跟踪请求源,而不仅仅通过ip/port来跟踪。如:使用应用名。 string "" low fetch.max.wait.ms The maximum amount of time the server will block before answering the fetch request if there isn’t sufficient data to immediately satisfy the requirement given by fetch.min.bytes. int 500 [0,…] low interceptor.classes 消费者拦截器列表。实现了ConsumerInterceptor 接口的类允许拦截消费者收到的所有消息(可能对消息做统一修改)。默认情况下,没有配置任何拦截器。 list null low metadata.max.age.ms The period of time in milliseconds after which we force a refresh of metadata even if we haven’t seen any partition leadership changes to proactively discover any new brokers or partitions. long 300000 [0,…] low metric.reporters A list of classes to use as metrics reporters. Implementing the MetricReporter interface allows plugging in classes that will be notified of new metric creation. The JmxReporter is always included to register JMX statistics. list [] low metrics.num.samples The number of samples maintained to compute metrics. int 2 [1,…] low metrics.sample.window.ms The window of time a metrics sample is computed over. long 30000 [0,…] low reconnect.backoff.ms 链接失败重试,间隔时间。当链接失败,间隔一定时间后再重试,防止短时间内,死循环式快速重试。 此配置对从当前consumer发出的所有请示有效。 long 50 [0,…] low retry.backoff.ms 失败重试,间隔时间。当请求失败时,间隔一定时间后再失败重试。防止短时间内,由于一些错误原因,导致死循环式快速失败重发。 long 100 [0,…] low sasl.kerberos.kinit.cmd Kerberos kinit command path. string /usr/bin/kinit low sasl.kerberos.min.time.before.relogin Login thread sleep time between refresh attempts. long 60000 low sasl.kerberos.ticket.renew.jitter Percentage of random jitter added to the renewal time. double 0.05 low sasl.kerberos.ticket.renew.window.factor Login thread will sleep until the specified window factor of time from last refresh to ticket’s expiry has been reached, at which time it will try to renew the ticket. double 0.8 low ssl.cipher.suites A list of cipher suites. This is a named combination of authentication, encryption, MAC and key exchange algorithm used to negotiate the security settings for a network connection using TLS or SSL network protocol.By default all the available cipher suites are supported. list null low ssl.endpoint.identification.algorithm The endpoint identification algorithm to validate server hostname using server certificate. string null low ssl.keymanager.algorithm The algorithm used by key manager factory for SSL connections. Default value is the key manager factory algorithm configured for the Java Virtual Machine. string SunX509 low ssl.trustmanager.algorithm The algorithm used by trust manager factory for SSL connections. Default value is the trust manager factory algorithm configured for the Java Virtual Machine. string PKIX low
  • 3.4 kafka Connect 配置

    Name Description Type Default Valid Values Importance config.storage.topic kafka topic to store configs string high group.id A unique string that identifies the Connect cluster group this worker belongs to. string high internal.key.converter Converter class for internal key Connect data that implements the Converter interface. Used for converting data like offsets and configs. class high internal.value.converter Converter class for offset value Connect data that implements the Converter interface. Used for converting data like offsets and configs. class high key.converter Converter class for key Connect data that implements the Converter interface. class high offset.storage.topic kafka topic to store connector offsets in string high status.storage.topic kafka topic to track connector and task status string high value.converter Converter class for value Connect data that implements the Converter interface. class high bootstrap.servers A list of host/port pairs to use for establishing the initial connection to the Kafka cluster. The client will make use of all servers irrespective of which servers are specified here for bootstrapping—this list only impacts the initial hosts used to discover the full set of servers. This list should be in the form host1:port1,host2:port2,.... Since these servers are just used for the initial connection to discover the full cluster membership (which may change dynamically), this list need not contain the full set of servers (you may want more than one, though, in case a server is down). list [localhost:9092] high cluster ID for this cluster, which is used to provide a namespace so multiple Kafka Connect clusters or instances may co-exist while sharing a single Kafka cluster. string connect high heartbeat.interval.ms The expected time between heartbeats to the group coordinator when using Kafka’s group management facilities. Heartbeats are used to ensure that the worker’s session stays active and to facilitate rebalancing when new members join or leave the group. The value must be set lower than session.timeout.ms, but typically should be set no higher than 1/3 of that value. It can be adjusted even lower to control the expected time for normal rebalances. int 3000 high session.timeout.ms The timeout used to detect failures when using Kafka’s group management facilities. int 30000 high ssl.key.password The password of the private key in the key store file. This is optional for client. password null high ssl.keystore.location The location of the key store file. This is optional for client and can be used for two-way authentication for client. string null high ssl.keystore.password The store password for the key store file.This is optional for client and only needed if ssl.keystore.location is configured. password null high ssl.truststore.location The location of the trust store file. string null high ssl.truststore.password The password for the trust store file. password null high connections.max.idle.ms Close idle connections after the number of milliseconds specified by this config. long 540000 medium receive.buffer.bytes The size of the TCP receive buffer (SO_RCVBUF) to use when reading data. int 32768 [0,…] medium request.timeout.ms The configuration controls the maximum amount of time the client will wait for the response of a request. If the response is not received before the timeout elapses the client will resend the request if necessary or fail the request if retries are exhausted. int 40000 [0,…] medium sasl.kerberos.service.name The Kerberos principal name that Kafka runs as. This can be defined either in Kafka’s JAAS config or in Kafka’s config. string null medium sasl.mechanism SASL mechanism used for client connections. This may be any mechanism for which a security provider is available. GSSAPI is the default mechanism. string GSSAPI medium security.protocol Protocol used to communicate with brokers. Valid values are: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL. string PLAINTEXT medium send.buffer.bytes The size of the TCP send buffer (SO_SNDBUF) to use when sending data. int 131072 [0,…] medium ssl.enabled.protocols The list of protocols enabled for SSL connections. list [TLSv1.2, TLSv1.1, TLSv1] medium ssl.keystore.type The file format of the key store file. This is optional for client. string JKS medium ssl.protocol The SSL protocol used to generate the SSLContext. Default setting is TLS, which is fine for most cases. Allowed values in recent JVMs are TLS, TLSv1.1 and TLSv1.2. SSL, SSLv2 and SSLv3 may be supported in older JVMs, but their usage is discouraged due to known security vulnerabilities. string TLS medium ssl.provider The name of the security provider used for SSL connections. Default value is the default security provider of the JVM. string null medium ssl.truststore.type The file format of the trust store file. string JKS medium worker.sync.timeout.ms When the worker is out of sync with other workers and needs to resynchronize configurations, wait up to this amount of time before giving up, leaving the group, and waiting a backoff period before rejoining. int 3000 medium worker.unsync.backoff.ms When the worker is out of sync with other workers and fails to catch up within worker.sync.timeout.ms, leave the Connect cluster for this long before rejoining. int 300000 medium access.control.allow.methods Sets the methods supported for cross origin requests by setting the Access-Control-Allow-Methods header. The default value of the Access-Control-Allow-Methods header allows cross origin requests for GET, POST and HEAD. string "" low access.control.allow.origin Value to set the Access-Control-Allow-Origin header to for REST API requests.To enable cross origin access, set this to the domain of the application that should be permitted to access the API, or ‘*’ to allow access from any domain. The default value only allows access from the domain of the REST API. string "" low client.id An id string to pass to the server when making requests. The purpose of this is to be able to track the source of requests beyond just ip/port by allowing a logical application name to be included in server-side request logging. string "" low metadata.max.age.ms The period of time in milliseconds after which we force a refresh of metadata even if we haven’t seen any partition leadership changes to proactively discover any new brokers or partitions. long 300000 [0,…] low metric.reporters A list of classes to use as metrics reporters. Implementing the MetricReporter interface allows plugging in classes that will be notified of new metric creation. The JmxReporter is always included to register JMX statistics. list [] low metrics.num.samples The number of samples maintained to compute metrics. int 2 [1,…] low metrics.sample.window.ms The window of time a metrics sample is computed over. long 30000 [0,…] low offset.flush.interval.ms Interval at which to try committing offsets for tasks. long 60000 low offset.flush.timeout.ms Maximum number of milliseconds to wait for records to flush and partition offset data to be committed to offset storage before cancelling the process and restoring the offset data to be committed in a future attempt. long 5000 low reconnect.backoff.ms The amount of time to wait before attempting to reconnect to a given host. This avoids repeatedly connecting to a host in a tight loop. This backoff applies to all requests sent by the consumer to the broker. long 50 [0,…] low rest.advertised.host.name If this is set, this is the hostname that will be given out to other workers to connect to. string null low rest.advertised.port If this is set, this is the port that will be given out to other workers to connect to. int null low rest.host.name Hostname for the REST API. If this is set, it will only bind to this interface. string null low rest.port Port for the REST API to listen on. int 8083 low retry.backoff.ms The amount of time to wait before attempting to retry a failed request to a given topic partition. This avoids repeatedly sending requests in a tight loop under some failure scenarios. long 100 [0,…] low sasl.kerberos.kinit.cmd Kerberos kinit command path. string /usr/bin/kinit low sasl.kerberos.min.time.before.relogin Login thread sleep time between refresh attempts. long 60000 low sasl.kerberos.ticket.renew.jitter Percentage of random jitter added to the renewal time. double 0.05 low sasl.kerberos.ticket.renew.window.factor Login thread will sleep until the specified window factor of time from last refresh to ticket’s expiry has been reached, at which time it will try to renew the ticket. double 0.8 low ssl.cipher.suites A list of cipher suites. This is a named combination of authentication, encryption, MAC and key exchange algorithm used to negotiate the security settings for a network connection using TLS or SSL network protocol.By default all the available cipher suites are supported. list null low ssl.endpoint.identification.algorithm The endpoint identification algorithm to validate server hostname using server certificate. string null low ssl.keymanager.algorithm The algorithm used by key manager factory for SSL connections. Default value is the key manager factory algorithm configured for the Java Virtual Machine. string SunX509 low ssl.trustmanager.algorithm The algorithm used by trust manager factory for SSL connections. Default value is the trust manager factory algorithm configured for the Java Virtual Machine. string PKIX low task.shutdown.graceful.timeout.ms Amount of time to wait for tasks to shutdown gracefully. This is the total amount of time, not per task. All task have shutdown triggered, then they are waited on sequentially. long 5000 low
    • ## 3.5 kafka Streams 配置

4. 设计

  • 4.1 动机

    我们设计 kafka的目的是为了提供了一个处理所有实时数据汇总的统一平台。为了实现这个目标,我们不得不考虑各种各样的用例。

    首先,它应该是一个可以以高吞吐量的方式来处理像实时日志收集一样的高容量事件流。

    其次,能优雅处理离线系统周期性加载数据而导致的大批量数据积压。

    另外,它能够处理低延迟的处理传统的点对点消息传递。

    我们希望能支持分区,分布式,实时处理汇总的数据,传递。这促成了我们的分区和消费者模型。

    在流信息被传递给其它数据系统时,我们知道系统必须能保证在机器出错故障时具有容错能力。

    为了支持上面这些想法,我们设计了一些相对于传统消息系统更像数据库日志的独特组件。在下面的章节中,我们会概述其中一部分设计。

  • 4.2 持久化

    不要害怕文件系统
    kafka 强依赖文件系统来存储和缓存消息。一个普遍的看法是“磁盘很慢”,这也使人们怀疑一个提供持久化功能的系统在性能上有没有竞争力。事实上,磁盘说慢非常慢,说快也很快。只要正确使用,正确设计磁盘结构,会让磁盘跟网络一样快。

    磁盘性能的关键事实是:在过去十年中,磁盘的吞吐量已经受到磁盘寻址的严重影响(翻译不到位,可以看原文)。因此,一个配置了6块 six 7200转每分钟的 SATA RAID-5 磁盘阵列,线性写可以达到600MB/秒。但是相同配置随机写只有100k/秒。整整相差了6000多倍。线性读写是所有使用方式中最容易想到的。并且也是被操作系统做了很大优化的方式。一个现代操作系统,会提供预读和延迟写技术来处理数据。预取即一次性取很多数据块。延迟写即把一组小的逻辑写整合成一次大的物理写。这也说明,顺序访问磁盘会比随机访问要快很多。

    为了弥补性能损失,现代操作系统更激进的使用主存来充当磁盘内存。一个现代os会很乐意使用所有的空闲内存来充当磁盘缓存(pageCache)。只有在缓存回收(其它进程申请缓存,且缓存不够时,回收pageCache)时损失一点性能(要写回磁盘)。磁盘的所有读写都将通过这个统一的缓存间接读取。如果不使用直接磁盘io,这个特性很难关闭。因此,即使一个进程维护了一个进程内的数据缓存,那么数据很可能被复制到os pageCache中,所有数据都会被有效存储两次。

    此外,我们是建立在jvm之上。研究过java内存的都了解以下两点:

    • (1) 对象的内存开销非常高,通常是数据存储的倍数,或者更糟。
    • (2) 随着堆内存数据增加,java垃圾收集变的越来越困难。

    因为这些特性,使用文件系统以及依赖pageCache比直接使用内存(虽然pageCache也在内存中,但不像jvn直接使用内存,而是通过pageCache间接使用:不知道理解是否正确)或其它结构。我们通过自动连接到空闲内存,至少让可用内存翻倍(有空闲内存就使用,其它程序申请就释放,不固定占有--相同jvm head)。 通过存储压缩过字节数据比存储对象,我们可能还能让可用内存翻倍。这就使在一个32G内存的机器上缓存28-30G也不会触发GC。另外,即使服务重启了,缓存仍然存在。相反,进程内的缓存会全部丢失(重新加载需要花费很长时间)--(注意:是服务重启,并不是机器重器。pageCache是在内存中,由os管理,与进程无直接关系,因此不会丢失)。
    这也简化了维护缓存与文件系统之间一致性的编程逻辑。这比使用一次性的进程内缓存更有效也更正确。

    这意味着这是一个非常简单的设计:不用担心因为直接使用内存(进程内维护),刷新内存到文件系统时出现内存溢出导致数据丢失。所有数据立即写持久化日志到文件系统(os层面,而磁盘,此处批的是pageCache ),而不是直接刷新到磁盘。这也意味着把数据转移到内核的pageCache。

    通过pageCache和顺序读写来提高性能
    pageCache是非进程内,所以不受大小限制,不会被jvm GC。而且可以随时使用空闲内存,以及自由释放(别人不用我用,别人用我立马还)
    而且,进程中内存也同时会有pageCache,所以是重复。

    顺序读写:是随机读写性能的6000倍。

    恒定的时间复杂度

    大部分持久化数据结构都会选择BTree,这能提供丰富的存取,它的时间复杂度为o(logN)。但是kafka使用更简单的方式,向文件中追加数据,或从文件中顺序读数据。缺点就是不提供丰富的读写方式(如:按某属性检索指定数据)。

  • 4.3 效率

    我们在效率上投入了大量努力。我们最主要的一个用例就是处理网站活动数据。网站活动数据容量非常大:每个页面浏览都可能产生几个写操作。另外,每条消息都至少有一个(通常很多)消费者消息。因此,我们努力让消息消费的代价变的尽可能小。

    上一节我们讨论了磁盘效率,影响磁签署效率主要有两个原因:过多的小型i/o操作,和大量的字节复制。

    小型i/o即发生在客户端与服务器之间,又发生在服务器自己的持久化操作中。

    为了消除上述情况,我们创建了一个“消息集”的抽象概念,即消息按自然分组组合在一起。这种机制允许网络请示可以一次把多个消息分组打包在一起发送,这样可以分摊一次请求只发一条消息而带来的网络开销。服务器可以一次性把打包在一起的消息追加到日志中。消费者也可以整包消费消息。

    这个简单的优化让速度提升了一个数量级。批量操作导致大的网络数据包,大的磁盘线性操作,以及连序的内存块等等。所有这些,都让kafka能把随机的消息流以线性的方式写入,并发送给消费者。

    另外一影响性能的是字节复制。在低消息率(消息量小)的情况下,这不是问题。但是在大量负载的情况下,这影响是显著的。为了消除这个,我们采用了一个标准的二进制消息格式。生产者、消费者、代理都遵守这个标准(因此数据包在传递过程中不需要修改)。

    消息日志本身就是一个由broker维护的文件集目录。这些文件顺序存储着消息集。这些消息存储格式与生产者和消费者使用了相同的格式(传统的mq可能使用不的格式:如生产者使用字符串,代理使用二进制,消费者又使用字符串)。保持通用的格式可以优化一个最重要的操作:持久化日志块的网络传输。现代unix 操作系统,为从pagecache向socker传输数据提供了一个高度优化的编程方式。
    在linux下,这个是通过“ sendfile system call.”实现的

    为了理解sendFile的影响,需要了解数据从文件到socket的传输路径。

    • (1). 操作系统把数据从磁盘上读到内核空间中的pagecache中。
    • (2). 应用程序把数据从内核空间读到用户空间的缓冲中。
    • (3). 应用程序把数据写回到内核空间的socket缓冲中。
    • (4). 操作系统把数据从socket缓冲中复制到NIC 缓冲中。然后发送到网络上。

    消息传输过程1
    四个副本,两次系统调用,这显然是低效。通过使用sendfile可以消除重复复制。它是允许os直接把数据从pagecache复制到network。

    消息传输过程1
    kafka消息传输图解

    我们希望针对一个主题多个消费者的情况能有一个通用的用例。使用上面零复制优化方案,数据从磁盘到pagecache,只复制一次。多次消费共用同一个pagecache的数据。而不像那种把数据放到内存的做法,每次读都会把数据从内核中复制出去。这让消息的消费速率基本接近网络传输的最高限制。

    把pagecache和sendfile结合起使用,让kafka集群,你会发现基本没有读取磁盘的操作,因此数据完全从缓存中读取(基本没有读操作,并不代表没有写操作。此处有一个前提:生产者和消费者同时在线,生产者生产的数据放入pagecache中,还没有被回收时,就被消费者消费,因此基本不需要再从磁盘读到pagecache)。

    点到点的批量压缩

    在一些情况下,cpu和磁盘并不是瓶颈,网络带宽才瓶颈。对于霜从数据中心向广域网发消息的数据管道,确实是这样的。当然,用户可以一次压缩一条消息(完全不需要kafka的支持即可)。但是这可能导致很低的压缩率。因为一条消息的冗余数据并不多。如果想提高压缩率,应该多条相同类型的消息一起批量压缩(相同类型的消息它们结构相同,那么属性名就高度冗余)。

    kafka支持循环递归消息集(具体参考:MessageSet)。一批消息可以一起压缩并以压缩的格式一起发送到服务器。这批消息会以压缩格式存储在日志中。只有在被消息时被消费者解压。

    kafka支持 GZIP, Snappy,LZ4压缩协议。更多细节看这里

  • 4.4 生成者

    负载均衡

    生产者直接发送数据到代理。代理是没有任何中间路由层的。为了帮助代理实现路由,每个kafka节点能提供在作何时间获取服务器元数据的请求。这些元数据包括哪些服务器牌激活状态,同一个主题分区的领导者位置信息(如:ip/端品)。

    客端控制消息发布到哪个分区。这种控制算法可是随机的(随机负载均衡),或者通过一些语议分区涵数。我们公开了语议分区接口,允许用户提供一个消息键,通过这个键hash到不同的分区(当然如果需要,可以重写分区函数)。例如:如果消息键是一个用户id,那么同一个用户的所有消息都会被发送到相同的分区上,反过来消费者消息时就可以(???)。这种设计方式,是为了对位置敏感的消费者(??:估计类似于分布式session)

    异步发送

    批量发送是效率的主要因素。为了批量操作,kafka生产者通过在内存中缓存数据,并一次请求发送较大的批次。批量操作可以通过配置一个消息数量上限和一个延迟时间(64k或10ms)来控制批量操作。这样就允许一次请求可以发送更消息,让服务器使用更少量但是更大的i/o操作。缓存是可配置的,为牺牲少量延迟但是提供更高吞吐量的追求提供了一个可选机制。

  • 4.5 消费者

    kafka消费者通过拉的方式从代理消费消息。消费者在每次请求中指定它在消息日志中的偏移量(从哪个位置开始消费),并从该位置接收一个日志块。因此,消费者可以控制偏移量位置,并在需要时重新消费已消费过的数据。

    推送 vs 拉取

    一个我们考虑的问题是,消费者是应该从代理拉取数据,还是代理把数据推给消费者。 在这方面,kafka选择了一个大多数消息系统者会使用,但更传统的方式:生产者主动把数据推送到代理,消费者主动从代理拉取数据。一些以日志为中心的系统,例如: Scribe和Apache Flume,是基于推送的方式把数据推到下流系统。这两种方式各有利弊,但是基于推的系统,因为代理控制了数据传输速率,所以很难处理各种不同类型的消费者。一般来说,我们的目标是为了让消费者尽可能以最大的效率消息消息。但是,基于推的系统,如果消费端消费速率跟不上生产速率,就会导致过载。基于拉的系统有更好的特性,消费者可以落后生产者,只是在消费者有能力的情况下追赶生产者即可。这种方式可以通过某种补偿协议实现。消费者可以表示自己过载,但是仍然可以充分利用传输速率。因此,我们选择使用拉模型。

    基于拉的系统还有另外一个优点:消费者可以主动批量操作数据。一个基于推的系统,在不知道消费者是否会立即处理的情况下,必须选择是立即推送还是缓存更多数据后批量推送。如果需要低延迟,就必须一次一条消息的方式发送,这太浪费了。基于拉的设计修复了这个缺陷,因为消费者可以从日志的当前位置拉取后面的所有消息(可以配置最大拉取数量)。因此在不会引起不必要的延迟的情况下,这是一个最佳的批处理方式。

    一个简单的基于拉的系统有一个不足之处就是:如果代理没有数据了,消费者可能仍然循环拉取数据。为了消除这个,我们在请求的提供了参数,让以通过长连接的方式来阴塞一个请求,至到代理有数据时再返回。

    消费者位置

    让人惊讶的是,跟踪哪些消息被消费了,是影响一个消息系统性能的一个关键点。大多消息系统都会在代理上保存哪些消息被消费的元数据。也就是说,消息一旦分发给消费者,代理就要立即在本地记录下,或者等消费者确认。这是一个直观的选择。事实上,对一个单一人服务器,这种状态除此之外还能存到哪儿。由于许多消息系统存储的消息规模并不大,因此这也是一个务实的选择。代理知道哪些消息已经消费了,并可以立即删除,因此可以保持一个很小量的数据存储。

    让代理和消费者对消息是否已经消费达成协议到底是不是一个微不足道的问题也许很不明显。如果消息每次通过网络分发出去,代理就必须马上记录下来,如果消费者处理消息失败了(如:超时了,或崩溃了),那么消息可能就丢失了。为了解决这个问题,许多消息系统增加了一个回执确认的特性。也就是说,消息一是发出,消息会被标记为“发送”状态而不是”已消费”状态。代理等待消费者回执确认后,再把消息标记为已消息。但是,这又带来了新的问题,首先,如果消费者处理完消息,在发送回执的时候失败了,那么消息可能会被消费两次。现在为了解决这个问题,代理必须对每条消息保存多个状态(一个是加锁,以至不会发送第二次。第二可删除状态),这个会影响性能。

    kafka使用不同的处理方式。主题被切分成小的顺序的分区集合。每一个分区同一时间只能被一个消费者消费。这就意味着一个消费者的位置在每个分区上只用一个integer字段就可标记下一条消息的偏移量。这使得消息被消费的状态维护非常小。状态要以定期状态,这使消息确认代价非常小。

    kafka采用的这种方式有个副作用。一个消费者可以故意倒回去消息已经被消费的数据。这违反了队列的通用协议。但是这原来就应该是大多数消费者的重要特性。例如,如果消费者代码有一个bug,在消息被消费以后才发与,那么在bug修复以后可以重新消费消息。

    离线数据加载

    可扩展的持久化特性使这些消费者成为可能。像:定期批量加载数据到离线系统的消费者(hadooop或关系型数据仓库)
    在hadoop并行加载数据的情况下我们通过拆分map-task,每个节点/主题/分区都允许并行加载。hadoop提供task管理,任务失败时,可以重新从原来的位置加载(不用担心失败,因为有副本)。

  • 4.6 消息传递语义

    待…

  • 4.7 复制

    kafka复制每个主题的分区日志,如果配置了多台服务。这允许集群中一台服务失效后,通过副本仍然能保持消息的可用性。

    别的消息系统也提供了相关的复制特性(kafka是完全基于副本),但是它们感觉就是一个附加的,没有完全使用的,有很大缺点:奴隶服务器是非激活状态,吞叶量严重影响,它需要手动配置等等。kafka默认就是基于副本,事实上,我们(???)

    副本的最小单位主题分区。在没有失败的情况下,每个kafka分区有一个leader和0个或更多followers。副本总数(包括leader)组成了副本因子。所有的读写都由leader的分区上处理。通常,有比leader多很多的分区。leader均匀的分布在所有broker上。followers上的副本日志与leader保持完全一样:都有相同的偏移量,消息拥有相同的顺序(当然,在任何时间,leader日志未尾有几条还没有复制的消息-因为延迟)。

    followers从leader消费消息就像一个普通的消费者,把消息追加他们日志(不是复制文件的方式创建副本,而是假装成消费者从leader消费)。followers从leader批量处理日志。

    像大多数分布式系统自动处理故障一样,需要对节点的“激活”状态有一个明确的定义。对kafka节点而言,需要满足两个我们的:
    节点必须能与zookeeper保持会话(心跳机制)。如果节点是一个奴隶节点,它必须能复制leader上的所有写操作,并且不能落后太多。我们指的节点满足这两个条件叫做“同步”。为了避免“激活”和”“失败”这两个概念的含糊不清。leader跟踪“同步”的所有节点集合。如果followers挂了,或者卡住了,或者落后太多(复制的太慢),那么leader就从它的同步副本中删除。卡住或滞后的副本控制是由 replica.lag.time.max.ms 配置。

    在分布式系统术语中,我只试图处理“失败/恢复”模型,如:节点突然息火了,然后重新恢复。kafka不处理“拜占庭”式错误。这些节点产生随意或恶意的反应(可能是因为bug或者违规操作)

    一条消息只有当所有同步副本把消息都追加到它们的分区日志中才称为“已提交”。只有“已提交”的消息才会发送给消费者。这意味消费者不需要担心它们看到消息会因为leader挂掉而消失。另一方面,生产者可以选择是等待消息处于“已提交”状态还是不需要等待。这取决于为了低延迟还是持久化之间的权衡。这是通过生产者的”acks”配置来控制。

    做为kafka心脏的分区,kafka分区是一自制的日志。副本是分布式系统最基础的原语之一。有许多实现方法。副本可以被一些使用,但是由其它分布式系统以状态模式的方式实现。

    一个日志复制模型,就是处理一系统值时顺序保持一致。有很多方法可以实现,但是有一个最简单也是最快的方式:选一个leader,由这个leader来选择提供给它的值的顺序。只要leader是激活的,所有followers只要复制leader所选的顺序就可以保证所有副本消息顺序的一致性。

    当然,如果leader没有失效,我们是不是需要followers的。但是,当leader挂了时,我们需要从followers中选一个新的leader。不过,followers本身也可能落后太多,或者崩溃。因此我们必须保证我们选择一个最新的follower。一个日志副本的基本保证的算法是:如果我们告诉客户端消息已经提交了,此时leader失效了,那么选出的新leader必须包含那条消息。这就需要一个折衷,如果一条消息在被标明“己提交”之前等待更多的follower确认,那么它在失效后,会有更多的follower可以做为新的leader,这会造成吞吐量降。

    法定人数:???todo

    一个常用的的算法是:majority vote(“少数服从多数”),但Kafka并未采用这种方式。这种模式下,如果我们有2f+1个Replica(包含Leader和Follower),那在commit之前必须保证有f+1个Replica复制完消息,为了保证正确选出新的Leader,fail的Replica不能超过f个。因为在剩下的任意f+1个Replica里,至少有一个Replica包含有最新的所有消息。这种方式有个很大的优势,系统的latency只取决于最快的几个Broker,而非最慢那个。Majority Vote也有一些劣势,为了保证Leader Election的正常进行,它所能容忍的fail的follower个数比较少。如果要容忍1个follower挂掉,必须要有3个以上的Replica,如果要容忍2个Follower挂掉,必须要有5个以上的Replica。也就是说,在生产环境下为了保证较高的容错程度,必须要有大量的Replica,而大量的Replica又会在大数据量下导致性能的急剧下降。这就是这种算法更多用在ZooKeeper这种共享集群配置的系统中而很少在需要存储大量数据的系统中使用的原因。例如HDFS的HA Feature是基于majority-vote-based journal,但是它的数据存储并没有使用这种方式。

    实际上,Leader Election算法非常多,比如ZooKeeper的Zab, Raft和Viewstamped Replication。而Kafka所使用的Leader Election算法更像微软的PacificA算法。

    Kafka在ZooKeeper中动态维护了一个ISR(in-sync replicas),这个ISR里的所有Replica都跟上了leader,只有ISR里的成员才有被选为Leader的可能。在这种模式下,对于f+1个Replica,一个Partition能在保证不丢失已经commit的消息的前提下容忍f个Replica的失败。在大多数使用场景中,这种模式是非常有利的。事实上,为了容忍f个Replica的失败,Majority Vote和ISR在commit前需要等待的Replica数量是一样的,但是ISR需要的总的Replica的个数几乎是Majority Vote的一半。

    虽然Majority Vote与ISR相比有不需等待最慢的Broker这一优势,但是Kafka作者认为Kafka可以通过Producer选择是否被commit阻塞来改善这一问题,并且节省下来的Replica和磁盘使得ISR模式仍然值得。

    不纯洁的leader选举:如果所有副本都失效了怎么办?

    kafka保证数据不丢失的前提是:至少有一个副本是同步的。如果所有节点的分区副本都失效了,就无法保证数据不丢失。

    如果真发生了这种事情,那么有两个方案:

    • 等待ISR中的任一个Replica“活”过来,并且选它作为Leader
    • 选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader

    这就需要在可用性和一致性当中作出一个简单的折衷。如果一定要等待ISR中的Replica“活”过来,那不可用的时间就可能会相对较长。而且如果ISR中的所有Replica都无法“活”过来了,或者数据都丢失了,这个Partition将永远不可用。选择第一个“活”过来的Replica作为Leader,而这个Replica不是ISR中的Replica,那即使它并不保证已经包含了所有已commit的消息,它也会成为Leader而作为consumer的数据源(前文有说明,所有读写都由Leader完成)。Kafka0.8.*使用了第二种方式。根据Kafka的文档,在以后的版本中,Kafka支持用户通过配置选择这两种方式中的一种,从而根据不同的使用场景选择高可用性还是强一致性。

    可用性和持久性

    当向kafka写入消息时,生产者可以选择是否等待消息被commited的确认(0,1,all(-1))。注意,all(-1),不保证所有的副本都收到消息了。默认情况下,acks=all,只保证所有“同步”(为了性能,一般只选指定数量的副本做为同步副本,只要这些副本确认了就可以保证消息不丢失)的副本已经确认。例如:如果一个主题配置了两个副本,一个失效(那么就只有一个同步副本),当acks=all成功时,然后,写入的数据仍然可能会丢失。如果余下的副本也失败了???。虽然这是为了保证最大的可用性,但有时这种对有些更喜欢持久性的用户是不可用取的方案。因此我们提供了两个主题级别的配置来满足持久性:

    禁用unclean的领导人选举-如果所有的副本变得不可用,那么分区将保持不可用,直到最近的领导者再次可用。这有效地提高数据丢失的风险。
    指定一个最小ISR数量,只有当ISR数量超过最小ISR数量,分区才接收写入。

    副本管理

    我们上面的讨论都是围绕丰单一的日志,即一个主题分区。然后kafka集群中有成百上千个分区。我们试图用一个循环的试负载分区。避免对高容量的主题所有分区分区都集中在少数的几台节点上。同样,我们也让每个节点都成为某个分区的leader(防止某个节点是很多主题的leader,而其它节点仅仅是follower)

    优化领导人选举进程是非常重要的,因为它是不可用性的关键窗口。一个最简单的选举实现是:当一个节点失效时,将一个一个终止这个节点上每个分区的选举。相反,我们选举出所有节点上的一个做为”controller”,这个”controller”检测borker级别的失败,并且当一个broker失败时,负责更改所有影响的分区的leader。
    这使得我们可以批量发起变更通知,这让选举程序面对大量分区时,变得代价更小也更快。如果controller失效了,余下的broker中的一个将成为新的controller.

  • 4.8 日志压缩

    略… todo
    即:日志在指定时间内或大小内可以保存一段时间,一但超出,将被删除。但日志压缩可以按消息key合并压缩长时间保留(如:相同key-如:userId,可能有多条数据,如:如每次修改就是一条消息,那么会压缩成一条数据,而且是最后一条数据)

  • 4.9 配额(限额)

    从0.9版本,kafka集群提供了强制生产者和消费者的配额。限额是对每个client_id的,基于字节的截阀值。一个clientId逻辑上限定一个应用。因为一个clientId可跨越多个生产者和消费者。所以配额可以做为一个整体限制一个clientId对应的所有生产者和消费者。

    为什么需要配额?
    对于处理非常大容量数据的生产者或消费者,很可能会独占broker资源,并导致网络饱和以及对别的客户端和borkers产生DOS攻击。有了配额,就可解决这个问题。在大的多租户集群中,一系列小的恶意操作都可能降低用户的体验。

    强制
    默认情况,每个唯一的clientId会收来自集群配置的配额(bytes/sec,通过quota.producer.default, quota.consumer.default配置)。配置是基于broker,每个client只能发布或拉取以最大速率范围内。我们决定基于broker定义配额,要比配置到client上要好。因为那样实现起来太难了。

    当检测到一个超额行为,broker会怎么做?
    在我们的解决方案中,broker不会向客端报错,而是直接降低客端速度。它计算违规的client需要延迟的时间,并延迟response.这种方法对客户端是透明的。

    其它,略… todo

    覆盖默认配额
    有时可能需要一个更高的配额,clientId的配额是在zookeeper下的/config/clients中配置。 这个配置会影响所有brokers,并立即生效。这让我们不无可厚非重启整个集群。

5. 实现

  • 5.1 api 设计

    生产者APIs

    生产者 API包含两个低层 producers: kafka.producer.SyncProducer 和kafka.producer.async.AsyncProducer.

    class Producer {  /* 发送数据,通过key分区。即可以使用同步也可以使用异常producer发送 */  public void send(kafka.javaapi.producer.ProducerData<K,V> producerData);  /* 发送数据集,通过key分区。即可以使用同步也可以使用异常producer发送 */  public void send(java.util.List<kafka.javaapi.producer.ProducerData<K,V>> producerData);  /* 关闭producer,并清理*/  public void close();}

    目标是通过暴露一个包含所有功能的api接口给客户端。
    新的producer:

    • 要以处理多生产者请求的队列/缓冲 和 批量数据异步调度。
      kafka.producer.Producer提供批量处理多个生产者请示的能力(producer.type=async).批量处理大小可以通过参数配置。数据被先缓冲在队列中,当达到queue.time或batch.size时,一个后台线程(kafka.producer.async.ProducerSendThread)从队列中取出批量数据,然后让kafka.producer.EventHandler序列化,并发送到broker 分区。
      一个自定义event Handler可以通过event.handler配置参数进行配置。对于各种各样的生产者队列管线,注册回调方法非常有用。即可以注册自定义日志记录/代码跟踪,也可以是自定义监控逻辑。可以通过实现kafka.producer.async.CallbackHandler接口,并设置class 的 callback.handler配置。

    • 可以自己指定一个Encoder,用于序列化数据

      interface Encoder<T> {  public Message toMessage(T data);}

    默认的是: kafka.serializer.DefaultEncoder

    • 通过用户指定一个Partitioner,用于负载均衡
      路由决策是由 kafka.producer.Partitioner.决定。
      interface Partitioner<T> {   int partition(T key, int numPartitions);}

    分区api使用key和可用broker分区的数量生成一个分区id。这个id做为从一个存储了brokerIds和分区的列中检索一个broker分区的索引。
    默认的策略是hash(key)%numPartitions,如果key为空,会随机分配一个分区。可以通过partitioner.class 配置一个自定义的分区策略。

    Consumer APIs

    我们有两个层次的consumer api。 low-level “simple” API 维护一个连接到单个broker的链接(conection)。并有一个发送到服务器的网络请示的对应关系。这个api是完全无状态的。随着偏移量的增加,允许用户自己维护这些元数据。

    high-level api隐藏了brokers与consumer之间的细节。允许消费集群上的消费,而不需要关注低层机器拓扑。higth-level api也提供了用于匹配发布订阅的过滤器表达式(即:白名单或黑名单正则)

    Low-level API

    class SimpleConsumer {  /* Send fetch request to a broker and get back a set of messages. */  public ByteBufferMessageSet fetch(FetchRequest request);  /* Send a list of fetch requests to a broker and get back a response set. */  public MultiFetchResponse multifetch(List<FetchRequest> fetches);  /**   * Get a list of valid offsets (up to maxSize) before the given time.   * The result is a list of offsets, in descending order.   * @param time: time in millisecs,   *              if set to OffsetRequest$.MODULE$.LATEST_TIME(), get from the latest offset available.   *              if set to OffsetRequest$.MODULE$.EARLIEST_TIME(), get from the earliest offset available.   */  public long[] getOffsetsBefore(String topic, int partition, long time, int maxNumOffsets);}

    low-level api是为了实现一些高级api提供的低层接口。因为一些离线消费者特殊需求。

    High-level API

      /* create a connection to the cluster */  ConsumerConnector connector = Consumer.create(consumerConfig);  interface ConsumerConnector {    /**     * This method is used to get a list of KafkaStreams, which are iterators over     * MessageAndMetadata objects from which you can obtain messages and their     * associated metadata (currently only topic).     *  Input: a map of <topic, #streams>     *  Output: a map of <topic, list of message streams>     */    public Map<String,List<KafkaStream>> createMessageStreams(Map<String,Int> topicCountMap);    /**     * You can also obtain a list of KafkaStreams, that iterate over messages     * from topics that match a TopicFilter. (A TopicFilter encapsulates a     * whitelist or a blacklist which is a standard Java regex.)     */    public List<KafkaStream> createMessageStreamsByFilter(        TopicFilter topicFilter, int numStreams);    /* Commit the offsets of all messages consumed so far. */    public commitOffsets()    /* Shut down the connector */    public shutdown()  }

    与流有关,略… todo

  • 5.2 网络层

    网络层是一个NIO服务器,这里不做过多描术。sendfile是通过给MessageSet接口地址的writeTo方法实现。这使得支持文件备份的信息集合,可以使用更有效的transferTo方法,而不是使用内置的缓冲写数据。该线程模型是一个单一的acceptor线程和n个processor线程组成。每个都处理一个固定数量的连接。

  • 5.3 消息

    消息是由一个固定长度的头,一个可变长的模糊含义的key的字节数组,一个可变长的模糊含义的值的字节数组组成。
    头包含以下字段:

    • A CRC32 checksum to detect corruption or truncation.
    • A format version.
    • An attributes identifier
    • A timestamp
      让key和value含义模糊是正确的决定:现在正在做序列化库已经有了很大的进步,任何特写的选择对使用都是不正确的。不用说,一个特写的应用程序使用kafka很可能会指定一个特定的序列化类型。MessageSet接口是一个简单的迭代器,用于从NIO通道中读写大量的消息。
  • 5.4 消息格式

    /** * 1. 4 byte CRC32 of the message * 2. 1 byte "magic" identifier to allow format changes, value is 0 or 1 * 3. 1 byte "attributes" identifier to allow annotations on the message independent of the version *    bit 0 ~ 2 : Compression codec. *      0 : no compression *      1 : gzip *      2 : snappy *      3 : lz4 *    bit 3 : Timestamp type *      0 : create time *      1 : log append time *    bit 4 ~ 7 : reserved * 4. (Optional) 8 byte timestamp only if "magic" identifier is greater than 0 * 5. 4 byte key length, containing length K * 6. K byte key * 7. 4 byte payload length, containing length V * 8. V byte payload */
  • 5.5 日志

    一个主题名为“my_topic”,包含两个分区的日志,由两个目录组成(名为:my_topic_0 和 my_topic_1),这两个目录由存储了与这个主题相关的消息的日志文件集组成。日志文件的格式是由一系列“日志条目”组成,每个日志条目是一个4字节的整型N(存储了消息的长度),和紧接着的N个消息字节组成的消息内容。每个消息都有一个相对分区开始位置的偏移量(64bit Integer),它决定了消息在分区中的位置。
    每个消息的磁盘格式如下:
    每个日志文件用它第一个消息偏移量做为文件名,因此第一个创建的文件名为:00000000000.kafka,

    消息这个确定的二进制格式洒版本化和并固定为一个标准的接口。因此消息集可以在producer,broker,client之间传递,而不需要重复复制或修改。
    格式如下:

    On-disk format of a messageoffset         : 8 bytesmessage length : 4 bytes (value: 4 + 1 + 1 + 8(if magic value > 0) + 4 + K + 4 + V)crc            : 4 bytesmagic value    : 1 byteattributes     : 1 bytetimestamp      : 8 bytes (Only exists when magic value is greater than zero)key length     : 4 byteskey            : K bytesvalue length   : 4 bytesvalue          : V bytes

    使用消息偏移量做为消息id是不寻常的。我们最初是通过生产者创建一佧GUID,然后维护一个GUID与偏移量的映射来做。但是即然客户端要维护每个服务器id,那么全局GUID就没什么意义了。另外,维护一个随机id与偏移量的映射需要每重的索引数据结构,必须同步到硬盘上。因此简化查询结构,我们决定使用一个简单的原子计数器(每个分区一个),可以与分区id和节点id结合起来来唯一定位一条消息。这让消息查询结构非常简单。一旦我们钔了计数器,直接使用偏移量就很自然了,毕竟计数器对一个分区是单调递增了。由于偏移量的具体实现是对客户api隐藏的,因此我们可以做的更有效。

    kafka日志实现图

    日志允许把消息顺序追加到最后一个文件。此文件达到一个配置的大小(比如:1G)后,文件会被清空(是清空还是再创建一个新文件???todo)。
    日志有两个配置参数:M,一个用于让os强制把消息持久到硬盘的最大消息数(未刷时存在pagecache)。S,一个强制刷数据和秒数(超地这个时间,刷到硬盘)。

    这个给出了一个最多失去M消息或最多失去S秒内消息的保证。

    读取消息是通过一个64bit的逻辑偏移量和一个s-byte的最大块大小。然后返回一个大小遍历消息迭代器。S比任何一个单个的消息都要大。如果一个消息异常大,那么读操作可能重试多次,每次都加倍缓冲区,至到消息被成功读取。一个最大消息量和缓冲大小可以设置,让服务器拒绝大于一定大小的消息,并绑定到客户端,以让客户端每次都能读到一个完整的消息。
    很可能会出现,读缓总结尾是保存的是一个不完整的消息,不过这很容易检测。

    实际从偏移量读取进程,首先找到存储数据的日志段文件,然后从全部偏移量计划特写文件的偏移量,然后从文件偏移量读取数据。检索是通过简单的二分查找,而不是内存内的遍历查找。

    日志提供获取最新写入的消息的能力,让客户可以开始定阅“现在”的数据。这对于那些因为消息过期数据而失败的消息都很有用。这种情况,如果客户端指定了一个不存在偏移量,将返回OutOfRangeException,可以重置它自己。

    下面是返回给消费者的消息格式:

    MessageSetSend (fetch result)total length     : 4 byteserror code       : 2 bytesmessage 1        : x bytes...message n        : x bytesMultiMessageSetSend (multiFetch result)total length       : 4 byteserror code         : 2 bytesmessageSetSend 1...messageSetSend n

    删除
    数据删除是:一次只能删除一个日志段。日志管理器允许插入删除策略,以选择哪些文件可以删除。虽然保留N GB,超过此再删除也是很有用的策略,但是我们目前默认的策略是保留N 天。为了避免加读锁的时候还允许删除,我们使用一个copy-on-write 的段列表实现,当删除段的时候,提供了一个静太的不可变的快照副本。

    保证
    略… todo

  • 5.6 分布

    略… todo

6. 操作

这里有一些LinkedIn公司在生产系统的使用经验。

  • 6.1 kafka基本操作

    这里有一些kafka集群是非常通用的操作。在kafka分布式的bin/目录下,本章介绍的所有工具都是有效的。每个工具如果以无参方式运行,都将打印出工具的命令行选项细节。

    • 增加和删除主题(topics)
      你可以手动添加一个主题,也可以自动创建主题。当数据第一次发布,并且没有指定主题时,主题会被自动创建。如果主题是被自动创建的,你可能希望通过默认配置进行调整。

    主题通过以下工具添加和修改:

      > bin/kafka-topics.sh --zookeeper zk_host:port/chroot --create --topic my_topic_name  --partitions 20 --replication-factor 3 --config x=y

    复制因子用来控制写入的消息会被多少服务器复制。如果你的复制因子是3,那么如果2个服务失效,也不会丢失数据。我们建议你复制因子设置为2或者3,这样在不中断数据消费的情况下,机器可以透明的弹性变化。

    分区数量用来控制多数据日志会被共享。分区数量有几个影响,首先,每个分区必须安装在单独的机器上。因此如果你有20个分区,那么将不超过20台服务器来处理(不计算副本)。最后,分区数量决定了消费者的最大并发数。
    详细请看这里

    每个共享的分区日志都放在kafka日志目录下属于分区自己的文件夹下。这些文件夹名字是由主题名,”-“和分区id组成。因为文件夹名不能超过255个字节,所以主题名也是有限止的。我们假定分区数量不能超过100,000个,那么主题名就不能超过249个,这是为了给”-“(一个字符)和分区id(5个字符 999999)留下足够空间。

    命令行中的添加的配置会覆盖服务器中的默认配置。每个主题的完整配置文档请看[]这里](http://kafka.apache.org/documentation.html#topic-config)

    • 修改主题
      你可以使用相同的主题工具来修改配置或者主题的分区

      > bin/kafka-topics.sh --zookeeper zk_host:port/chroot --alter --topic my_topic_name    --partitions 40

      要注意,通过语义分区数据的用例中,添加分区是不会改变现数据的分区,因此这可能扰乱消费者。也就是说,如果数据是通过hash(key)%number_of_partitions(分区数),那么添加分区会导致整个分区重新调整,但是kafka不会以任何方式自动重新分布数据。

      增加配置:

      > bin/kafka-topics.sh --zookeeper zk_host:port/chroot --alter --topic my_topic_name --config x=y

      删除配置

      > bin/kafka-topics.sh --zookeeper zk_host:port/chroot --alter --topic my_topic_name --delete-config x

      删除选项默认是关闭的,需要配置来启动删除功能:

      delete.topic.enable=true

      kafka目前不支持减少主题的分区数量。

      修改主题副本因子的介绍,看这里

      平滑关闭

      kafka集群会自动检测broker是否关闭或失效,并且选举新的leader。无论是服务器失效了,还是为了维护或配置故意关闭,都会导致kafk集群自动检测。对于后者这种情况(维护或配置),kafka支持一种更平滑的机制来停止一个服务器而不是直接干掉它(kill)。
      平滑有两个优化:

      • (1). 在平滑关闭时,kafka会把所有日志同步到磁盘上,以避免重启后重新恢复数据(即:检查所有日志尾部的消息的完整性)。日志恢复需要时间,因此这加快了服务重启的速度。

      • (2). 在关闭之前将优先迁移leader服务器上的分区数据,这样会让领导转移的更快,最大限度的减少每个分区不可用的时间到毫秒内。
        如果服务是被平滑关闭而不是硬生生的kill,那么同步日志将是自动完成,不过leadership的转移还需要配合一个特殊的设置:

        controlled.shutdown.enable=true

      注意:只有broker上的所有分区都有副本(即:副本因子大于1,到少一个副本是激活的)关闭都会成功。这可能就是你想要的,因为关闭最后那个副本会导致主题分区不可用(说白了要关闭一个,至少还有一个热备的,否则,只有自己一人,那么自己关闭了,必然导致服务不可用)。

    • 平衡 leadership
      只要一个服务器停止或崩溃了,leadership就会转移到分区的其它副本上。即默认情况下,只要broker重启了,它只能当做分区的follower。也就是说它不能被客户端访问用来读写了。
      为了避免这种不平衡,kafka有一个首选副本的概念。如果一个分区的副本列表是1,5,9三个节点。那么节点1是leader的首选副本。因为它是最早位于列表中的。你可以通过以下命令让集群重新恢复原有副本为leader.

      > bin/kafka-preferred-replica-election.sh --zookeeper zk_host:port/chroot

      运行这个命令太烦锁,我们可以使用以下配置来让kafka自动平衡:

      auto.leader.rebalance.enable=true

      通过机架平衡副本(机架:就是机房中的机架--0.10.0.0版本新增加了机架感知功能)

      机架感知特性通过不同的机架,扩展了同一分区的不同副本。这把kafka从保证broker失效扩大覆盖到机架故障,限制了一个机架上所有broker一次性全部失效导致数据丢失的风险。(小道消息:此功能是由netflix提供)

      你可以通过以下配置,来指定一个broker属于某个特写的机架。

       broker.rack=my-rack-id

      当一个主题被创建,修改或副本被重新分布,机架约束会被兑现,以确保副本可以跨越多个机架(一个副本到少跨越m个不同的机架,m 由机架数,副本因子确定)。
      分配broker副本的算法保证每个broker的leader数量是恒定的,无论broker在机架上如何分布。这保证了吞吐量的均衡。
      如果机架上分配不同数量的broker,那么副本分配将不均衡。 具有少量broker的机架将具有更多的副本,意味着他们将使用更多的存储并且向副本中存储更的资源。因此,明智的做法是每个机架配置相同的brokers.

    • 集群间的数据镜像
      略… todo

    • 检查消费者位置
      有时,查看消费者位置非常有用。我们有一个工具可以展示一个消费者中的所有消费者位置。
      查看一个消费者组名为”my-group” ,主题为”my-topic”的消费者位置,运行工具如下:

      > bin/kafka-run-class.sh kafka.tools.ConsumerOffsetChecker --zookeeper localhost:2181 --group testGroup           Topic                          Pid Offset          logSize         Lag             Ownermy-group        my-topic                       0   0               0               0               test_jkreps-mn-1394154511599-60744496-0my-group        my-topic                       1   0               0               0               test_jkreps-mn-1394154521217-1a0be913-0

      从0.9.0版本,kafka.tools.ConsumerOffsetChecker工具已经过时了,请使用kafka.admin.ConsumerGroupCommand(或 bin/kafka-consumer-groups.sh 脚本)

      管理消费者组

      使用ConsumerGroupCommand工具,可以查询(列表、详情),删除 消费者组。比如:列出所有消费者组

      > bin/kafka-consumer-groups.sh --zookeeper localhost:2181 --listtest-consumer-group

      为了查看上个例子中的偏移量,我们展示消费者组的详情如下:

      > bin/kafka-consumer-groups.sh --zookeeper localhost:2181 --describe --group test-consumer-groupGROUP                          TOPIC                          PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG             OWNERtest-consumer-group            test-foo                       0          1               3               2               test-consumer-group_postamac.local-1456198719410-29ccd54f-0

      当你使用新的consumer api时,你可以使用”–new-consumer”来管理组:

      > bin/kafka-consumer-groups.sh --new-consumer --bootstrap-server broker1:9092 --list
    • 集群扩展
      向kafka集群中添加服务器是容易的,仅仅给他们分配一个唯一的brokerId,并且把这台机器上的kafka启动想来即可。但是这些新服务器不会自动分配任何数据分区。除非新创建主题,或者数据分区移动到它们上。因此,当你向集群添加一个新的机器时,你想把现存的数据迁移到这些机器。

    迁移数据的过程需要手动启动,但是完全自动化执行。迁移过程的低层实现是这样的:kafka增加一个新的服务器,这个新的服务器做为一个分区的follower。允许它完全复制现存的分区数据。当新的服务器完全复制了此分区中的数据后,并且加了同步副本(in-sync)时,现存副本中的一个就可以删除它们的分区数据了。
    (解释:新增加了服务器,不影响原有数据,这就导致大家都不使用它。除非两种情况:把原有分区数据重新分给它,另外,新创建主题。通知情况,新创建主题并不频繁。那么就需要重新分配数据。重新分配数据需要手动启动,而且新的机器也只能做follower)

    分区调整工个可以用于移动分区到各个 broker。一个理想的分区分配应该能保证数据负载均衡和分区数量均衡。分区调整工具没有能力智能分调整负载。因此,管理员必须找出哪些主题或分区需要移动。

    分区调整工个可以运行以下3种方式(互斥):

    • –generate:这种模式,给定一个主题列表和一个broker列表,工具生成一个重新分配报告(把指定主题的所有分区都移动新有 brokers上),这个选项提供了一个方便的生成重新分配的计划。

    • –execute : 这种模式,工具根据用户提供的重新调整计划(–generate生成的, 使用reassignment-json-file 选项指定)。这个可以是一个自定义的重新调整计划,也可以使用 –generate 生成的

    • –verify: 在这种模式下,工具验证由–execute执行的重新调整。验证状态为:成功、失败、正在进行中。

    自动迁移数据到新机器上
    重新调整工具可以用来把现有brokers集上的部分主题迁移到新的机器上。当扩展一个存在的集群时,这非常有用。因为很容易把全部主题都移到新的brokers集中,而不是一次只移一个分区。
    如果要这么做,我们必须提供一批需要移动的主题列表,和一批新加入的broker列表。工具将均匀的把给定的主题列表中的所有分区移到新的broker集上。迁移过程中,复制因子保持不变。
    指定的主题集中的所有分区副本都从旧的brokers集中迁移到新的brokers中。

    例如,下面的示例将把foo1,foo2两个主题的所有分区都迁移到新的broker机器5,6上。最后,foo1,foo2两个主题的所有分区都厚在brokers 5,6上。

    因为工个接受json文件格式的参数(包含:需要迁移的主题列表),所以首先创建一个json文件,要把需要迁移的主题配置到文件中

    > cat topics-to-move.json{"topics": [{"topic": "foo1"},            {"topic": "foo2"}], "version":1}

    一旦json文件就绪,使用分区重新调整工具生成一个分配计划。

    > bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --topics-to-move-json-file topics-to-move.json --broker-list "5,6" --generate  Current partition replica assignment  {"version":1,   "partitions":[{"topic":"foo1","partition":2,"replicas":[1,2]},                 {"topic":"foo1","partition":0,"replicas":[3,4]},                 {"topic":"foo2","partition":2,"replicas":[1,2]},                 {"topic":"foo2","partition":0,"replicas":[3,4]},                 {"topic":"foo1","partition":1,"replicas":[2,3]},                 {"topic":"foo2","partition":1,"replicas":[2,3]}]  }  Proposed partition reassignment configuration  {"version":1,   "partitions":[{"topic":"foo1","partition":2,"replicas":[5,6]},                 {"topic":"foo1","partition":0,"replicas":[5,6]},                 {"topic":"foo2","partition":2,"replicas":[5,6]},                 {"topic":"foo2","partition":0,"replicas":[5,6]},                 {"topic":"foo1","partition":1,"replicas":[5,6]},                 {"topic":"foo2","partition":1,"replicas":[5,6]}]  }

    工具生成了一个把主题foo1,foo2所有分区迁移到brokers 5,6上的计划。注意,分区迁移还没有开始。它只是告诉你当前分配计划和新计划的提议。为了防止万一需要回滚,新的计划应该保存起来。
    新的调整计划应该保存成一个json文件(如:expand-cluster-reassignment.json),并以–execute选项的方式,如下:

    > bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --reassignment-json-file expand-cluster-reassignment.json --executeCurrent partition replica assignment{"version":1, "partitions":[{"topic":"foo1","partition":2,"replicas":[1,2]},               {"topic":"foo1","partition":0,"replicas":[3,4]},               {"topic":"foo2","partition":2,"replicas":[1,2]},               {"topic":"foo2","partition":0,"replicas":[3,4]},               {"topic":"foo1","partition":1,"replicas":[2,3]},               {"topic":"foo2","partition":1,"replicas":[2,3]}]}Save this to use as the --reassignment-json-file option during rollbackSuccessfully started reassignment of partitions{"version":1, "partitions":[{"topic":"foo1","partition":2,"replicas":[5,6]},               {"topic":"foo1","partition":0,"replicas":[5,6]},               {"topic":"foo2","partition":2,"replicas":[5,6]},               {"topic":"foo2","partition":0,"replicas":[5,6]},               {"topic":"foo1","partition":1,"replicas":[5,6]},               {"topic":"foo2","partition":1,"replicas":[5,6]}]}

    最后, –verify可以肜来验证重新调整的状态。注意,那个调整计划文件expand-cluster-reassignment.json还要再次使用,如下:

      > bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --reassignment-json-file expand-cluster-reassignment.json --verify  Status of partition reassignment:  Reassignment of partition [foo1,0] completed successfully  Reassignment of partition [foo1,1] is in progress  Reassignment of partition [foo1,2] is in progress  Reassignment of partition [foo2,0] completed successfully  Reassignment of partition [foo2,1] completed successfully  Reassignment of partition [foo2,2] completed successfully

    自定义分区分配和迁移
    分区重新调整工具还能用于有选择性把一个分区的所有副本迁移到指定的一系列brokers中。当使用这种方式,它假定用户已经知道重新分配的计划,因此不需要指定一个重新分配计划,也就是跳过–generate步骤,直接执行–execute步骤。

    例如:以下例子把foo1主题中的分区0移到 brokers 5,6上,并且把foo2主题中的分区1移到brokers 2,3上。
    第一步是手动创建一个json格式的分配计划文件。

    > cat custom-reassignment.json{"version":1,"partitions":[{"topic":"foo1","partition":0,"replicas":[5,6]},{"topic":"foo2","partition":1,"replicas":[2,3]}]}

    然后执行:–execute

    > bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --reassignment-json-file custom-reassignment.json --executeCurrent partition replica assignment{"version":1, "partitions":[{"topic":"foo1","partition":0,"replicas":[1,2]},               {"topic":"foo2","partition":1,"replicas":[3,4]}]}Save this to use as the --reassignment-json-file option during rollbackSuccessfully started reassignment of partitions{"version":1, "partitions":[{"topic":"foo1","partition":0,"replicas":[5,6]},               {"topic":"foo2","partition":1,"replicas":[2,3]}]}

    执行验证: –verify

    bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --reassignment-json-file custom-reassignment.json --verifyStatus of partition reassignment:Reassignment of partition [foo1,0] completed successfullyReassignment of partition [foo2,1] completed successfully
    • 除役(删除)brokers
      重新分配工具还没有能力为将除役的brokers自动生成一个重新调整的计划。因此,管理员必须自己想一个重新调整计划来移动将要被除役的brokers上的分区到其它brokers上。这个过程会非常乏味,并且还要保证上分区数据不会全部移到同一台机器上。为了让这个过程轻松,我们在未来的版本上增加这样的工具支持。

    • 增加复制因子
      增加一个现存分区的复制因子是很容易的。只要在自定义的重新调整分区的json文件中指定一个扩展的副本,并且使用–execute选项就可以增加一个指定分区的复制因子

    例如,下面的示例是增加主题foo的分区0的复制因子,把复制因子1增加到3。在增加前,那个分区的唯一副本在broker 5上。同时,我们将增加更多的副本到broker 6 和7上(复制因子增加了,就必须有对应的broker来存储新增的副本)。

    第一步:创建一个重新调整计划文件:

    > cat increase-replication-factor.json{"version":1, "partitions":[{"topic":"foo","partition":0,"replicas":[5,6,7]}]}

    使用–execute选项,启动重新分配进程:

    > bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --reassignment-json-file increase-replication-factor.json --executeCurrent partition replica assignment{"version":1,"partitions":[{"topic":"foo","partition":0,"replicas":[5]}]}Save this to use as the --reassignment-json-file option during rollbackSuccessfully started reassignment of partitions{"version":1,"partitions":[{"topic":"foo","partition":0,"replicas":[5,6,7]}]}

    使用 –verify 选面验证:

    bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --reassignment-json-file increase-replication-factor.json --verifyStatus of partition reassignment:Reassignment of partition [foo,0] completed successfully

    你也可以使用kafka-topics工具来验证:

    > bin/kafka-topics.sh --zookeeper localhost:2181 --topic foo --describeTopic:foo   PartitionCount:1    ReplicationFactor:3 Configs: Topic: foo Partition: 0    Leader: 5   Replicas: 5,6,7 Isr: 5,6,7
    • 设置配额
      可以通过在brokers上配置默认的配额应用到所有clientId上。默认情况,每个clientId都会被限额。下面就是配置每个消费者和生者clientId 的限额为:10MB/秒。
       quota.producer.default=10485760 quota.consumer.default=10485760

    也可以对每个client自定义配置

    > bin/kafka-configs.sh  --zookeeper localhost:2181 --alter --add-config 'producer_byte_rate=1024,consumer_byte_rate=2048' --entity-name clientA --entity-type clientsUpdated config for clientId: "clientA".

    下面是如果显示一个给定client的配额:

    > ./kafka-configs.sh  --zookeeper localhost:2181 --describe --entity-name clientA --entity-type clientsConfigs for clients:clientA are producer_byte_rate=1024,consumer_byte_rate=2048

    

  • 6.2 数据中心

    一些部署可能需要管理一个跨越多个数据中心的数据管道。我们的建议是在每个数据中心本地部署一个kafka集群,每个数据中心的应该只与本地的kafka集群交互。不同数据中心的kafka集群,通过镜像实现数据同步。

    这种部署械允许数据中心做为独立的实体。并允许我们管理协调数据中心之间的复制。这允许每个设置独立操作,即使数据中心的链接是失效的:镜像会在链接成功后自动同步。

    对于需要所有数据全局视图的应用,你可使用镜像来提供从所有数据中心聚合好数据的集群。这些聚合的集群用于需要全部数据集合的应用。

    这不是唯一的部署方式,因为通过网络,很容易对远程kafka集群进行读写,但是每明显,这会增加请求延迟。

    kafka是通过批处理数据才获得高吞吐量,即使在高延迟的connection上。因此,为了保证高吞吐量,我们需要设置TCP socket buffer size。这个设置是通过: socket.send.buffer.bytes and socket.receive.buffer.bytes来配置的,具体看这里;

    在一个高延迟的网络上,只创建一个跨越多个数据中心的单一kafka集群是不明智的,这会即会导致kafka写也会导致zookeeper写操作的高延迟复制。

  • 6.3 重要配置

    • 客户端重要配置
      最重要的生产配置:

      • 压缩
      • 同步 vs 异步生产
      • 批处理大小(对异步而言)
        最重要的消费者配置是抓取数据的大小。

      所有配置文件看这里第三章:配置

    • 生产服务器配置
      下面是服务器上与生产者相关的配置:

      # Replication configurationsnum.replica.fetchers=4replica.fetch.max.bytes=1048576replica.fetch.wait.max.ms=500replica.high.watermark.checkpoint.interval.ms=5000replica.socket.timeout.ms=30000replica.socket.receive.buffer.bytes=65536replica.lag.time.max.ms=10000controller.socket.timeout.ms=30000controller.message.queue.size=10# Log configurationnum.partitions=8message.max.bytes=1000000auto.create.topics.enable=truelog.index.interval.bytes=4096log.index.size.max.bytes=10485760log.retention.hours=168log.flush.interval.ms=10000log.flush.interval.messages=20000log.flush.scheduler.interval.ms=2000log.roll.hours=168log.retention.check.interval.ms=300000log.segment.bytes=1073741824# ZK configurationzookeeper.connection.timeout.ms=6000zookeeper.sync.time.ms=2000# Socket server configurationnum.io.threads=8num.network.threads=8socket.request.max.bytes=104857600socket.receive.buffer.bytes=1048576socket.send.buffer.bytes=1048576queued.max.requests=16fetch.purgatory.purge.interval.requests=100producer.purgatory.purge.interval.requests=100

      客户端相关配置不同的用例各不相同。

作者:链上研发-老杨叔叔
版权声明:本文为链家上海研发中心原创文章,转载请注明出处。

  • 6.4 java版本

    从安全角度考虑,我们推荐使用jdk1.8及以上版本。linkedIn使用的是jdk.8 u5,及G1垃圾收集器。如果你想使用G1,并且使用jdk1.7,要确保u51或更新版本。 linkedIn测试了u21,但是GC有很多问题。
    linedIn的配置如下:

      -Xmx6g -Xms6g -XX:MetaspaceSize=96m -XX:+UseG1GC  -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:G1HeapRegionSize=16M  -XX:MinMetaspaceFreeRatio=50 -XX:MaxMetaspaceFreeRatio=80

    作为参者,这里有一些linkedIn公司最繁忙的集群中的一些属性:

    • 60个 broker
    • 50K 个分区(复制因子为2)
    • 800k 条消息/每秒
    • 300MB/秒 入站(写),1GB/秒 出站(读)
      The tuning looks fairly aggressive, but all of the brokers in that cluster have a 90% GC pause time of about 21ms, and they’re doing less than 1 young GC per second.
  • 6.5 硬件和操作系统

    略… todo

    • 操作系统
      kafka在unix系统上运行良好,在linux和solaris也测试过了

      windows上运行会有一些问题,它支持的不是很好。

      通常不需要太多os级别的调整,但是确实有两个重要os级别的配置:

      • 文件描述符限制:kafka中的日志段和打开connection需要使用文件描述符。如果一个broker有很多分区,那么它需要到少(number_of_partitions)*(partions_size/segment_size)个段需要追踪。我们建议至少允许100000文件描述符。
      • 最大socket buffer size:可以提高数据中心之间的高性能数据传输;具体看这里;
    • 硬盘和文件系统
      略… todo

    • 应用 vs os刷新管理
      kafka通常是立即把数据写入到文件。同时支持配置刷新策略来控制数据什么时间从os cache中刷新到磁盘。这个刷新策略可以控制,在一段时间后或一定量的消息后强制把数据从缓存中刷新到磁盘。
      下面是几个配置选项:

      略… todo

    • Linux Flush Behavior
      略… todo

    • Ext4 Notes
      略… todo
  • 6.6 监控

    略… todo

  • 6.7 zookeeper

    • 稳定版
      目前最稳定版是34,最新版本是3.4.6。zkClient是kafka用于与zookeeper交互的客户端层。
    • 操作zookeeper
      操作上我们通过下面说明安装一个健壮的zookeeper:

      • 物理/硬件/网络冗余布局:不要把它们放在同一个机架上,合适即可(但也不要走极端)。电源和网络有冗余。一个典型的zookeeper应该有5-7个服务器,这样可以容忍2-3台挂掉。当然,如果你有一个小的部署,那么使用3台服务器也是可以接受的。但是要记住,你仅仅能容忍1台服务器挂掉。
      • i/o分离:如果你有一个非常大量的写操作,你可能希望有一组专用的磁盘来记录事先日志。写事务日志是同步的(但是是批量的),因此并行操作可以大在提高性能。ZooKeeper 快速就是这样一个:同源并行写,理想情况下应该与事务日志分开写的功能。快照是异步写到磁盘的。你可以用dataLogDir参数配置一个服务器独立的磁盘组。
      • 应用分离:除非你了解别的程序的应用模式,否则不要把别别的应用与zookeeper安装在一想。最好把zookeeper隔离安装。
      • Use care with virtualization:?? todo
      • zookeeper配置:使用的是java,因此确保有足够的堆内存(我们通常使用3-5G,不过这要看数据量)。不幸的是,我们没有一个合适的公式。但是要记信,对于更多的zookeeper状态,会让快照变大,大的快照会影响恢复时间。如果快照变的太大,那么你就需要增initLimit参数的设置,以给服务器足够的时间用来恢复和加入到集群。
      • 监控:JMX和 4lw命令都是非常有用的,他们在某些情况下是重复的(在这种情况下,我们更喜欢4lw,他们更有预见性,至少,他们在监控设施上与LI工作的更好)。
      • 不要过度建设集群

      总的来说,我们试图保持zookeeper系统尽可能的小,并且尽可能的简单。我们尽可能不做任何比官网花哨的配置或程序布局。出于这个原因,我们跳过操作系统封装的版本,因为操作系统封装的版本,为了更好的方式表达它,会把一些事情放在操作系统层面,这会导致混乱。

7.安全

  • 7.1 安全概述

  • 7.2 Encryption and Authentication using SSL

  • 7.3 Authentication using SASL

  • 7.4 Authorization and ACLs

  • 7.5 Incorporating Security Features in a Running Cluster

  • 7.6 ZooKeeper Authentication

    • New Clusters

    • Migrating Clusters

    • Migrating the ZooKeeper Ensemble

8.kafka Connect

  • 8.1 概述

  • 8.2 用户指南

  • 8.3 Connector开发指南

9. kafka Streams

  • 9.1 概述

  • 9.2 开发者指南

    • 核心概念

    • Low-Level Processor API

    • High-Level Streams DSL

0 0
原创粉丝点击