内存溢出的原因分析:
当kafka集群服务挂了:
1、生产者继续向kafka发送消息时,有两个超时设置会导致线程不被及时释放
max.block.ms:指定生产者调用send()方法或使用partitionsFor()方法获取元数据时的阻塞时间,默认值60000ms(60秒);
request.timeout.ms:指定了生产者在发送数据时等待服务器返回响应的时间,默认值30000ms(30秒);
2、还有一个缓冲区大小的设置也会导致异常抛出。
buffer.memory:设置生产者内存缓冲区的大小,生产者用它缓冲要发送到服务器的消息,如果应用程序发送消息的速度超过发送到服务器的速度,会导致生产者空间不足。
即使用默认配置,当kafka挂了,线程调用send()方法向kafka发送消息至少会被阻塞60s,线程分分钟就会全部被阻塞,web容器在没有可用线程时收到的请求一般还会存放在队列中等待响应,线程得不到释放意味着内存同样无法被释放,所以很快内存就溢出了。
建议:
1、适当减少阻塞超时时长(测试设置为300ms)
2、增加生产者内存缓冲区,即便kafka挂了只要能即时释放线程及内存,应用服务就不至于挂掉,但阻塞时长过小有可能导致kafka网络波动时部分数据丢失,对数据有严格要求的场景并不适用。另外也可以从线程池里做限制,避免高并发场景下线程堵死的情况。
3、目前测试发现ISR副本同步数据较慢,适当调大拉取线程数。
kafka优化参数:
线程参数
1.负责写磁盘的线程数num.io.threads 建议:整个参数值要占总核数的 50%,比如你的服务器的是 24 核,要给 13 核用于写磁盘
2.副本拉取线程数num.replica.fetchers 建议:这个参数占总核数的 50%的 1/3
3.数据传输线程数num.network.threads 建议:这个参数占总核数的 50%的 2/3
适当调大通讯buffer
socket.receive.buffer.bytes
socket.send.buffer.bytes
队列参数
queued.max.requests=10000 建议:这个参数是指定用于缓存网络请求的队列的最大容量,这个队列达到上限之后将不再接收新请求,产线环境适当调大。
参考:http://www.mstacks.com/131/1384.html#content1384
建议限制内存队列中的最大元素个数。
手动切换leader,如果partition leader为-1。
使用kafka/bin/zookeeper-shell.sh连接zk:(开kerberos认证后,kafka的znode节点有acl认证,使用其他的zkClient时会无法修改)
*
./zookeeper-shell.sh demo1:2181
*
get /brokers/topics/R***/partitions/1/state 查看原始数据
*
set /brokers/topics/R***/partitions/1/state {“controller_epoch”:46,“leader”:1015,“version”:1,“leader_epoch”:10,“isr”:[1015]} #修改副本1015作为leader。
手动切换kafka集群的controller: 修改zk里整个集群的controller也行,会促使重新分发元数据
1、使用kafka/bin/zookeeper-shell.sh连接zk:(开kerberos认证后,kafka的znode节点有acl认证,使用其他的zkClient时会无法修改)
cd /usr/hdp/3.1.0.0-78/kafka/bin
./zookeeper-shell.sh demo1:2181
2、进入zk命令行,定位controller在哪个节点: get /kafka/controller
##(znode也可能是 get /controller)
3、删除/kafka/controller 的znode节点: rmr /kafka/controller
另外还可以重启controller所在broker ,促进controller重新选举。
ack机制,即producer发送消息的确认机制,会影响到kafka的消息吞吐量和安全可靠性,二者不可兼得,只能平均;
ack的取值有三个1、0、-1
ack=0,producer只发送一次消息,无论consumer是否收到;
ack=-1,producer发送的消息,只有收到分区内所有副本都成功写入的通知后才认为发动成功;
ack=1,producer发送的消息只有leader接收成功后才认为消息发送成功,无论leader是否成功将消息同步到follower,所以,ack值为1 也不一定是安全的。
选举新的leader时,容忍n台节点的故障,需要2n+1个副本。
检查topic的ISR发现存在ISR缺失情况,且长时间无法恢复。
当所有的副本都down掉时,必须及时作出反应。有以下两种选择:
- 等待ISR中的任何一个节点恢复并担任leader。
- 选择所有节点中(不只是ISR)第一个恢复的节点作为leader.
如果ISR以外的节点恢复,这个节点的数据就会被作为线上数据,有可能和真实的数据有所出入,因为有些数据它可能还没同步到。这种情况也可能会导致ISR中follower无法恢复。
1、查看网络情况,可能是由于网络问题导致数据延迟,从而导致follower移除。
2、上层应用问题:Server完成 producer request 前需要确认的数量。
上层producer应用acks设置是1 ,等待leader写到local log就行;
建议:acks=all或acks=-1,等待isr中所有副本确认。
(注意:确认都是broker 接收到消息放入内存就直接返回确认,不是需要等待数据写入磁盘后才返回确认,这也是kafka快的原因)。
3、可能存在坏盘,数据丢失导致ISR无法恢复。建议排查磁盘状态
4、ISR无法自动恢复处理。
删除或移动数据到其他空闲磁盘,重启Broker。
1.磁盘删除文件后,释放文件资源后,broker进程不能识别磁盘的空闲资源吗,或者是要等一段时间后才会同步到broker进程中,如果重启broker就会立即触发更新,所以重启后就可以了
2.分区数据还是不能成功写入 有具体的日志报错提示嘛?
3.可以手动将分区目录下的比较老的已经消费了日志文件删除了,不要等异步线程自己去删除,然后是不是可以了
4.Kafka有2个参数控制删除已经消费了的数据,一个是根据时间,一个是根据空间,参数是不是需要调整一下
5.操作之前能先暂停生产数据流入
我只能思考到这,我认为这是典型一个消息积压后,集群不可用的问题
1、登录MRS Manager,单击“服务管理 > Kafka > 实例”,将健康状态为“出错”的Broker实例停止并记录实例所在节点的管理IP地址以及对应的“broker.id”,该值可通过单击角色名称,在“实例配置”页面中设置“参数类别”为“全部”,搜索“broker.id”参数获取。
2、使用PuTTY工具以root用户登录记录的管理IP地址,并执行df -lh命令,查看磁盘占用率为100%的挂载目录,例如“/srv/BigData/kafka/data1”。
3、进入该目录,执行du -sh *命令,查看该目录下各文件夹的大小。查看是否存在除“kafka-logs”目录外的其他文件,并判断是否可以删除或者迁移。
是,删除或者迁移相关数据,然后执行步骤 8。
否,执行步骤 4。
4、进入“kafka-logs”目录,执行du -sh *命令,选择一个待移动的Partition文件夹,其名称命名规则为“Topic名称-Partition标识”,记录Topic及Partition。
5、修改“kafka-logs”目录下的“recovery-point-offset-checkpoint”和“replication-offset-checkpoint”文件(两个文件做同样的修改)。
减少文件中第二行的数字(若移出多个目录,则减少的数字为移出的目录个数)。
删除待移出的Partition所在的行(行结构为“Topic名称 Partition标识 Offset”,删除前先将该行数据保存,后续此内容还要添加到目的目录下的同名文件中)。
6、修改目的数据目录下(例如/“/srv/BigData/kafka/data2/kafka-logs”)的“recovery-point-offset-checkpoint”和“replication-offset-checkpoint”文件(两个文件做同样的修改)。
增加文件中第二行的数字(若移入多个Partition目录,则增加的数字为移入的Partition目录个数)。
添加待移入的Partition行到文件末尾(行结构为“Topic名称 Partition标识 Offset”,直接复制步骤 5中保存的行数据即可)。
7、移动数据,将待移动的Partition文件夹移动到目的目录下,移动完成后执行chown omm:wheel -R Partition目录命令修改Partition目录属组。
8、登录MRS Manager,单击“服务管理 > Kafka > 实例”,启动停止的Broker实例。
9、等待5-10分钟后查看Broker实例的健康状态是否为“良好”。
./kafka-server-start.sh …/config/server.properties &
创建topic
bin/kafka-topics.sh --zookeeper ip1:2181,ip2:2181,ip3:2181 --topic mytopic --replication-factor 1 --partitions 1 --create
显示topic
bin/kafka-topics.sh --zookeeper ip1:2181,ip2:2181,ip3:2181 --list
查看详细信息
bin/kafktopics.sh --describe --zookeeper ip1:2181,ip2:2181,ip3:2181
生产数据
./kafka-console-producer.sh --broker-list ip1:9092 --topic mytopic
接收消息:
./kafka-console-consumer.sh --zookeeper localhost:2181 --topic mytopic --from-beginning
查看分区编号:
cat /data01/kafka-logs/meta.properties
/usr/hdp/current/kafka-broker/bin/kafka-topics.sh --describe --zookeeper @@@174.29.248:2181,@@@174.29.249:2181,@@@174.29.250:2181
/usr/hdp/3.1.0.0-78/zookeeper/bin/zkCli.sh -server oc-gx-29-248:2181,oc-gx-29-249:2181,oc-gx-29-250:2181
Topic:ITD_EVENT_CENTER_yzsj PartitionCount:20 ReplicationFactor:2 Configs:retention.ms=17280000
Topic:__consumer_offsets PartitionCount:40 ReplicationFactor:3 Configs:
Topic:itd_5g_control_cell_MR PartitionCount:20 ReplicationFactor:2 Configs:retention.ms=17280000
Topic:itd_5g_control_f1 PartitionCount:20 ReplicationFactor:2 Configs:retention.ms=17280000
Topic:itd_5g_control_n26 PartitionCount:20 ReplicationFactor:2 Configs:retention.ms=17280000
Topic:itd_5g_use_mms PartitionCount:20 ReplicationFactor:2 Configs:retention.ms=17280000
Topic:itd_yx_mme PartitionCount:240 ReplicationFactor:2 Configs:retention.ms=72000000
ISR无法自动恢复处理:
创建文件:cat topics-to-move.json
{“topics”: [{“topic”: “shanxi.dim.json”}
],
“version”:1
}
生成partitions迁移计划:
bin/kafka-reassign-partitions.sh --zookeeper @@@174.29.248:2181,@@@174.29.249:2181,@@@174.29.250:2181 --topics-to-move-json-file topics-to-move.json --broker-list “1007,1008,1009,1010,1011,1012” —generate
复制生成的迁移计划(Proposed partition reassignment configuration)到topics-reassignment.json文件中,执行迁移计划:
cat topics-reassignment.json
{“version”:1,
“partitions”:[
{“topic”:“stock_cbss_main_order_9”,“partition”:123,“replicas”:[1011,1012]}
]
}
bin/kafka-reassign-partitions.sh --zookeeper dn01.hadoop.unicom:2181,dn08.hadoop.unicom:2181,dn16.hadoop.unicom:2181 --reassignment-json-file topics-reassignment.json --execute
使用–verify查看进度
bin/kafka-reassign-partitions.sh --zookeeper dn01.hadoop.unicom:2181,dn08.hadoop.unicom:2181,dn16.hadoop.unicom:2181 --reassignment-json-file topics-reassignment.json --verify
查看topic ISR分布:
bin/kafka-topics.sh --describe --topic shanxi.dim.json --zookeeper dn01.hadoop.unicom:2181,dn08.hadoop.unicom:2181,dn16.hadoop.unicom:2181
/usr/hdp/current/kafka-broker/bin/kafka-topics.sh --describe --topic itd_yx_mme --zookeeper @@@174.29.248:2181,@@@174.29.249:2181,@@@174.29.250:2181
[zk: oc-gx-sp-29-248:2181,oc-gx-sp-29-249:2181,oc-gx-sp-29-250:2181(CONNECTED) 2] ls /brokers/ids
[1008, 1007, 1006, 1005, 1004, 1003, 1002, 1001, 1010, 1009]
./runRemoteCmd.sh “cat /data/data1/kafka-logs/meta.properties” k
kafka宕机恢复过程
1 新建一个broker, id跟宕掉的broker一样。启动该broker
2 通过下面脚本查看恢复状态
./kafka-topics.sh --zookeeper @@@.168.6.20:2181 --describe --unavailable-partitions
3 确认下所有broker启动正常,如果有因为leader的offset滞后导致不能启动的,需要设置
unclean.leader.election.enable=true
然后所有broker重起。