文章目录
- kafka使用和操作
- 1.环境搭建
- 2.基本操作
- 2.1.服务器基本操作
- 2.2.topic相关操作
- 2.3.生产者相关命令
- 2.4.消费者相关命令
- 3. 生产者
- 3.1发送消息 异步发送 没有回调函数
- 3.2 发送消息 异步发送 带回调函数
- 3.3 发送消息 同步发送
- 3.4 生产者 分区策略
- 3.4.1自定义分区器
- 3.5 生产者常用的配置
- 3.1.7 生产者 ack 应答模式
- 3.1.7.1 应答模式总结
- 3.1.7.2 代码配置应答模式
- 4.kafka broker
- 4.1 基本工作原理
- 4.1.1.节点的注册
- 4.1.2. kafka leader选举流程
- 4.1.3 topic 信息
- 4.2节点的服役和退役
- 4.2.1 下线kafka节点
- 4.2.2 上线新的kafka 节点
- 4.2.3 kafka 选举流程和 ar , isr
- 4.2.4 故障转移的过程
- 4.2.5 leader再平衡策略
- 4.2.6 kafka日志存储
- 5.消费者
- 5.1 消费者的基础概念
- 5.1.1 消费者的原理
- 5.1.2 消费者的配置
- 5.2 消费者代码实现
- 5.2.1 普通的消费者代码
- 5.2.2 消费者指定消费某个分区
- 5.2.3 消费者消费策略
kafka使用和操作
1.环境搭建
2.基本操作
2.1.服务器基本操作
# 启动kafka
/usr/local/kafka_2.12-3.0.0/bin/kafka-server-start.sh -daemon /usr/local/kafka_2.12-3.0.0/config/server.properties
# 停止kafka
/usr/local/kafka_2.12-3.0.0/bin/kafka-server-stop.sh
2.2.topic相关操作
# 查看 topic 列表
/usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --list
# 创建一个名称为 test 的 topic, partitions 指定分区数量, replication-factor 副本数量
/usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --create --partitions 3 --replication-factor 3 --topic test
# 查看某个主题的详细信息
/usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --describe --topic test
# 修改分区数量 只能增加不能减少
/usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --alter --topic test --partitions 4
# 删除主题
/usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --delete --topic test
2.3.生产者相关命令
# 通过控制台发送消息 到 test 这个 topic
/usr/local/kafka_2.12-3.0.0/bin/kafka-console-producer.sh --bootstrap-server node-1:9092 --topic test
2.4.消费者相关命令
# 从控制台消息消息
/usr/local/kafka_2.12-3.0.0/bin/kafka-console-consumer.sh --bootstrap-server node-1:9092 --topic test
3. 生产者
3.1发送消息 异步发送 没有回调函数
public class TestProducer {
private static String kafkaAddr = "node-1:9092";
private static String topic = "test";
public static void main(String[] args) {
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaAddr);
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);
for (int i = 0; i < 10; i++) {
producer.send(new ProducerRecord<String, String>(topic, "a"+i));
}
producer.close();
}
}
3.2 发送消息 异步发送 带回调函数
producer.send(new ProducerRecord<String, String>(topic, "a" + i), new Callback() {
public void onCompletion(RecordMetadata recordMetadata, Exception e) {
String topic = recordMetadata.topic();
int partition = recordMetadata.partition();
long offset = recordMetadata.offset();
System.out.println("topic="+topic+"partition="+partition+"offset="+offset);
}
});
3.3 发送消息 同步发送
RecordMetadata recordMetadata = producer.send(new ProducerRecord<String, String>(topic, "a" + i)).get();
3.4 生产者 分区策略
// 发往指定的分区1 , 如果生产者指定发往那个分区, kafka就直接发往对应的分区了
// 分区对应类: org.apache.kafka.clients.producer.UniformStickyPartitioner
producer.send(new ProducerRecord<String, String>(topic, 1,"","a" + i), new Callback() {
public void onCompletion(RecordMetadata recordMetadata, Exception e) {
String topic = recordMetadata.topic();
int partition = recordMetadata.partition();
long offset = recordMetadata.offset();
System.out.println("topic="+topic+"partition="+partition+"offset="+offset);
}
});
// 使用 key 分区=key.gethashCode() % topic.partitionCount;
// 分区对应类: org.apache.kafka.clients.producer.internals.DefaultPartitioner
producer.send(new ProducerRecord<String, String>(topic, ""+i,"val" + i), new Callback() {
public void onCompletion(RecordMetadata recordMetadata, Exception e) {
String topic = recordMetadata.topic();
int partition = recordMetadata.partition();
long offset = recordMetadata.offset();
System.out.println("topic="+topic+"partition="+partition+"offset="+offset);
}
});
// 如果生产者没有使用分区, kafka会使用黏性 分区, 会随机选择一个分区, 并尽可能一直使用这个分区, 当该分区的 batch已满或者 linger.ms 时间到了会重新选择一个分区与上次不同
// 分区对应类: org.apache.kafka.clients.producer.RoundRobinPartitioner
3.4.1自定义分区器
/**
* 自定义分区器, 判断value 是 user开头的发送到 0分区 其他发送到1分区
*/
public class MyPartitioner implements Partitioner {
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
String val = value.toString();
int partition =0;
if(val.startsWith("user")){
partition = 0;
}else{
partition =1;
}
return partition;
}
public void close() {
}
public void configure(Map<String, ?> configs) {
}
}
// 使用分区, 在创建 kafka配置的时候指定相关的分区
properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"com.syl.demo.producer.MyPartitioner");
3.5 生产者常用的配置
// 1. 创建 kafka 生产者的配置对象
Properties properties = new Properties();
// 2. 给 kafka 配置对象添加配置信息:bootstrap.servers
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop102:9092");
// key,value 序列化(必须):key.serializer,value.serializer
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
// RecordAccumulator:缓冲区大小,默认 32M:buffer.memory
properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG,33554432);
// batch.size: 批 次 大 小 , 默 认 16K
properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
// linger.ms:等待时间,默认 0
properties.put(ProducerConfig.LINGER_MS_CONFIG, 1);
// compression.type:压缩,默认 none,可配置值 gzip、snappy、lz4 和 zstd
properties.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"snappy");
3.1.7 生产者 ack 应答模式
- 0
生产者发送数据到kafka 不需要等待数据落盘就应答了消费者, 存在消息丢失的可能性; - 1
生产者发送数据到kafka Leader 收到数据后应答, 存在消息丢失 消费者发送数据后 Leader 挂了, 新的 Leader不会知道这条数据 - -1
生产者发送过来的数据,Leader和SR队列里面的所有节点收齐数据后应答。
•数据完全可靠条件 = ACK级别设置为-1 + 分区副本大于等于2 + ISR里应答的最小副本数量大于等于2
3.1.7.1 应答模式总结
应答模式总结
acks=0,生产者发送过来数据就不管了,可靠性差,效率高;
acks=1,生产者发送过来数据Leader应答,可靠性中等,效率中等;
acks=-1,生产者发送过来数据Leader和ISR队列里面所有Follwer应答,可靠性高,效率低;在生产环境中,acks=0很少使用;acks=1,一般用于传输普通日志,允许丢个别数据;acks=-1,一般用于传输和钱相关的数据, 对可靠性要求比较高的场景。
3.1.7.2 代码配置应答模式
// 设 置 acks
properties.put(ProducerConfig.ACKS_CONFIG, "all");
// 重试次数retries,默认是 int 最大值,2147483647
properties.put(ProducerConfig.RETRIES_CONFIG, 3);
4.kafka broker
4.1 基本工作原理
4.1.1.节点的注册
kafka 是依赖zookeeper 的, 当每一个 kafka 启动的时候, 会向zookeeper 注册节点信息注册到 zk的 /kafka/broker/ids 这个节点下就能够看到整个kafka集群的机器数量
4.1.2. kafka leader选举流程
kfka每台机器都会有 一个controller 模块, 启动后会向 zk的 /kafka/controller 注册那台机器先注册上那一台就是 控制整个集群选举的机器, 当某一台注册上后 它会监控 /kafka/broker/ids 这个节点的变化, 如果某台服务下线了, 监控机器会重新选举该节点的leader
4.1.3 topic 信息
当创建 topic 会向zk 的 /kafka/brokers/topics/topic_name, 节点注册相应的topic topic_name 下面对应的有这个 topic的分片信息(partitions), 每个分片都会有 谁是 leader isr队列信息
# 当我们创建一个 test topic 3个分区 3个副本
/usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --create --partitions 3 --replication-factor 3 --topic test
# zookeeper 显示, 下面zk显示 三个分片信息, 显示的是 broker.id kafka配置文件的主机id
/kafka/brokers/topics/test/partitions/1/state
{
"controller_epoch" : 9,
"leader" : 1,
"version" : 1,
"leader_epoch" : 0,
"isr" : [ 1, 3, 2 ]
}
/kafka/brokers/topics/test/partitions/2/state
{
"controller_epoch" : 9,
"leader" : 2,
"version" : 1,
"leader_epoch" : 0,
"isr" : [ 2, 1, 3 ]
}
/kafka/brokers/topics/test/partitions/0/state
{
"controller_epoch" : 9,
"leader" : 3,
"version" : 1,
"leader_epoch" : 0,
"isr" : [ 3, 2, 1 ]
}
4.2节点的服役和退役
4.2.1 下线kafka节点
# 创建一个2个副本的 主题
/usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --create --partitions 2 --replication-factor 2 --topic test
# 登录服务器操作
cd /root
vim topics-to-move.json
{
"topics": [
{"topic": "test"}
],
"version": 1
}
# 生成一个负载均衡计划, 删除掉 broker id 为3的服务器
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-reassign-partitions.sh --bootstrap-server node-1:9092 --topics-to-move-json-file /root/topics-to-move.json --broker-list "1,2" --generate
# 当前的计划, 我们可以看到 有2个分区 0分区(副本在 1,3 服务器) 1分区(副本在 2,1 服务器)
Current partition replica assignment
{
"version": 1,
"partitions": [{
"topic": "test",
"partition": 0,
"replicas": [1, 3],
"log_dirs": ["any", "any"]
}, {
"topic": "test",
"partition": 1,
"replicas": [2, 1],
"log_dirs": ["any", "any"]
}]
}
# 修改后的计划, 按照我们命令上传了 生成的新计划里面没有3号服务器了
Proposed partition reassignment configuration
{
"version": 1,
"partitions": [{
"topic": "test",
"partition": 0,
"replicas": [1, 2],
"log_dirs": ["any", "any"]
}, {
"topic": "test",
"partition": 1,
"replicas": [2, 1],
"log_dirs": ["any", "any"]
}]
}
# 创建执行计划, 拷贝 修改后的计划 json 并执行
vim increase-replication-factor.json
{
"version": 1,
"partitions": [{
"topic": "test",
"partition": 0,
"replicas": [1, 2],
"log_dirs": ["any", "any"]
}, {
"topic": "test",
"partition": 1,
"replicas": [2, 1],
"log_dirs": ["any", "any"]
}]
}
# 执行企划
/usr/local/kafka_2.12-3.0.0/bin/kafka-reassign-partitions.sh --bootstrap-server node-1:9092 --reassignment-json-file /root/increase-replication-factor.json --execute
# 验证计划
/usr/local/kafka_2.12-3.0.0/bin/kafka-reassign-partitions.sh --bootstrap-server node-1:9092 --reassignment-json-file /root/increase-replication-factor.json --verify
# 再次查看节点发现 3号机器已经没有了
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --describe --topic test
Topic: test TopicId: sIpAfy1qQziyfMqrhOBYBA PartitionCount: 2 ReplicationFactor: 2 Configs: segment.bytes=1073741824
Topic: test Partition: 0 Leader: 1 Replicas: 1,2 Isr: 1,2
Topic: test Partition: 1 Leader: 2 Replicas: 2,1 Isr: 2,1
4.2.2 上线新的kafka 节点
vim topics-to-move.json
{
"topics": [
{"topic": "test"}
],
"version": 1
}
# 生成计划
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-reassign-partitions.sh --bootstrap-server node-1:9092 --topics-to-move-json-file /root/topics-to-move.json --broker-list "1,2,3" --generate
Current partition replica assignment
{"version":1,"partitions":[{"topic":"test","partition":0,"replicas":[1,2],"log_dirs":["any","any"]},{"topic":"test","partition":1,"replicas":[2,1],"log_dirs":["any","any"]}]}
Proposed partition reassignment configuration
{"version":1,"partitions":[{"topic":"test","partition":0,"replicas":[2,3],"log_dirs":["any","any"]},{"topic":"test","partition":1,"replicas":[3,1],"log_dirs":["any","any"]}]}
# 执行计划
vim increase-replication-factor.json
{"version":1,"partitions":[{"topic":"test","partition":0,"replicas":[2,3],"log_dirs":["any","any"]},{"topic":"test","partition":1,"replicas":[3,1],"log_dirs":["any","any"]}]}
/usr/local/kafka_2.12-3.0.0/bin/kafka-reassign-partitions.sh --bootstrap-server node-1:9092 --reassignment-json-file /root/increase-replication-factor.json --execute
# 查看topic 的分区副本信息, 已经按照我们的计划更新了
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --describe --topic test
Topic: test TopicId: sIpAfy1qQziyfMqrhOBYBA PartitionCount: 2 ReplicationFactor: 2 Configs: segment.bytes=1073741824
Topic: test Partition: 0 Leader: 2 Replicas: 2,3 Isr: 2,3
Topic: test Partition: 1 Leader: 3 Replicas: 3,1 Isr: 1,3
4.2.3 kafka 选举流程和 ar , isr
- ar 副本数量 和副本所存在的顺序
- isr 该分区 副本存活的 服务器(如果follower 长时间没发送请求数据给 leader 就会被剔除 isr队列 默认30秒
replica.lag.time.max.ms
参数控制)
# 创建 topic 3个分区 3个副本
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --create --partitions 3 --replication-factor 3 --topic test
Created topic test.
# 查看topic详情下面显示 Isr 为存活的kafka存活的服务器,
# Replicas 为 ar, 也就是副本存在哪些服务器.
# Leader 分片所在服务器的 Leader
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --describe --topic test
Topic: test TopicId: Ze9LaGjSTdS5cdAzI1LUKw PartitionCount: 3 ReplicationFactor: 3 Configs: segment.bytes=1073741824
Topic: test Partition: 0 Leader: 3 Replicas: 3,2,1 Isr: 3,2,1
Topic: test Partition: 1 Leader: 1 Replicas: 1,3,2 Isr: 1,3,2
Topic: test Partition: 2 Leader: 2 Replicas: 2,1,3 Isr: 2,1,3
# 停止掉 3号服务器, 我们发现 isr 服务器少了, 是因为他是 存活的服务器列表, 由 ar=Replicas 2号服务器接替了 3号的位置
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --describe --topic test
Topic: test TopicId: Ze9LaGjSTdS5cdAzI1LUKw PartitionCount: 3 ReplicationFactor: 3 Configs: segment.bytes=1073741824
Topic: test Partition: 0 Leader: 2 Replicas: 3,2,1 Isr: 2,1
Topic: test Partition: 1 Leader: 1 Replicas: 1,3,2 Isr: 1,2
Topic: test Partition: 2 Leader: 2 Replicas: 2,1,3 Isr: 2,1
# 停掉2号服务器, 我们发现停掉 2号服务器后 所有的分片信息都集中到了 1号服务器里面
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --describe --topic test
Topic: test TopicId: Ze9LaGjSTdS5cdAzI1LUKw PartitionCount: 3 ReplicationFactor: 3 Configs: segment.bytes=1073741824
Topic: test Partition: 0 Leader: 1 Replicas: 3,2,1 Isr: 1
Topic: test Partition: 1 Leader: 1 Replicas: 1,3,2 Isr: 1
Topic: test Partition: 2 Leader: 1 Replicas: 2,1,3 Isr: 1
# 我们再启动 3号服务器
[root@node-1 ~]# /usr/local/kafka_2.12-3.0.0/bin/kafka-topics.sh --bootstrap-server node-1:9092 --describe --topic test
Topic: test TopicId: Ze9LaGjSTdS5cdAzI1LUKw PartitionCount: 3 ReplicationFactor: 3 Configs: segment.bytes=1073741824
Topic: test Partition: 0 Leader: 1 Replicas: 3,2,1 Isr: 1,3
Topic: test Partition: 1 Leader: 1 Replicas: 1,3,2 Isr: 1,3
Topic: test Partition: 2 Leader: 1 Replicas: 2,1,3 Isr: 1,3
总结: leader 选举策略,如果某个 broker 挂了 新的 leader需要具备, 在Isr队列存活 并且在 ar中排在最前面的副本(最前面的副本同步的数据最多)
4.2.4 故障转移的过程
- LEO(Log end offset) 每个副本最新的offset
- HW (所有副本最小的 LEO)
集群中有 1,2,3 台 broker
当某台 broker 故障停机了, 它首先先从 Isr 队列删除掉;
当这台服务器故障结束好了, 它会吧 自己上次 记录 HW之后的数据全部删除掉(会认为是没有验证的数据)
这台服务器就同步数据, 当同步到 基本水位线 HW 的时候 才重新加入 Iso队列
当集群中 leader 宕机了, 先按照选举流程选举 新的 leader
所有的副本节点从leader同步数据如果高于leader的数据需要删除, 追求数据的一致性
4.2.5 leader再平衡策略
当我们集群中某个节点挂了, 后面有自己启动了, 这样节点比较多了, 就会将所有主题的 leader集中到一个或者某几台服务器上, 这样没有达到负载均衡的效果, kafka有自动平衡策略, 比较耗费集群性能
参数名称 | 描述 |
auto.leader.rebalance.enable | 默认是 true。 自动Leader Partition 平衡。生产环境中,leader 重选举的代价比较大,可能会带来性能影响,建议设置为 false 关闭。 |
leader.imbalance.per.broker.percentage | 默认是 10%。每个 broker 允许的不平衡的 leader的比率。如果每个 broker 超过了这个值,控制器会触发 leader 的平衡。 |
leader.imbalance.check.interval.seconds | 默认值 300 秒。检查 leader 负载是否平衡的间隔时间。 |
4.2.6 kafka日志存储
# topic 是一个逻辑分区, 下面有 分区 分区下面有 Segement 默认每个Segement 存储1G文件,可以通过segment.bytes 修改配置
# 偏移量索引文件 存在 log文件存储 4Kb的数据在索引文件中添加一条日志, 采用稀疏索引存储的
00000000000000000000.index
# 存储正在的日志数据
00000000000000000000.log
# 时间戳索引
00000000000000000000.timeindex
5.消费者
5.1 消费者的基础概念
在kafka每个消费者都是独立的必须要有一个 groupId, 这个groupId 可以吧多个消费者串起来, 一个分区只能被同一个groupId的一个消费者消费消息,反过来说 一个消费者集群有10台机器, 这个分区有10个分区 刚好 每个消费者对应一个分区去消费, 如果分区有5个有10个消费者 剩下的5个消费者就闲着了
5.1.1 消费者的原理
多个消费者组成一个组那么它么怎么消费消息呢, 首先在每个 broker 对消费有一个模块为 coordinator 用来辅助消费者消费数据
如有一个 topic 名称为 user 有 3个分区, 2个副本
消费者组为 g1_user, 这个组中的消费者有4个
首先每个消费者 组名称.getHashCode() % 50 = (coordinator = brokerId)
每个消费者都去请求同一个 coordinator, coordinator会随机选择其中一个消费者 作为消费者中的老大;
选择好消费者 老大后 coordinator 会将所有的消费者发给消费者老大, 消费者老大定制一个消费计划 再次发送给 coordinator;
coordinator 获得消费计划后 分发给组中所有的消费者, 由每个消费者去找 broker 拉取消息, 这样消息就实现了一个消费的过程
在 消费者与coordinator 消费数据的时候 会有一个每3秒的心跳检测机制 一旦超过session.timeout.ms=45s 该消费者就会被移除触发再次平衡 或者 消费者处理消息超过 max.poll.interval.ms5分钟 也会再次触发再平衡策略;
5.1.2 消费者的配置
参数名称 | 描述 |
group.id | 标记消费者所属的消费者组。 |
enable.auto.commit | 默认值为 true,消费者会自动周期性地向服务器提交偏移量。 |
auto.commit.interval.ms | 如果设置了 enable.auto.commit 的值为 true, 则该值定义了消费者偏移量向Kafka 提交的频率,默认 5s。 |
auto.offset.reset | 当 Kafka 中没有初始偏移量或当前偏移量在服务器中不存在(如,数据被删除了),该如何处理? earliest:自动重置偏移量到最早的偏移量。 latest:默认,自动重置偏移量为最新的偏移量。 none:如果消费组原来的(previous)偏移量不存在,则向消费者抛异常。 anything:向消费者抛异常。 |
offsets.topic.num.partitions | consumer_offsets 的分区数,默认是 50 个分区。 |
heartbeat.interval.ms | Kafka 消费者和 coordinator 之间的心跳时间,默认 3s。该条目的值必须小于 session.timeout.ms , 也不应该高于session.timeout.ms 的 1/3。 |
session.timeout.ms | Kafka 消费者和 coordinator 之间连接超时时间,默认 45s。超过该值,该消费者被移除,消费者组执行再平衡。 |
max.poll.interval.ms | 消费者处理消息的最大时长,默认是 5 分钟。超过该值,该消费者被移除,消费者组执行再平衡。 |
fetch.min.bytes | 默认 1 个字节。消费者获取服务器端一批消息最小的字节数。 |
fetch.max.wait.ms | 默认 500ms。如果没有从服务器端获取到一批数据的最小字节数。该时间到,仍然会返回数据。 |
fetch.max.bytes | 默认Default: 52428800(50 m)。消费者获取服务器端一批消息最大的字节数。如果服务器端一批次的数据大于该值(50m)仍然可以拉取回来这批数据,因此,这不是一个绝对最大值。一批次的大小受 message.max.bytes ( brokerconfig)or max.message.bytes (topic config)影响。 |
max.poll.records | 一次 poll 拉取数据返回消息的最大条数,默认是 500 条。 |
partition.assignment.strategy | 消 费 者 分 区 分 配 策 略 , 默 认 策 略 是 Range +CooperativeSticky。Kafka 可以同时使用多个分区分配策略。可以选择的策略包括: Range 、 RoundRobin 、 Sticky 、 |
5.2 消费者代码实现
5.2.1 普通的消费者代码
public static void main(String[] args) {
Properties proper = new Properties();
// 2.给消费者配置对象添加参数
proper.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092,node-2:9092,node-3:9092");
// 配置序列化 必须
proper.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
proper.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 配置消费者组(组名任意起名) 必须
proper.put(ConsumerConfig.GROUP_ID_CONFIG, "g1");
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(proper);
consumer.subscribe(Arrays.asList("test"));
while (true){
ConsumerRecords<String, String> poll = consumer.poll(Duration.ofSeconds(1));
for (ConsumerRecord<String, String> stringStringConsumerRecord : poll) {
System.out.println(stringStringConsumerRecord);
}
}
}
5.2.2 消费者指定消费某个分区
// 删除下面这行代码
// consumer.subscribe(Arrays.asList(topic));
// 消费某个主题的某个分区数据
ArrayList<TopicPartition> topicPartitions = new ArrayList<>();
topicPartitions.add(new TopicPartition("first", 0));
consumer.assign(topicPartitions);
5.2.3 消费者消费策略
// 修改分区分配策略
proper.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,"org.apache.kafka.clients.consumer.RoundRobinAssignor");