安装
下载地址:
https://archive.apache.org/dist/kafka/
zookeeper下载地址
http://archive.apache.org/dist/zookeeper/
复制kafka server.properties复制三份
分别命名
server1.properties, server2.properties, server3.properties
分别更改配置
broker.id=0 broker集群要不同
listeners=PLAINTEXT://192.168.100.151:9092
log.dirs=/yangk/kafka/kafka1/logs
这里是使用同一台机器, 所以分别 9092,9093,9094
分别启动
./kafka/bin/kafka-server-start.sh server-cluser-config/server1.properties &
./kafka/bin/kafka-server-start.sh server-cluser-config/server2.properties &
./kafka/bin/kafka-server-start.sh server-cluser-config/server3.properties &
producer生成者常用参数设置:
key.serializer: key序列化,指定类
value.serializer:value序列化,指定类。
acks:取值0,1,-1
acks=0; 不会等待服务器返进行确认,直接返回。
acks=1; 等待leader分区确认同步,不会等待其他flower同步到
acks=-1; 等待所有分区同步成功, 包括leader 和flower同步成功
bootstrap.servers: 生产者地址列表 host:port,host:post
buffer.memory: 缓冲等待发送的记录的总内存大小
compression.type:压缩类型,用来压缩批量信息操作。 none, gzip, snappy, lz4, zstd
retries : 大于0时 ,进行重试次数,当发送失败时客户端会进行重试,重试的次数由retries指定,此参数默认设置为0。即:快速失败模式,当发送失败时由客户端来处理后续是否要进行继续发送
retries = Integer.MAX_VALUE
max.in.flight.requests.per.connection = 1
key.deserializer :
value.deserializer :
bootstrap.servers:
fetch.min.bytes: 服务器应为获取请求返回的最小数据量。如果没有足够的数据可用,则请求将在回答请求
之前等待积累足够多的数据。1 字节的默认设置意味着只要有一个字节的数据可用或获取
请求超时等待数据到达就会响应获取请求。将此设置为大于 1 的值将导致服务器等待大量
数据积累,这可以稍微提高服务器吞吐量,但会增加一些延迟
fetch.max.bytes:服务器应为获取请求返回的最大数据量。记录由消费者分批获取,如果获取的第一个非空
分区中的第一个记录批次大于该值,则仍会返回该记录批次,以确保消费者可以取得进
展。因此,这不是绝对最大值
group.id: 消费组id
heartbeat.interval.ms: 消费者协调器的心跳之间的预期时间。心跳用于确保消费者的会话保持活跃,并在
新消费者加入或离开组时促进重新平衡。该值必须设置为低于session.timeout.ms,但通常不应设置为高于该值的 1/3。它可以调整得更低,以控制正常重新平衡的预期时
间。
max.partition.fetch.bytes: 服务器将返回的每个分区的最大数据量。记录由消费者批量获取。如果
fetch 的第一个非空分区中的第一个记录批次大于此限制,则仍会返回该批次以确保
消费者可以取得进展
session.timeout.ms: 客户端定期发送心跳以向代理指示其活跃度。如果在此会话超时到期之前代理没有收到
心跳,则代理将从组中删除此客户端并启动重新平衡
auto.offset.reset:
earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的
offset时,从头开始消费
latest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset
时,消费新产生的该分区下的数据
none: topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不
存在已提交的offset,则抛出异常
Rebalance
rebalance本质上是一种协议,规定了一个consumer group下的所有consumer如何达
成一致来分配订阅topic的每个分区;
什么时候rebalance?
rebalance的触发条件有三种:
1.组成员发生变更(新consumer加入组、已有consumer主动离开组或已有consumer崩溃了)
2.组订阅 topic 数发生变更,比如使用基于正则表达式的订阅,当匹配正则表达式的新 topic 被创建时则会触发 rebalance
3.组订阅 topic 的分区数发生变更,比如使用命令行脚本增加了订阅 topic 的分区数;
这里我摘自 《kafka 实战》作者的经历来说明:
Rebalance协议
Join Group 请求: consumer 请求加入组
SyncGroup 请求: group leader 把分配方案同步更新到组内所有成员中 Heartbeat 请求: consumer 定期向 coordinator 汇报心跳表明自己依然存
Heartbeat 请求: consumer 定期向 coordinator 汇报心跳表明自己依然存
LeaveGroup 请求: consumer 主动通知 coordinator consumer 即将离组
LeaveGroup 请求: consumer 主动通知 coordinator consumer 即将离组
Rebalance流程
那么consumer group如何确定自己的coordinator是谁呢?
具体计算公式: consumers_offsets partition# = Math.abs(groupId.hashCode() % groupMetadataTopicPartitionCount) 注意:groupMetadataTopicPartitionCount由offsets.topic.num.partitions指定,默认是50个分区。
该分区leader所在的broker就是被选定的coordinator
流程图来自 《kafka开发实战》
joinGroup 请求阶段
SyncGroup 请求阶段
关于offset的消费位置?表示消费到哪里?
String key=” ghztest1”;/消费组id
partition = Math.abs(k.hashCode()) % partition;
System.out.println(partition);//得到消费组消费的offset的位置
查看主题信息 信息。
./kafka-topics.sh --bootstrap-server 192.168.226.128:9092,192.168.226.128:9093,192.168.226.128:9094 --topic GHZabcd --describ
如果没有设置副本数据, 则当broker挂了, 则该主题topic则不能使用
修改副本数量, 来解决单机问题
新键 :replication.json
{
"version": 1,
"partitions": [
{
"topic": "GHZabcd",
"partition": 0,
"replicas": [
1,
2,
3
]
},
{
"topic": "GHZabcd",
"partition": 1,
"replicas": [
2,
3,
1
]
},
{
"topic": "GHZabcd",
"partition": 2,
"replicas": [
3,
2,
1
]
},
{
"topic": "GHZabcd",
"partition": 3,
"replicas": [
1,
2,
3
]
}
]
}
执行:
./kafka-reassign-partitions.sh --zookeeper 127.0.0.1:2181 --reassignment-json-file replication.json –execute
副本协同机制
Leader-> flower 分区同步
- GHZabcd 分为4个分区
GHZabcd-0, leader 节点为3 (brokerid=3) 副本列表:brokerId=1,2,3
GHZabcd-1, leader 节点为3 (brokerid=3) 副本列表:brokerId=2,3,1
GHZabcd-2, leader 节点为3 (brokerid=3) 副本列表:brokerId=3,2,1
GHZabcd-3, leader 节点为3 (brokerid=3) 副本列表:brokerId=1,2,3
- ISR (In Sync Replica)
1)leader会维持一个与其保持同步的replica副本集合,该集合就是ISR,每一个partition都有一个ISR,它时有leader动态维护。
2)我们要保证kafka不丢失message,就要保证ISR这组集合存活(至少有一个存活),并且消息commit成功。
同步复制: leader 每消费一条数据,所有的flower同步成功,才被commit 成功。 一致性高,可用性不高。
异步复制: leader 每消费一条数据, 等follower慢慢去复制,可用高,立即返回,一致性差一些。
Commit: leader 向客户端确认该消息以及消费,必须要所有的flower
都向leader 发送确认ack;
什么时候ISR会发生变化?
ISR 是由leader 维护
- 当在某个时间段内,leader 未收到flower的fetch同步请求。
- 当leader 与flower 的同步数据相差阈值。则剔出 ISR;等待flower再次属于阈值内。
Server.properties
rerplica.lag.time.max.ms=10000; //flower在规定时间内没向leader发送fetch 请求。 则踢出ISR
rerplica.lag.max.messages=1; //flower 与leader 相差的数据大于阈值。 则提出。等待小于阈值再次加入
对于生产者来说: 为了保证幂等性。 则必须要保证。 所有的flower向leader同步成功才会。
request.required.asks=-1.