文章目录
- Kafka主题和分区-笔记3
- 主题的增删改查
- 新增主题
- 查看主题
- 修改主题
- 主题端配置参数与broker端关系
- 删除主题
- KafkaAdminClient
- 分区
- 优先副本(preferred replica)的选举
- 分区重分配
- 复制限流
- 修改副本因子
- 分区数的选择
- kafka性能测试
- 合适的分区数
Kafka主题和分区-笔记3
主题和分区都是逻辑概念,分区可有一到多个副本,每个副本对应一个日志文件,每个日志文件对应一到多个日志分段LogSegment,每个日志分段还可以细分为索引文件,日志存储文件和快照文件
主题的增删改查
主题的增删改查一般通过kafka-topics.sh脚本来执行 在kafka的bin目录下
或使用KafkaAdminClient 通过XXXRequest请求
新增主题
若broker端配置参数auto.create.topics.enable
设置为true(默认值),那么当生产者向一个未创建的主题发消息时(或当一个消费者开始从未知主题读取消息,或当任意一个客户端向未知主题发送元数据请求时),会自动创建一个分区数为broker端配置参数num.partitions
(默认1),副本因子为default.replication.factor
(默认值1)的主题
不建议auto.create.topics.enable
置位true
kafka-topics.sh新增主题:本质是调用kafka.admin.TopicCommand
创建一个topic-test主题 分区数4 副本因子2
bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic topic-test --partitions 4 --replication-factor 2
--zookeeper:ZooKeeper连接地址
--partitions:分区数
--replication-factor:副本数
--topic:主题名称
--create:表示创建主题的指令类型,除此之外还有list,describe,alter,delete
Kafka会在log.dir或log.dirs参数所配置的目录下创建相应的主题分区
文件命名:<topic>-<partition> 这类文件对应的不是分区
创建一个主题时会在ZooKeeper的/brokers/topics/目录下创建一个同名的实节点
--replica-assignment参数:手动指定分区副本的分配方案,无需partitions和replication-factor参数 格式<分区1副本1所在brokerId:分区1副本2所在brokerId>,<分区2副本1所在brokerId:分区2副本2所在brokerId>
bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic topic-test --replica-assignment 0:1,1:2,2:0
以上创建一个分区数3,副本数2的主题
--config:通过此参数设置要创建主题的相关参数,可覆盖原本的默认配置
--config max.message.bytes=1000 主题端配置参数
--if-not-exists:创建主题时若主题存在则不做任何处理
主题,分区,副本和日志的关系:同一个分区中的多个副本必须分布在不同的broker 表现为一个broker不会出现重复地<topic>-<partition>命名文件
一对多
一对多
一对一
主题Topic
分区Partition
副本Replica
日志文件log
kafka-topics.sh脚本在创建主题时会检测是否包含.
或_
,kafka内部会将.
改成下划线_
,故而尽量避免主题名称含这两个符号
broker端参数broker.rack机架信息
Kafka支持指定broker的机架信息。若指定了机架信息,则在分区副本分配时会尽可能地让分区副本分配到不同的机架上
必须全部broker都有broker.rack参数或都没有 或使用disable-rack-aware参数忽略机架信息
查看主题
通过list和describe指令查看主题信息
查看主题内的内容
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topicName --from-beginning
list查看当前所有可用的主题
bin/kafka-topics.sh --zookeeper localhost:2181 --list
test
test1
__consumer_offsets
describe查看分区副本的分配细节
bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic topic-test
Topic:PushNotice PartitionCount:1 ReplicationFactor:1 Configs:
Topic: PushNotice Partition: 0 Leader: 0 Replicas: 0 Isr: 0
PartitionCount分区数
ReplicationFactor副本数
Partition分区编号
Leader :leader分区所在brokerId
Replicas:副本所在brokerId,AR集合
Isr:分区的ISR集合,brokerId
--topics-with-overrides:找出所有包含覆盖配置的主题 --config,列出与集群不一样配置的主题
--under-replicated-partitions和--unavailable-partitions:找出有问题的分区
--under-replicated-partitions找出所有包含失效副本的分区。包含失效副本的分区可能正在进行同步操作,也有可能同步发生异常,此时分区的ISR集合小于AR集合
修改主题
主题创建之后,仍然可以修改分区个数,配置等,通过alter指令
注意kafka只支持增加分区数而不支持减少分区数
alter
修改分区数
bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic topic-test --partitions 5
--if-exists:不存在则忽略
修改config配置
bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic topic-test --config max.message.bytes=2000
--delete-config:删除之前覆盖的配置,恢复原有的默认值
bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic topic-test --delete-config max.message.bytes
kafka-config.sh
包含修改配置alter和查看配置describe两种指令类型,与kafka-topics.sh不同,kafka-config.sh不仅可以操作主题相关的配置,还可以支持操作broker,用户和客户端3个类型的配置
主题端配置参数与broker端关系
若没有修改过主题的任何配置参数,那么就会使用broker端的对应参数作为其默认值
主题端参数 | 作用 | broker端参数 |
cleanup.policy | 日志压缩策略。默认delete,compact等 | log.cleanup.policy |
compression.type | 消息的压缩类型。默认值producer,gzip等 | 同 |
delete.retention.ms | 被标识删除的数据能够保留的时间,默认86400000,即1天 | log.cleaner.delete.retention.ms |
file.delete.delay.ms | 清理文件可以等待的时间,默认60000,即1分钟 | log.segment.delete.delay.ms |
max.message.bytes | 消息的最大字节数,默认1000012 | 同 |
message.timestamp.type | 消息的时间戳类型,默认CreateTime,还有LogAppendTime | log.message.timestamp.type |
message.timestame.difference.max.ms | 消息中自带的时间戳和broker收到消息时的时间戳之间最大的差值,默认Long.MAX_VALUE,message.timestamp.type为CreateTime时有效 | 同 |
min.insync.replicas | 分区ISR集合中至少要有多少个副本,默认1 | 同 |
retention.bytes | 分区中所能保留的消息总量,默认-1,无限制 | log.retention.bytes |
retention.ms | 使用delete的日志清理策略时消息能够保留的时间,默认604800000,即7天,若-1则无限制 | log.retention.ms |
segment.bytes | 日志分段的最大值,默认1073741824,即1GB | log.segment.bytes |
segment.ms | 最长多久滚动一次日志分段,默认7天 | log.roll.ms |
unclean.leader.election.enable | 是否可以从非ISR集合中选举leader副本,默认false,若true可能数据丢失 | 同 |
删除主题
delete指令:必须配置broker端参数delete.topic.enable
为true才能删除 默认true
bin/kafka-topics.sh --zookeeper localhost:2181 --delete --topic topic-test
--if-exist
kafka-topics.sh脚本删除主题的行为本质上只是在ZooKeeper中的/admin/delete_topics路径下创建一个与待删除主题同名的节点,标记删除状态,然后由kafka的控制负责删除
ZooKeeper客户端删除主题:
zkCli.sh
create /admin/delete_topics/topic-test ""
手动删除:
主题的元数据存储在ZooKeeper中的/brokers/topics 和/config/topics路径下
主题的消息数据存储在log.dir配置的路径下 手动删除这3个地方
KafkaAdminClient
通过用KafkaAdminClient管理broker,配置和ACL,主题
创建主题
public CreateTopicsResult createTopics(final Collection<NewTopic> newTopics,
final CreateTopicsOptions options)
删除主题
public DeleteTopicsResult deleteTopics(Collection<String> topicNames,
DeleteTopicsOptions options)
列出主题
public ListTopicsResult listTopics(final ListTopicsOptions options)
查询主题的信息
public DescribeTopicsResult describeTopics(final Collection<String> topicNames, DescribeTopicsOptions options)
查看配置信息
public DescribeConfigsResult describeConfigs(Collection<ConfigResource> configResources, final DescribeConfigsOptions options)
修改配置信息
public AlterConfigsResult alterConfigs(Map<ConfigResource, Config> configs, final AlterConfigsOptions options)
增加分区
public CreatePartitionsResult createPartitions(Map<String, NewPartitions> newPartitions,
final CreatePartitionsOptions options)
验证主题
一般auto.create.topics.enable参数为false,不允许自动创建主题
Kafka broker端有参数 create.topic.policy.class.name 默认null,该参数提供一个入口验证主题创建的合法性
需要自定义实现CreateTopicPolicy接口 如PolicyTest实现该接口然后在server.properties中配置create.topic.policy.class.name=org.apache.kafka.server.policy.PolicyTest
如此创建topic时,命名不规范会报错
分区
包括优先副本的选举,分区重分配,复制限流,修改副本因子
优先副本(preferred replica)的选举
分区使用多副本机制,其中leader副本对外提供读写,follower副本只进行消息的同步。若一个分区的leader副本不可用,那么就意味着整个分区变得不可用,此时则从剩余follower副本中选举一个新的leader
优先副本preferred replica:
优先副本是指在AR集合列表中的第一个副本。优先副本是为了能够治理负载失衡的情况,如下负载失衡 leader为0的分区有2个
Topic: topic1 PartitionCount:3 ReplicationFactor:3 Configs:
Topic: topic1 Partition: 0 Leader: 1 Replicas: 1,2,0 Isr: 1,0,2
Topic: topic1 Partition: 1 Leader: 0 Replicas: 2,0,1 Isr: 0,1,2
Topic: topic1 Partition: 2 Leader: 0 Replicas: 0,1,2 Isr: 0,1,2
如上主题topic1中分区0的AR集合Replicas为[1,2,0],那么分区0的优先副本即为1。理想情况下优先副本就是该分区的leader副本,故而优先副本也称preferred leader
Kafka要确保所有主题的优先副本在Kafka集群中均衡分布,如此保证leader均衡分布,若leader分布过于集中则集群负载不均衡
优先副本的选举是指通过一定方式促使优先副本被选举为leader副本,也叫分区平衡
Kafka中提供分区自动平衡的功能,broker端参数auto.leader.rebalance.enable
,默认true,若开启分区自动平衡的功能,则Kafka的控制器会启动一个定时任务轮询所有的broker节点,计算每个broker节点的分区不平衡率**(broker的不平衡率=非优先副本的leader个数/分区总数)**是否超过leader.imbalance.per.broker.percentage
参数配置的比值,默认10%,若超过设定的比值则会自动执行优先副本的选举动作以求分区平衡。执行周期由参数leader.imbalance.check.interval.seconds
控制,默认300秒
broker端分区自动平衡相关参数
auto.leader.rebalance.enable:是否开启分区自动平衡功能 默认true开启:生产环境建议false,自动执行会引起客户端阻塞,导致不可用,建议手动再平衡
leader.imbalance.per.broker.percentage:broker节点分区不平衡率可容忍的最高比值 默认10% 超过则分区再平衡
leader.imbalance.check.interval.seconds:分区再平衡的执行周期,若分区不平衡且比值超过leader.imbalance.per.broker.percentage 才会再平衡,默认300秒
kafka-perferred-replica-election.sh 手动执行分区再平衡
kafka-perferred-replica-election.sh脚本提供了对分区leader副本进行重新平衡的功能。
此优先副本选举足够安全,客户端可自动感知分区leader副本的变化
bin/kafka-preferred-replica-election.sh --zookeeper localhost:2181
执行结果
Created preferred replica election path with __consumer_offsets-22,__consumer_offsets-30,__consumer_offsets-8
Successfully started preferred replica election for partitions Set(分区集合...)
直接执行kafka-perferred-replica-election.sh会将集群上所有的分区都执行一遍优先副本的选举操作。leader副本的转移是一项高成本工作,若要执行的分区数多会影响客户端。若集群中包含大量的分区,那么上面的这种方式有可能失效。
在优先副本的选举过程中,具体的元数据信息会被存入ZooKeeper的/admin/preferred_replica_election节点,若这些数据超过了ZooKeeper所允许的大小,则会选举失败。默认允许大小1MB
path-to-json-file
参数批量对部分分区执行优先副本的选举操作
当面对大量分区的集群时,通过kafka-perferred-replica-election.sh脚本path-to-json-file参数指定一个JSON文件(保存需要执行优先副本选举的分区清单)来执行优先副本的选举操作
创建JSON文件test.json
{
"partitions":[
{
"partition":0,
"topic":"topic-test"
},
{
"partition":1,
"topic":"topic-test"
}
]
}
执行脚本bin/kafka-preferred-replica-election.sh --zookeeper localhost:2181 --path-to-json-file test.json
执行结果:成功将分区0和1进行优先副本的再选举
Created preferred replica election path with topic-test-0,topic-test-1
Successfully started preferred replica election for partitions Set(topic-test-0,topic-test-1)
**注意:**生产环境使用path-to-json-file
参数来分批,手动地执行优先副本的选举操作
分区重分配
Kafka分区分配存在的问题:
- 多副本某个节点down下,则位于这个节点leader副本会移交到集群的其他follower副本。此时这个节点的分区副本都失效,但Kafka不会将这些失效的副本自动地迁移到集群中剩余的可用broker节点上
- 当集群中新增broker节点时,只有新创建的主题分区才有可能被分配到这个节点上,而之前的主题分区并不会自动分配到新加入的节点中,导致新节点的负载和原先节点的负载之间严重不均衡
为了解决上述两个问题,需要让分区副本合理重分配,Kafka提供kafka-reassign-partitions.sh
脚本来执行分区重分配的工作,它可以在集群扩容,broker节点失效的场景下对分区进行迁移
kafka-reassign-partitions.sh
脚本执行步骤
- 创建需要一个包含主题清单的JSON文件
- 根据主题清单和broker节点清单生成重分配方案
- 执行具体的重分配
当需要将brokerId为1的broker节点下线时,需将其上的分区副本迁移出去
1.创建一个JSON文件 test.json;文件内容为要进行分区重分配的主题清单 对于主题topic-test 如下
{
"topics":[
{
"topic":"topic-test"
}
],
"version":1
}
2.根据JSON文件和指定所要分配的broker节点列表来生成一份候选的重分配方案
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --generate --topics-to-move-json-file test.json --broker-list 0,2
--generate是该脚本的指令类型参数,相当于kafka-topics.sh的--create,它用来生成一个重分配的候选方案
--topic-to-move-json用来指定分区重分配对应的主题清单文件的路径
--broker-list用来指定所要分配的broker节点列表
执行结果:
当前的分区副本分配情况的json格式内容 保存起来以后回滚分配
Crrent partition replica assignment
{...}
重分配的候选方案,此时并没有执行重分配,只是生成执行重分配的json格式内容
Proposed partition reassignment configuration
将该方案保存在test1.json文件中
3.执行具体的重分配动作
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --execute --reassignment-json-file test1.json
此时会按test1.json文件中的分区分配方案进行重分配!
--execute 指令类型参数,执行重分配动作
--reassignment-json-file test1.json 指定分区重分配方案的文件路径
查看分区重分配的进度
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --verify --reassignment-json-file test1.json
分区重分配的基本原理:本质在于数据复制
通过控制器为每个分区添加新副本(增加副本因子),新的副本将从分区的leader副本哪里复制所有的数据(数据迁移,耗费时间,空间,带宽)
控制器将旧副本从副本清单里移除(恢复为原先的副本因子数)
注意:重分配过程中要确保由足够的空间,且执行后若leader负载不均衡可使用优先副本的选举重新选举leader
分区重分配对集群的性能有很大的影响,需要占用额外的资源,如网络和磁盘。实际应该降低重分配的粒度,分成多个小批次来执行
注意:若要将某个broker下线,最好再分区重分配之前关闭或重启该broker。如此这个broker不存在任何分区的leader节点。减少broker间的流量复制
复制限流
若集群中某个主题或某个分区的流量在某段时间内特别大,那么分区重分配时只靠减少粒度不足以应对,此时就需要限流机制,可对副本间的复制流量进行限制保证重分配期间整体服务不受影响
副本间复制限流的方式
-
kafka-config.sh
脚本 -
kafka-reassign-partitions.sh
脚本
kafka-config.sh
脚本限流:动态配置的方式达到限流
broker端参数
follower.replication.throttled.rate:设置follower副本复制的速度
leader.replication.throttled.rate:设置leader副本传输的速度
两者配置一般值相同,单位B/s
设置传输速度1kb/s
bin/kafka-configs.sh --zookeeper localhost:2181 --entity-type brokers --entity-name 1 --alter --add-config follower.replication.throttled.rate=1024,leader.replication.throttled.rate=1024
结果
Completed Updating config for entity: brokers '1'.
主题端参数
follower.replication.throttled.replicas:被限制速度的主题所对应的的follower副本列表 [0:1,1:2,2:0] 即[分区n:follower副本broker]
leader.replication.throttled.replicas:被限制速度的主题所对应的的leader副本列表[0:0,1:1,2:2] 即[分区n:leader副本brokerId]
kafka-reassign-partitions.sh
脚本限流:需要一个throttle参数 推荐此方法 本质也是第一个方法的四个参数
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --execute --reassignment-json-file test1.json --throttle 10
限流的速度上限10B/s 以上命名可重复执行提高限流的速度上限
需要周期性执行查看进度的命令直到重分配完成,这样可确保限流设置被移除
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --verify --reassignment-json-file test1.json
修改副本因子
详情看分区重分配
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --execute --reassignment-json-file test1.json
json格式:
{
"version": 1,
"partitions": [
{
"topic": "topic-throttle",
"partition": 1,
"replicas": [
2,
0
//1.此处新增一个副本
],
"log_dirs": [
"any",
"any"
//2.此处对应要新增any log_dirs参数的数量和replicas的数量保持一致!
]
},
{
"topic": "topic-throttle",
"partition": 0,
"replicas": [
0,
2
],
"log_dirs": [
"any",
"any"
]
},
{
"topic": "topic-throttle",
"partition": 2,
"replicas": [
0,
2
],
"log_dirs": [
"any",
"any"
]
}
]
}
副本因子可以增加也可以减少,replicas参数每多一个副本brokerId,log_dirs参数就多一个any
分区数的选择
kafka性能测试
生产者性能测试kafka-producer-perf-test.sh
,消费者性能测试kafka-consumer-perf-test.sh
kafka-producer-perf-test.sh
向主题topic-test 发送100万条消息,每条消息大小为1024B,生产者对应acks参数为1
bin/kafka-producer-perf-test.sh --topic topic-test --num-records 1000000 --record-size 1024 --throughput -1 --producer-props bootstrap.servers=localhost:9092 acks=1
执行结果
184756 records sent, 36951.2 records/sec (36.09 MB/sec), 711.8 ms avg latency, 1298.0 max latency.
381240 records sent, 76248.0 records/sec (74.46 MB/sec), 403.8 ms avg latency, 538.0 max latency.
386370 records sent, 77274.0 records/sec (75.46 MB/sec), 397.8 ms avg latency, 461.0 max latency.
1000000 records sent, 64094.346879 records/sec (62.59 MB/sec), 457.14 ms avg latency, 1298.00 ms max latency, 400 ms 50th, 786 ms 95th, 1161 ms 99th, 1286 ms 99.9th.
已发送1000000条记录,64094.346879条记录/秒(62.59 MB /秒),457.14 ms平均延迟,1298.00 ms最大延迟,400 ms 50%,786 ms 95%,1161 ms 99%,1286 ms 99.9%。
records send 消息总数
records/sec 每秒发送的消息总数来统计吞吐量
MB/sec 每秒发送的消息大小来统计吞吐量
avg latency 消息处理的平均耗时
max latency 消息处理的最大耗时
50th,99.9th等 表示50%,99.9%的消息处理耗时
--topic:指定目标主题
--num-records:指定发送消息的总条数
--record-size:设置每条消息的字节数单位B
--producer-props:指定生产者的配置,空格分隔多组配置
--producer.config:指定生产者的配置文件
--throghput:限流控制,值小于0不限流,大于0,当发送的吞吐量大于该值时就会被阻塞一段时间 该参数限制的是77274.0 records/sec (75.46 MB/sec) 单位b/sec
--print-metrics:提示更多性能指标
kafka-consumer-perf-test.sh
bin/kafka-consumer-perf-test.sh --topic topic-test --messages 1000000 --broker-list localhost:9092
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec, rebalance.time.ms, fetch.time.ms, fetch.MB.sec, fetch.nMsg.sec
WARNING: Exiting before consuming the expected number of messages: timeout (10000 ms) exceeded. You can use the --timeout option to increase the timeout.
2020-03-04 15:10:58:531, 2020-03-04 15:11:04:657, 976.5625, 159.4127, 1000000, 163238.6549, 16, 6110, 159.8302, 163666.1211
start.time 起始运行时间
end.time 结束运行时间
data.consumed.in.MB 单位MB,消费的消息总量
MB.sec 按字节大小计算的消费吞吐量
data.consumed.in.nMsg:消费的消息总数
nMsg.sec 按消息个数计算的吞吐量
rebalance.time.ms 再平衡的时间 单位ms
fetch.time.ms 拉取消息的持续时间
fetch.MB.sec 每秒拉取消息的字节大小
fetch.nMsg.sec每秒拉取消息的个数
其中fetch.time.ms=end.time-start.time-rebalance.time.ms
合适的分区数
分区数并非越多越好,分区数对kafka性能提升拥有一个阈值
分区数的上限和linux的文件描述符的限制有关通过ulimit -n 65536
将上限提高,或修改limits.conf文件
root soft nofile 65535
root hard nofile 65535
不同环境的分区数阈值不同,最大效率需要进行环境测试
分区在进行leader角色切换时会不可用
broker节点数不多时,建议将分区数设定为集群中broker的倍数,如3,6,9