主题管理
1.1 创建主题
当broker端配置参数auto.create.topics.enable设置为true(默认为true),那么当生产者向一个尚未创建的主题发送校学习时,会自动创建一个分区数为num.partitions,副本因子为default.replication.factor的主题。另外,当一个消费者开始从位置主题中读取消息时,或者当任意一个客户端向未知追发送元数据请求时,都会按照配置参数num.partitions和default.replication.factor的值来创建一个相应的主题。
当你手动创建了一个topic后,会根据broker端参数log.dir或者log.dirs参数锁配置的目录下创建相应的主题分区。所以强烈建议不要讲kafka的log.dir或log.dirs配置在/tmp目录下
kafka中每一个数据文件夹对应一个分区的副本,可以在log.dir或者log.dirs目录下找到一个命名方式为topic-partition-partionId的目录。后面的partitionId分区id。
当你创建好了topic以后,可以在zookeeper的/kafka/brokers/topics/<topic-name>中找到这个主题的相关信息。
下面我们创建一个topic-create的目录,并查看相关信息
kafka-topics.sh --zookeeper cdh001:2181/kafka \
--create --topic topic-create \
--partitions 4 \
--replication-factor 2
[zk: cdh001:2181/kafka(CONNECTED) 2] get /brokers/topics/topic-create
{"version":1,"partitions":{"2",[1,2],"1":[0,1],"3":[2,1],"0":[2,0]}}
除了使用上面这种创建模式(由kafka自动分配分区与副本),也可以手动设置分区副本信息,使用参数replica-assignmnet
kafka-topics.sh --zookeeper cdh001:2181/kafka --create --topic topic-create --replica-assignment 1:2,2:0,0:1,1:0
这里的1:2,2:0,0:1,1:0指的是第一个分区是在brokerId为1和2的机器上,以此类推。以逗号分隔分区,分号分隔机器。因此不能出现相同的数字以分号分隔,如 0:0,1:1这样
在创建topic的使用使用–config参数来指定要重新设定的参数
kafka-topics.sh --zookeeper cdh001:2181/kafka --create --topic topic-create --replica-assignment 1:2,2:0,0:1,1:0 --config cleanup.policy=compact --config max.message.bytes=10000
新指定的参数可以在zookeeper的/config/topics/<topic-name> 这个节点下查看。
如果是使用机架的情况,请在broker端中配置broker.rack=xxx这个参数
1.2 分区副本的分配
在创建主题的时候如果broker端没有broker.rack这个参数或者使用了–disable-rack-aware这个参数,在分配分区副本的时候将不考虑机架的问题。
1.3 查看主题
kafka-topics.sh这个脚本有5中指令类型:create、list、describe、alter和delete。其中list和describe指令可以用来方便地查看主题信息。
kafka-topics.sh --zookeeper cdh001:2181/kafka --list
# 显示所有的topic
__consumer_offsets
topic-create
kafka-topics.sh --zookeeper cdh001:2181/kafka --topic topic-create --describe
# 显示具体的一个topic的信息
Topic:topic-create PartitionCount:4 ReplicationFactor:2 Configs:
Topic:topic-create Partition: 0 Leader:2 Replicas: 2,1,0 Isr: 2,1,0
Topic:topic-create Partition: 1 Leader:0 Replicas: 0,2,1 Isr: 0,2,1
Topic:topic-create Partition: 2 Leader:2 Replicas: 1,0,2 Isr: 1,0,2
Topic:topic-create Partition: 3 Leader:2 Replicas: 2,0,1 Isr: 2,0,1
使用describe这个指令查看主题信息是还可以topic-with-overrides、under-replicated-partitions和unavailable-partitions这三个参数
当增加了–topic-with-overrides参数时,查看有新添加配置参数的主题
当增加了–under-replicated-partitions参数时,查看有失效副本的主题
当增加了–unavailable-partitions参数时,查看了有无效分区的主题
1.4 修改主题
是用kafka-topics.sh配合–alter指令。当要重新指定分区数或者副本数时:
kafka-topics.sh --zookeeper cdh001:2181/kafka --alter --topic topic-config --partitions 3 --replication-factor 5 --config max.message.bytes=20000
目前kafka原生支持分区数增加而不支持分区数减少,但代码层面还是能实现的就是代码量会增加很多而已。
同时,当使用–delete-config这个指令时会将覆盖的参数恢复默认值。
1.5 配置管理
使用kafka-configs.sh脚本来专门对配置进行操作,这里的操作是指在运行状态下修改原有的配置,如此可以达到动态变更的目的。一般要配合–entity-type和–entity-name这两个参数来使用。
entity-type类型 | entity-name的选择 |
---|---|
主题类型,取值:topics | 主题名称 |
broker类型,取值:brokers | brokerId |
客户端类型,取值:clients | clientId |
用户类型,取值:users | 指定用户名 |
使用alter指令变更配置时,需要配合add-config和delete-config这两个参数来一起使用。
add-config参数用来实现配置的增和改
delete-config参数用来实现配置的删
kafka-configs.sh -zookeeper cdh001:2181/kafka --entity-type topics --entity-name topic-config --add-config max.message.bytes=10000,clean.up=compact
使用kafka-configs.sh脚本来变更配置时,会在zookeeper中创建一个命名方式为/config/<entity-type>/<entity-name>的节点,并将配置写入这个节点
变更配置时还会在zookeeper中/config/changes/节点下创建一个一"config_change_"为前缀的持久顺序节点
1.6 主题端参数
请前往官网查看http://kafka.apache.org/documentation/#topicconfigs
1.7 删除主题
使用–delete这个指令,且设置参数delete.topic.enable为true。
也可以自己手动删除主题,
第一步:删除zookeeper中的节点/config/topics/topics-delete
[zk: localhsot:2181/kafka (CONNECTED) 7] rmr /config/topics/topic-delete
第二步:删除zookeeper中的节点/brokers/topics/topics-delete及其子节点
[zk: localhsot:2181/kafka (CONNECTED) 8] delete /brokers/topics/topic-delete
第三步:删除集群中所有主题topic-delete有关文件
rm -rf $log.dir/topic-delete*
使用KafkaAdminClient
使用org.apache.kafka.clients.admin.KafkaAdminClient这个类来操作,其继承了org.apache.kafka.clients.admin.AdminClient抽象类,并气筒了多种方法
- 创建主题 CreateTopicResult createTopics(Collection<NewTopic> newTopics)
- 删除主题 DeleteTopicsResult deleteTopics(Collection<String> topics)
- 列出所有主题 ListTopicsResult listTopics()
- 查看主题信息 DescribeTopicsResult describeTopics(Collection<String> topicsNames)
- 查询配置信息 DescribeConfigsResult describeConfigs(Collection<ConfigResource> resources)
- 修改配置信息 AlterConfigsResult alterConfigs(Map<ConfigResource,Config> configs)
- 增加分区 CreatePartitionsResult createPartitions(Map<String,NewPartitions> newPartitons)
// 创建一个topic
String brokerList = "localhost:9092";
String topic = "topic-admin";
Properties props = new Properties();
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, brokerList);
props.put(AdminClientConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000);
AdminClient client = AdminClient.create(props); // 创建一个AdminClient对象
NewTopic newTopic = new NewTopic(topic, 4, (short)1);
CreateTopicResult result = client.createTopic(Collections.singleton(newTopic));
try{
result.all().get();
} catch(Exception e) {
e.printStackTrace();
}
client.close();
NewTopic这个类的属性
private final String name; // 主题名称
private final int numPartitions; // 分区数
private final short replicationFactor; // 副本因子
private final Map<Integer, List<Integer>> replicasAssignments;
private Map<String, String> configs = null;
CreateTopicsResult的部分源码
public class CreateTopicsResult {
private final Map<String, KafkaFuture<Void>> futures;
CreateTopicResult(Map<String, KafkaFuture<Void>> futures) {
this.futures = futures;
}
public Map<String, KafkaFuture<Void>> values() {
return futures;
}
public KafkaFuture<Void> all() {
return KafkaFuture.allOf(futures.values().toArray(new KafkaFuture[0]));
}
}
使用describeConfigs方法的使用示例
public static void describeTopicConfig() throws ExecutionException, InterruptedException {
String brokerList = "localhost:9092";
String topic = "topic-admin";
Properties props = new Properties();
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, brokerList);
props.put(AdminClientConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000);
AdminClient client = AdminClient.create(props); // 创建一个AdminClient对象
ConfigResource resource = new ConfigResource(ConfigResource.Type.Topic, topic);
DescribeConfigResult result = client.
describeConfigs(Collections.singleton(resource));
Config config = result.all().get().get(resource);
client.close();
如果要修改配置使用alterConfigs这个方法
ConfigResource resource = new ConfigResource(ConfigResource.Type.Topic, topic);
ConfigEntity entity = new ConfigEntity("cleanup.policy", "compact");
Config config = new Config(Collection.singtelon(entity));
Map<ConfigResource, Config> configs = new HashMap<>();
configs.put(resource, config);
alterConfigResult result = client.alterConfigs(configs);
result.all().get();
增加partitions
NewPartitions newPartitions = NewPartitions.increaseTo(5);
Map<String,NewPartitions> newPartitionsMap = new HashMap<>();
newPartitionsMap .put(topic, newPartitions);
CreatePartitionsResult result = client.createPartitions(newPartitionsMap);
result.all().get();
分区管理
3.1 优先副本的选举
在创建好了topic后,使用–describe来查看topic中的详细信息时能看到,有一列Replicas,这个就是优先副本列表。
在kafka中可以提供分区自动平衡的功能,榆次对应的broker端参数是auto.leader.rebalance.enable,这个参数默认是true,当开启了这个功能后,kafka的控制器会启动一个定时任务,这个任务会轮询所有的broker节点,计算broker节点的分区不平衡率(broker中的不平衡率=非优先副本的leader个数/分区总数)是否超过了leader.imbalance.per.broker.percentage参数配置的比例,默认为10%。执行周期有参数leader.imbalance.check.interval.seconds控制,默认为300秒。
但生产环境中不推荐开启这个功能,最好还是手动触发
手动启动一次优先副本调整使用kafka-perferred-replica-election.sh这个副本
# 对所有分区副本都执行优先调整
kafka-perferred-replica-election.sh --zookeeper locahost:2181/kafka
如果只想针对某些分区进行,或者想小批次逐次执行,则使用如下方法
在这个脚本中添加一个参数–path-to-json-file来选定某分区
内容如下:
{
"paritions":[
{
"partition":0,
"topic":"topic-partition"
},
{
"partition":1,
"topic":"topic-partition"
},
{
"partition":2,
"topic":"topic-partition"
}
]
}
然后
kafka-perferred-replica-election.sh --zookeeper locahost:2181/kafka --path-to-json-file election.json
3.2 分区重分配
当需要将某些节点下线时,将该节点上的分区转移到别的节点上继续执行使用脚本kafka-reassign-partition.sh
第一步:创建一个json文件定义要进行分区重分配的主题清单
{
"topics":[
{
"topic":"topic-reassign"
}
],
"version":1
}
第二步:使用该json生成执行计划
kafka-reassign-paritions.sh --zookeeper locahost:2181/kafka --generate --topic-to-move-json-file reassin.json --broker-list 0,2
在控制台上将生成两端输出 Current partition replica assignment和Proposed partition reassignment configuration,将Proposed partition reassignment configuration的内容复制到一个json文件中project.json
–broker-list参数是指定要参与到重分区的节点的brokerId
第三步:
kafka-reassign-paritions.sh --zookeeper locahost:2181/kafka --execute --reassignment-json-file project.json
3.3 复制限流
分区重分配的过程就是先增加部分,然后进行数据同步,最后删除旧的副本来达到最终的目的。数据复制会占用额外的资源,所以需要对复制过程进行限速。
副本间限速有两种实现方式:kafka-configs.sh和kafka-reassin-partitions.sh脚本
这里先介绍后者
kafka-reassign-partitions.sh --zookeeper locahost:2181/kafka --execute --reassignment-json-file project.json --throttle 10
就是在重分区的执行前进行限流
性能测试
生产者测试脚本
kafka-producer-perf-test.sh --topic topic-1 --num-records 10000000 --record-size 1024 --throughput -1 --producer-props bootstrap.server=localhost:2181/kafka acks=1 --pirnt-metrics
消费者测试脚本
kafka-consumer-perf-test.sh --topic topic-1 --messages 1000000 --broker-list localhost:9092
后面继续更新。。。。