Kafka 基础梳理

Kafka 基础梳理

角色

  1. Kafka Cluster(Kafka服务集群),每个服务节点称为:Broker。
  2. Broker之间基本上是对等关系,通常第一个启动的broker角色为:Controler
  3. Controler 通过zk集群获取kafka的元数据,同时负责把元数据信息同步到其他Broker上面
  4. 生成者(Producer)
  5. 消费者(Consumer)
  6. 内部是:主题(Topic)存储,是逻辑概念
  7. Topic可以有多个分区(Partition),主题默认一个分区,分区是数据存储的实体目录
  8. 分区采用主从架构,分为:leader 和 follower。对外服务统一都由 leader 负责

数据存储(Producer)

  1. 数据写入,采用磁盘 顺序写(追加写)
  2. 数据存储采用分段存储,存储参数如下:
// 数据存储参数
log.segment.bytes=1G // Partition默认切割文件大小 1G
log.roll.ms=60 * 60 * 1000 // 指定roll文件的时间,毫秒单位,优先级高于 log.roll.hours
log.roll.hours=168 // 指定roll的时间,小时单位,默认 168,即7天
  1. 文件类型
类型说明备注
.index偏移量索引文件1、偏移量采用多级、稀松索引,每写4k数据创建一个索引
2、内容为 offset:position,即:偏移量 和 物理位置
.timestamp时间戳索引文件
.log日志文件存储消息数据,以当前文件中第一条数据的偏移量(offset)命名

数据读取(Consumer)

  1. 数据读取(Consumer),采用 零拷贝

zookeeper 参数配置

  • zoo.cfg 文件配置
clientPort=2181 // 默认端口号

/**
 * 默认将事务日志文件和快照日志文件都存储在dataDir对应的目录下。
 * 建议将事务日志(dataLogDir)与快照日志(dataLog)单独配置,
 * 因为当zk集群进行频繁的数据读写操作时,会产生大量的事务日志信息,
 * 将两类日志分开存储会提高系统性能,
 * 而且,可以允许将两类日志存在在不同的存储介质上,
 * 利用磁盘顺序写的特性,提高日志写入速度。
 */
dataDir=/usr/local/zk/data // 数据存储目录(快照日志)
dataLogDir=/usr/local/zk/dataLog // 事物日志存储目录

/**
 * zk集群服务器信息,IP(或主机名)、端口信息,
 * 假如有3台服务器,配置参考如下:
 * 其中 server后面的数字就是zk节点的别名,取值在 0-255,不可重复
 * 端口 2888:选主的端口
 * 端口 3888:集群内部通信端口
 */
server.1=hodoop1:2888:3888
server.2=hodoop2:2888:3888
server.3=hodoop3:2888:3888
  • myid 文件
/**
 * zoo.cfg 文件中配置项目:dataDir=/usr/local/zk/data 的目录下
 * 创建 myid 文件(touch myid),里面输入zk节点的别名,
 * 例如 server.1 的别名就是:1
 */ 

核心参数配置(server.properties)

broker.id=0 // 每个kafka节点都必须设置唯一的id,自然数即可
log.dirs=/d01/kafka/data,/d02/kafka/data // 设置kafka日志(即消息数据)存放的目录,通常一个磁盘对应一个目录,多个磁盘的目录使用逗号分隔
zookeeper.connect=Hadoop1:2181,hadoop2:2181,hadoop3:2181 // controller broker对kafka的管理,就是监听zk的元数据目录
listeners=PLAINTEXT://hadoop1:9092 // broker监听客户端发送请求的端口号,其中 hadoop1 是主机名,9092为端口号
delete.topic.enable=true // 默认为true,允许删除topic
log.retention.hours=168 // kafka的数据生命周期,默认是 168小时(7天),可以按需调整
log.retention.bytes=-1 // 如果分区的数据量超过这个限制,就会自动清理数据,此参数不常用,默认为 -1意味不按照此规则来处理
num.network.threads=3 // kafka接收数据请求的线程数,默认为3个,可以调整到 6 或 9个
num.io.threads=8 // kafka处理数据请求的线程数,默认为8个,可以根据cpu core数量调整,16、24、32都可,需要硬件支持
num.patitions=1 // topic默认的分区数,默认为 1,需用修改,一般在实际使用时具体指定
log.flush.intelval.ms=1000 // kafka将os cache里数据刷写到本地磁盘的等待时间,默认是 1s,太小,建议设置成1分钟,60 * 1000
log.flush.intelval.meassages=10000 // kafka将数据写入本地磁盘时,需要等待的消息条数,默认为 1w条,就够用了
message.max.bytes= // 单条消息的最大值,默认是 977k(约等于1m),太小,一般设置为 10m,10 * 1024 * 1024
/**
 * 默认1,生产者发送数据成功最小需要ISR的副本数量。
 * 这个参数会配合 生产者的 request.required.acks 参数使用,
 * 尤其当 request.required.acks=-1 时,
 * min.insync.replicas>=2 且 replication.factor>=2时,不会丢数据。
 * request.required.acks 有3个值,默认为 1
 * 1:服务端leader partition收到数据即认为发送成功;
 * 0:不等待服务端响应就继续发送数据,此方式发送效率最高,但数据可靠性最低;
 * -1:等待服务端的设定的最小副本都确认收到才认为发送成功,此方式数据可靠性最高,发送效率最低
 */
min.insync.replicas=1
replication.factor=1 // ISR(即:in sync replica),服务端设置的分区副本数,默认为1,考虑到数据可靠性,至少设置为 2

服务启动及测试

# 服务启动
./kafka-server-start.sh -deamon ../config/server.properties
# 服务停止
./kafka-server-stop.sh

# 创建主题,分区为3,每个分区副本为2
./kafka-topics.sh --create --zookeeper host1:2181,host2:2181,host3:2181 --replication-factor 2 --patitions 3 --topic test
# 查看topic
./kafka-topics.sh --list --zookeeper hodoop1:2181,hodoop2:2181,hodoop3:2181

# 客户端工具:创建生成者
./kafka-console-producer.sh --broker-list hadoop1:9092,hadoop2:9092,hadoop3:9092 --topic test
# 客户端工具:创建消费者
./kafka-console-consumer.sh --bootstrap-server hadoop1:9092,hadoop2:9092,hadoop3:9092 --topic test --from-beginning

# 压力测试
# 生产数据,往topic:test上写入 50w数据,每个数据大小是200字节
# 测试结果参考下图
./kafka-producer-perf-test.sh --topic test --num-records 500000 --record-size 200 --throughput 1 --producer-props bootstrap-servers=hadoop1:9092,hadoop2:9092,hadoop3:9092
# 消费数据,从topic:test上消费50w数据
./kafka-producer-perf-test.sh --broker-list hadoop1:9092,hadoop2:9092,hadoop3:9092 --fetch-size 2000 --messages 500000 --topic test

参考写入数据测试结果,50w条数据写入效率:大约 5w/s,效率很好!
在这里插入图片描述
参考消费数据测试结果,50w条数据消费效率:大约3.7w/s,效率很好!!
在这里插入图片描述

运维命令

# topic 数量大,需要调整分区
# 创建topic:test1,分区为1
./kafka-topics.sh --create --zookeeper host1:2181,host2:2181,host3:2181 --replication-factor 1 --patitions 1 --topic test1
# 调整分区为:3个
./kafka-topics.sh --alter --zookeeper host1:2181,host2:2181,host3:2181 --patitions 3 --topic test1

# 增加副本
# touch myjson.json
# 分区 patition0 副本3个,存储在 broker :0、1、2 三台服务器上
# 其他分区同理
{
  "version":1,
  "patitions": [
    {"topic":"test1","partition":0,"replicas":[0,1,2]},
    {"topic":"test1","partition":1,"replicas":[0,1,2]},
    {"topic":"test1","partition":2,"replicas":[0,1,2]}
  ]
}

# 执行json脚本,增加副本
./kafka-reassign-partitions.sh --zookeeper host1:2181,host2:2181,host3:2181 --reassignment-json-file myjson --execute

# 负载不均衡topic,手动迁移
# touch topicMove.json <- 准备迁移的topic:test1 和 test2
{
  "version":1,
  "topics":[
    {"topic":"test1"},
    {"topic":"test2"}
  ]
}

# 迁移指令,“5,6” 就是要迁移的目标broker id,执行后会生成一个迁移方案
# 迁移方案会生成在文件:expand-cluster-reassignment.json 中
./kafka-reassign-partitions.sh --zookeeper host1:2181,host2:2181,host3:2181 --topics-to-move-json-file topicMove.json --broker-list "5,6" --generate

# 执行上述 迁移方案
./kafka-reassign-partitions.sh --zookeeper host1:2181,host2:2181,host3:2181 --reassignment-json-file expand-cluster-reassignment.json --execute

# 验证迁移方案
./kafka-reassign-partitions.sh --zookeeper host1:2181,host2:2181,host3:2181 --reassignment-json-file expand-cluster-reassignment.json --verify

# 默认为true,自动负载均衡
auto.leader.rebalance.enable=true
# 每个broker允许的不平衡leader的比例,
# 如果每个broker超过这个值,控制器会触发leader平衡
# 这个值表示百分比
leader.imbalance.per.broker.percentage=10
# 默认值 300s,每隔 300s检查leader是否平衡
leader.imbalance.check.intelval.seconds=300

生产者(Producer)吞吐量调优

buffer.memory=33554432 // 生成者缓存池大小,默认32m
compression.type=lz4 // 生产者发送数据是否启用压缩,默认none,不压缩;可以使用 lz4 算法压缩。开通压缩后,会增加cpu开销
batch.size=16384 // 生产者发送消息批次大小,默认 16k,较小,可以考虑适当调大,例如:32768(32m)
linger.ms=100 // 默认为0,意味着消息一来就要被发送出去,不合理。配合 batch.size 参数使用,当 batch.size 设定的大小在指定时间内无法达到的时候,批次也会正常发送出去,可以设置为 100ms

生产者其他参数

// 保证生产者(Producer)同时只能发送一条消息
// 防止消息乱序(消息重复发送的时候导致)
max.in.flight.requests.per.connection=1

// 重试,当消息发送失败的时候,系统会自动重试
retries=3
// 配合 retries 参数一起使用,重试等待时间,单位毫秒
retry.backoff.ms=100

消费者(Consumer)偏移量存储

  • kafka内部集成 topic 用于存储消费者偏移量
  • topic名称为:__comsumer_offsets,默认有 50个分区
  • key:group_id + topic + partition_id
  • value:当前offset
  • 监控消费者的offset(工具:KafkaOffsetMonitor-assembly-0.3.0-SNAPSHOT.jar)
# touch monitor.sh & vi monitor.sh
# 工具支持kafka存储offset 和 zk存储offset
# 如果是zk存储,参数 --offsetStorage zookeeper 即可
# chmod +x monitor.sh 之后,后台运行脚本:nohup ./monitor.sh &
# 运行成功后,网页端输入:hadoop1:9004 即可
java -cp KafkaOffsetMonitor-assembly-0.3.0-SNAPSHOT.jar \
     com.quantifind.kafka.offsetapp.OffsetGetterWeb \
     --offsetStorage kafka \
     --zk hadoop1:2181 \
     --port 9004 \
     --refresh 15.seconds \
     --retain 2.days

消费者(Consumer)参数配置

/**
 * 消费者(Consumer)与协调员(在某个broker上启动的Coordinator)
 * 之间的心跳时间间隔,一旦故障了,会通过心跳下发rebalance到consumer
 * 其他consumer会做rebalance操作
 */
heartbeat.intelval.ms=3000
// kafka长时间感知不到一个consumer就认为它故障了,默认10s
session.timeout.ms=10*1000
/**
 * 如果两次poll操作时间超过设定值
 * 就认为这个consumer处理能力太弱,会被提出消费组
 */
max.poll.interval.ms=5*1000

// 消费者获取单条消息的最大值,默认1m,建议设置大一些,比如10m
fetch.max.bytes=10*1024*1024
// 消费者一次最多获取多少条数据,默认500条
max.poll.records=500
// 消费者和broker的连接时间空闲一段时间,该连接资源会被回收
// 一般建议设置成-1,就是一直不回收
connection.max.idle.ms=-1
// 允许消费者消费后自动提交offset到__consumer_offsets主题中,默认为true
enable.auto.commit=true
// 每隔多久提交一次offset,参考参数:enable.auto.commit
auto.commit.intelval.ms=5*1000
/**
 * 生产上配置为:latest
 * ealiest:当各分区下有已提交的offset时,从提交offset开始消费,否则从头消费
 * latest:当各分区下有已提交的offset时,从提交offset开始消费,否则消费新产生的该分区下的数据
 * none:当各分区下有已提交的offset时,从提交offset开始消费,只要有一个分区不存在已提交offset记录,就报异常
 */
auto.offset.reset=latest

消费者(Consumer)与协调器(Coordinator)

  1. 使用groupId获取hash值,然后对__consumer_offsets的partition数量(默认为:50个)取模,取模得到的partition所在的broker就作为coordinator,该partition也是该group下所有分区提交offset的分区
  2. 每个consumer都发送JoinGroup请求到Coordinator
  3. Coordinator从consumer group中选择一个consumer作为leader
  4. 然后把consumer group的情况发送给leader
  5. leader接着会指定消费方案
  6. 通过SyncGroup发给Coordinator
  7. Coordinator把消费方案下发给所有consumer,他们会从指定的分区的leader broker开始进行socket连接以及消费信息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值