在kafka中除了直接通过代码的方式进行一些信息配置外,我们还可以通过在kafka安装目录下的bin目录下的工具进行操作,我们先来了解下基础的一些操作,看下新增topic的工具:
> bin/kafka-topics.sh --bootstrap-server broker_host:port --create --topic my_topic_name --partitions 20 --replication-factor 3 --config x=y
以上的语法表示我们新增了一个topic,其中:
replication-factor表示包含leader服务器节点在内的服务器复制节点有3个,它说明有3个服务器节点需要复制这个topic。如果在这3个节点中丢失了2台复制节点也不会担心数据会被丢失。
partitions表示将当前topic分成20份日志来存储,并且每个分区对应一个完整的服务器,也就是说这20个日志对应的服务器不会超过20台服务器。同理如果分区日志过多,也会影响消费者处理的并行度。
每个partition分区日志都是存放在对应kafka目录下的logs文件夹下面的对应topic相关名称文件夹里,这个topic对应的文件夹名称是由"topic名称-分区id"组成,并且名称长度不能超255个字符。
> bin/kafka-topics.sh --bootstrap-server broker_host:port --alter --topic my_topic_name --partitions 40
该命令用来修改topic对应日志的分区数量,执行这个命令后会导致消费者可能不能正确消费到以前的数据,因为以前的数据并不会因为现在的最新分区数量而把以前存在过的数据进行转移到新分区上面。kafka现在还不支持减少分区数,意思就是说只能增加分区数。
> bin/kafka-configs.sh --bootstrap-server broker_host:port --entity-type topics --entity-name my_topic_name --alter --add-config x=y
> bin/kafka-configs.sh --bootstrap-server broker_host:port --entity-type topics --entity-name my_topic_name --alter --delete-config x
上面2个分别是新增和删除配置。
> bin/kafka-topics.sh --bootstrap-server broker_host:port --delete --topic my_topic_name
删除topic。
kafka在节点进行更改或者维护配置而造成的停机操作,kafka并不会直接将服务kill掉,而是通过一种非常优雅的方式进行关闭操作:
1.它将会把所有的自己的日志都同步到磁盘上面,以避免在重启时进行日志的恢复。
2.在关闭之前,它会将服务器作为leader的任何分区迁移到其他副本。这将使领导权转移更快,并将每个分区不可用的时间减少到几毫秒。
要使用这种优雅的关闭方式需要配置controlled.shutdown.enable=true。当然这还需要在该节点有其他复制节点的情况下才起作用。针对一个broker节点宕机或者停机,那么在该节点上的leader信息将会转移到其他复制节点上面,当该节点重启完成后,它也只能作为相应分区的follower节点。为了做到再平衡,默认情况下kafka将自动重新将在剩余的复制节点中选举出新的leader节点,默认情况下将设置auto.leader.rebalance.enable=true来实现,如果将该配置设置为了false,则需要我们手动去进行调节,命令是:
> bin/kafka-preferred-replica-election.sh --bootstrap-server broker_host:port
当我们将kafka的broker节点放置在不同机架上面的时候,kafka将会通过机架感知特性将同一分区的副本分散到不同机架上。我们可以通过设置broker.rack=my-rack-id来指定broker属于某个特定的机架。当创建、修改主题或重新分发副本时,将遵守机架约束,确保副本能够跨越尽可能多的机架(一个分区将跨越min(#机架,复制因子)不同的机架)。也因此用于将副本分配给broker的算法确保每个broker的leader数量是恒定的,无论代理如何跨机架分布。这确保了均衡的吞吐量。如果设置了不同的机架有不同的broker节点,这也会将导致不同的机架上面有不同数量的副本复制信息,因此会造成负载的不均衡。
kafka还设计了kafka-mirror-maker.sh工具用于在不同集群之间将数据进行镜像传递的功能,该工具在源集群使用并把数据生成到目标集群上面。这种镜像的常见用例是在另一个数据中心提供副本。这种镜像操作是可以运行多个的,以保证吞吐量和容错。数据将会从源集群的一个topic读取到目标集群的相同topic中,实际上也就是说mirror工具相当于是一个消费者和生产者的集合。基于源集群和目标集群是完全不同的独立实体,它们可以有不同的分区和偏移量,因此镜像集群实际上并不是一种容错机制(因为消费者的位置不同),也因此我们完全可以使用普通的集群内复制。镜像生成器进程将保留并使用消息键进行分区,因此在每个key上将会保留顺序。看下镜像生成器的例子:
> bin/kafka-mirror-maker.sh
--consumer.config consumer.properties
--producer.config producer.properties --whitelist my-topic
这个例子是将topic为my-topic的主题进行镜像同步,而whitelist属性表示可以进行镜像同步的主题,就像一个白名单类似的东西,它的值可以设置为满足Java的正则表达式所能转换的值,如A|B,它表示A和B两种topic,为了方便理解,我们也可以将"|"改为",",如果需要镜像全部的topic,我们可以用"*"表示。为了自动创建和复制所有数据在源集群中,以及后面新增的topic,我们一般需要设置auto.create.topics.enable=true。
在kafka中我们可以通过kafka-consumer-groups.sh来列举、删除以及描述消费者分组信息,当然如果你想手动或者自动的删除消费者分组信息,那么得必须保证消费者分组的最后提交偏移量已经到期了。我们先看下列举消费者组的命令:
> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list
test-consumer-group
查看消费者消费到的消息的位置,如下:
> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group my-group
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
my-topic 0 2 4 2 consumer-1-029af89c-873c-4751-a720-cefd41a669d6 /127.0.0.1 consumer-1
my-topic 1 2 3 1 consumer-1-029af89c-873c-4751-a720-cefd41a669d6 /127.0.0.1 consumer-1
my-topic 2 2 3 1 consumer-2-42c1abd4-e3b2-425d-a8bb-e1ea49b29bb2 /127.0.0.1 consumer-2
--members: 这个命令是用来列举还在消费者分组中还存活的成员:
> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group my-group --members
CONSUMER-ID HOST CLIENT-ID #PARTITIONS
consumer1-3fc8d6f1-581a-4472-bdf3-3515b4aee8c1 /127.0.0.1 consumer1 2
consumer4-117fe4d3-c6c1-4178-8ee9-eb4a3954bee0 /127.0.0.1 consumer4 1
consumer2-e76ea8c3-5d30-4299-9005-47eb41f3d3c4 /127.0.0.1 consumer2 3
consumer3-ecea43e4-1f01-479f-8349-f9130b75d8ee /127.0.0.1 consumer3 0
--members --verbose:除了上面的展示的信息外,它还新列举除了每个分区上面对应的topic信息
> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group my-group --members --verbose
CONSUMER-ID HOST CLIENT-ID #PARTITIONS ASSIGNMENT
consumer1-3fc8d6f1-581a-4472-bdf3-3515b4aee8c1 /127.0.0.1 consumer1 2 topic1(0), topic2(0)
consumer4-117fe4d3-c6c1-4178-8ee9-eb4a3954bee0 /127.0.0.1 consumer4 1 topic3(2)
consumer2-e76ea8c3-5d30-4299-9005-47eb41f3d3c4 /127.0.0.1 consumer2 3 topic2(1), topic3(0,1)
consumer3-ecea43e4-1f01-479f-8349-f9130b75d8ee /127.0.0.1 consumer3 0 -
--offsets:输出的信息和--describe一样。
--state:用来显示组级别信息
> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group my-group --state
COORDINATOR (ID) ASSIGNMENT-STRATEGY STATE #MEMBERS
localhost:9092 (0) range Stable 4
--delete:删除分组信息
> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --delete --group my-group --group my-other-group
Deletion of requested consumer groups ('my-group', 'my-other-group') was successful.
--reset-offsets:重置消费者组的偏移量,这个命令的使用范围必须是在--all-topics和--topic二选一,当然如果是选择了--from-file这种场景下面倒是可以不用选择。它有3种执行方案:
1.默认是显示被重置的偏移量
2.--execute:执行--reset-offsets命令。
3.--export:导出结果到CSV文件。
--reset-offsets可供选择的其他场景有:
--to-datetime <String: datetime> :将偏移量重置为datetime的偏移量,时间格式为:YYYY-MM-DDTHH:mm:SS.sss
--to-earliest:重置偏移量为最早的偏移量。
--to-latest : 重置偏移量为最新的偏移量。
--shift-by <Long: number-of-offsets> : 重置偏移量为当前位置±n的偏移位置。
--from-file : 通过CSV文件中的值来重置偏移量。
--to-current:重置偏移量为当前偏移量。
--by-duration <String: duration> : 重置偏移量为从当前时间戳的时间段的偏移量,格式为:PnDTnHnMnS。
--to-offset : 重置偏移量为指定值的偏移量。
需要注意的是在重置偏移量时消费者实例不可用,并且当重置的偏移量大于实际的偏移量时,那么实际的偏移量值将会被选择。看下消费者组重置为最新的偏移量
> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --reset-offsets --group consumergroup1 --topic topic1 --to-latest
TOPIC PARTITION NEW-OFFSET
topic1 0 0
如果使用的是旧的高级消费者,并在ZooKeeper中存储组元数据(即offsets.storage=zookeeper),则通过——ZooKeeper而不是——bootstrap-server进行相关设置:
> bin/kafka-consumer-groups.sh --zookeeper localhost:2181 --list
在kafka中我们为了集群的扩展需要把一些topic的信息转换到其他新加入集群的机器上,这个时候我们可以通过工具kafka-reassign-partitions.sh来实现topic信息的转移,这个转移过程是手动启动,但是数据的转移过程是自动化的,新的服务器将作为它正在迁移的分区的follower,并且它将完全复制该分区中的现有数据。当新服务器完全复制此分区的内容并加入同步副本时,其中一个现有副本将删除其分区的数据。在转移分区数据的过程中,复制因子是不变的。转移的过程一般分为3个步骤:
1.--generate:这一步是在给定一组主题和一组broker的情况下,该工具将会生成候选重新分配方案,以将指定主题的所有分区移动到新的broker。此选项仅提供了一种方便的方法,用于在给定主题和目标broker列表的情况下生成分区重新分配计划。
2.--execute: 这一步将会根据用户提供的分配计划移动指定主题的指定分区到新的机器上面,它和--reassignment-json-file一起使用,这个file是个json文件,它可以是通过用户自己配置的,也可以是第一步的--generate生成的。
3.--verify:是用户检查--execute是否执行成功,状态有3种:全部程序成功、失败和执行中。
我们来看下一个例子,它将topics foo1,foo2的所有分区信息转移到新的节点5和6上面,经过转移后的topics foo1,foo2的所有分区信息最后只存在了节点5和6上面。因为支持json文件的格式进行数据的上传,因此我们首先定义一个json文件如下:
> cat topics-to-move.json
{"topics": [{"topic": "foo1"},
{"topic": "foo2"}],
"version":1
}
定义好json文件后我们就可以通过--generate命令来生成分区分配计划了,如下:
> bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --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]}]
}
将生成的分区计划的值的Proposed复制到一个json文件中,如expand-cluster-reassignment.json,然后运行--execute命令,如下:
> bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --reassignment-json-file expand-cluster-reassignment.json --execute
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]}]
}
Save this to use as the --reassignment-json-file option during rollback
Successfully 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来检查转移的情况,这个命令需要用--execute执行的转移的json文件,如下:
> bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --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
当然,如果你不想通过--generate来生成转移计划,想自己手动的指定转移topic指定的分区也是可以的,如将topic foo1的分区0转移到节点5和6,把topic foo2的分区1转移到节点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 --bootstrap-server localhost:9092 --reassignment-json-file custom-reassignment.json --execute
Current 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 rollback
Successfully started reassignment of partitions
{"version":1,
"partitions":[{"topic":"foo1","partition":0,"replicas":[5,6]},
{"topic":"foo2","partition":1,"replicas":[2,3]}]
}
最后检查下转移结果如下:
> bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --reassignment-json-file custom-reassignment.json --verify
Status of partition reassignment:
Reassignment of partition [foo1,0] completed successfully
Reassignment of partition [foo2,1] completed successfully
上述这些转移都是在topic分区所在的broker节点都存活状态下的转移,如果节点已经不存活了,肯定是无法进行转移的。
有的时候我们需要给topic增加更多的复制节点,这个时候我们也可以通过kafka-reassign-partitions.sh来进行操作,下面的一个例子是topic foo原来只有一个复制副本在broker 5上面,现在我们需要把复制因子从1改为3,也即新增复制节点6和7,首先我们也得像前面一样定义一个json文件来设置转移操作:
> cat increase-replication-factor.json
{"version":1,
"partitions":[{"topic":"foo","partition":0,"replicas":[5,6,7]}]}
然后通过--execute来重新分配,如下:
> bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --reassignment-json-file increase-replication-factor.json --execute
Current partition replica assignment
{"version":1,
"partitions":[{"topic":"foo","partition":0,"replicas":[5]}]}
Save this to use as the --reassignment-json-file option during rollback
Successfully started reassignment of partitions
{"version":1,
"partitions":[{"topic":"foo","partition":0,"replicas":[5,6,7]}]}
在通过--verify来检查下转移是否完成:
> bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --reassignment-json-file increase-replication-factor.json --verify
Status of partition reassignment:
Reassignment of partition [foo,0] completed successfully
最后通过kafka-topics.sh工具来检查下复制因子:
> bin/kafka-topics.sh --bootstrap-server localhost:9092 --topic foo --describe
Topic:foo PartitionCount:1 ReplicationFactor:3 Configs:
Topic: foo Partition: 0 Leader: 5 Replicas: 5,6,7 Isr: 5,6,7
在数据的转移过程中为了保证其他操作的正常进行,我们需要对转移做一些限流控制,kafka提供了2种接口来实现,最简单、最安全的方式就是通过kafka-reassign-partitions.sh来设置,另外一个就是通过kafka-configs.sh来查看和更新限流控制。这里主要介绍如何通过kafka-reassign-partitions.sh来设置限流以及通过kafka-configs.sh来显示限流的信息。我们先看下限流转移的数据为50MB/S:
$ bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --execute --reassignment-json-file bigger-cluster.json --throttle 50000000
The throttle limit was set to 50000000 B/s
Successfully started reassignment of partitions.
如果这个时候你嫌这个速度有点慢,我们还可以在移动过程中进行限流调整:
$ bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --execute --reassignment-json-file bigger-cluster.json --throttle 700000000
There is an existing assignment running.
The throttle limit was set to 700000000 B/s
这个限流操作一般都是针对这次数据移动的,但是如果没有清除这次限流操作的话也有可能会对其他的正常数据造成影响,因此通常我们是通过--verify来检查数据转移是否完成同时在完成后它会自动的清除掉限流的配置。
> bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 --verify --reassignment-json-file bigger-cluster.json
Status of partition reassignment:
Reassignment of partition [my-topic,1] completed successfully
Reassignment of partition [mytopic,0] completed successfully
Throttle was removed.
通过kafka-configs.sh,它有两对限流配置,第一对是指限流阀值本身,这个配置是broker级别的:
leader.replication.throttled.rate
follower.replication.throttled.rate
另一个是经过调整的副本的枚举集的配置对:
leader.replication.throttled.replicas
follower.replication.throttled.replicas
这四个配置值都由kafka-reassign-partitions.sh自动分配,我们通过kafka-configs.sh来查看限流分配情况:
> bin/kafka-configs.sh --describe --bootstrap-server localhost:9092 --entity-type brokers
Configs for brokers '2' are leader.replication.throttled.rate=700000000,follower.replication.throttled.rate=700000000
Configs for brokers '1' are leader.replication.throttled.rate=700000000,follower.replication.throttled.rate=700000000
查看副本限流情况:
> bin/kafka-configs.sh --describe --bootstrap-server localhost:9092 --entity-type topics
Configs for topic 'my-topic' are leader.replication.throttled.replicas=1:102,0:101,
follower.replication.throttled.replicas=1:101,0:102
可以看到leader的限流配置节点是在节点102的分区1,节点101的分区0上面,而follower节点限流配置节点是在节点101的分区1,节点102的分区0上面。
默认情况下kafka-reassign-partitions.sh只会把leader限流给所有已经存在了的复制节点,而follower限流会给所有数据被转移到的节点上面,也就是说如果现在有101,102节点,现在需要把101,102数据转移到102,103上面,那么leader限流只会出现在101和102上面,而follower限流则只会出现在103节点上面。
在使用限流复制的时候,需要注意2点:
1.限流的移除
通过 kafka-reassign-partitions.sh --verify进行移除。
2.复制进度的确认
如果限流的设置相比于写入速率过低(max(BytesInPerSec) > throttle),这个就可能导致复制不能正常的保持进度,BytesInPerSec是用来监视生产者写入每个broker的吞吐量的指标。监控的配置是:
kafka.server:type=FetcherLagMetrics,name=ConsumerLag,clientId=([-.\w]+),topic=([-.\w]+),partition=([0-9]+)