kafka优化和相关问题
Kafka的Message存储采用了分区(partition),分段(LogSegment)和稀疏索引这几个手段来达到了高效性。
Kafka消息数据积压,Kafka消费能力不足怎么处理?
1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)
2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。
kafka丢失数据原因:
-
生产者生产的数据还没同步到 follower 当中,leader宕机了,重新选举之后造成了数据丢失
-
同步模式解决问题:设置ack应答为all或者-1。并引入幂等写操作
-
异步模式,当缓冲区满了,如果配置为0(没有收到确认,一满就丢弃),数据立刻丢弃 ----解决:不限制阻塞超时时间。就是一满生产者就阻塞
producer.type = async queue.enqueue.timeout.ms = -1 //设置队列缓冲区超时时长为-1 无限等待
-
-
kafka的数据一开始就是存储在PageCache上的,定期flush到磁盘上的,也就是说,不是每个消息都被存储在磁盘了,如果出现断电或者机器故障等,PageCache上的数据就丢失了。
- 解决问题:设置flush的触发条数,flush的定期触发时长
-
单批数据的长度超过限制会丢失数据,报kafka.common.MessageSizeTooLargeException异常
- 解决问题:大数据尽量分批发放
-
消费者丢失数据:业务执行异常,自动提交offset,导致丢失数据,
- 解决方案:设置为处理完手动提交
-
在自动提交消费位置之前异常关闭了kafka丢失数据
Consumer重复消费的原因:
-
直接kill了线程,导致消费后offset没有提交
-
设置offset为自动提交,关闭kafka时,如果在close之前,调用 consumer.unsubscribe() 则有可能部分offset没提交,下次重启会重复消费。
-
消费后的数据,当offset还没有提交时,partition就断开连接。
-
当消费者重新分配partition的时候,可能出现从头开始消费的情况,导致重发问题。
-
当消费者消费的速度很慢的时候,可能在一个session周期内还未完成,导致心跳机制检测报告出问题
参数优化
2、log数据文件刷盘策略
# 每当producer写入10000条消息时,刷数据到磁盘
log.flush.interval.messages=10000
# 每间隔1秒钟时间,刷数据到磁盘
log.flush.interval.ms=1000
3、日志保留策略配置
# 保留三天,也可以更短 (log.cleaner.delete.retention.ms)
log.retention.hours=72
4、Replica相关配置
offsets.topic.replication.factor:3
# 这个参数指新创建一个topic时,默认的Replica数量,Replica过少会影响数据的可用性,太多则会白白浪费存储资源,一般建议在2~3为宜。
kafka日志:
每个分区目录下面有三个日志文件,xxx.log是消息集文件, xxx.index 偏移量索引文件 ,xxx.timeindex 时间戳索引文件
在server.properties中配置了log.dirs值,表示kafka数据的存放目录,而非Kafka的日志目录。
[root@node1 kafka_2.11-1.0.1]# vi config/server.properties
log.dirs=/data/kafka
Kafka运行时日志默认输出到$KAFKA_HOME/logs目录下,容易撑爆分区,造成操作系统崩溃。需要将日志输出到指定分区,比如/var/log目录下。
日志优化:
设置日志保留策略、清理、压缩。
1、当kafka server的被写入海量消息后,会生成很多数据文件,且占用大量磁盘空间,如果不及时清理,可能磁盘空间不够用,kafka默认是保留7天。2、可以合理的设置可以通过设置cleanup.policy来清理特定大小的日志文件,或者设定在某个时间点清理 。3、压缩操作会对Topic中每个键进行处理,只保留其最后一个值,并清除所有其他重复项
2)Producer优化(producer.properties)
buffer.memory:33554432 (32m)
#在Producer端用来存放尚未发送出去的Message的缓冲区大小。缓冲区满了之后可以选择阻塞发送或抛出异常,由block.on.buffer.full的配置来决定。
生产者批次发送(设置消息积累大小 batch_size 或者逗留时间 Linger Time ) 触发之后统一发送
设置同步或者异步发送( Sync or Async )
compression.type:none
#默认发送不进行压缩,推荐配置一种适合的压缩算法,可以大幅度的减缓网络压力和Broker的存储压力。
Kafka内存调整(kafka-server-start.sh)
默认内存1个G,生产环境尽量不要超过6个G。
export KAFKA_HEAP_OPTS=“-Xms4g -Xmx4g”
broker端:
-
broker能接收消息的最大字节数的设置一定要比消费端能消费的最大字节数要小,否则broker就会因为消费端无法使用这个消息而挂起。
-
broker设定的可接受的最大字节数必须得生产者发送的的数据要大,否则broker就会因为数据量的问题无法复制副本,导致数据丢失
-
网络和io操作线程配置优化
# broker处理消息的最大线程数(默认为3)
num.network.threads=cpu核数+1
# broker处理磁盘IO的线程数
num.io.threads=cpu核数*2
consumer端:
- 关闭自动更新offset,等到数据被处理后再手动跟新offset。
在消费前做验证前拿取的数据是否是接着上回消费的数据,不正确则return先行处理排错。
一般来说zookeeper只要稳定的情况下记录的offset是没有问题,除非是多个consumer group 同时消费一个分区的数据,其中一个先提交了,另一个就丢失了。 - fetch.message.max.bytes这将决定消费者可以获取的数据大小。值越大,吞吐量越大,可以适当设定
- 消费者数量建议和分区相同
- 设置检查点,当出现异常时可重新读取数据
topic端:
合理设置分区,避免热点数据
充分利用Apache ZooKeeper :
ZooKeeper节点的数量一般最多5个。一个节点适合于开发环境,对于大多数生产环境三个节点的Kafka集群足够了。虽然大型Kafka部署可能需要5个ZooKeeper节点来减少延迟,但是必须考虑节点上的负载。如果7个或更多的节点同步和处理请求,整个系统的负载将变得非常大,性能可能会有明显的影响。
合理地使用并行处理:
根据保守的估计,单个Topic上一个分区可以交付10MB /s,以此进行推断,可以获得所需的总吞吐量。