主题与分区

主题管理

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类型,取值:brokersbrokerId
客户端类型,取值:clientsclientId
用户类型,取值: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

后面继续更新。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值