一、当Kafka集群开始"喊饿"时
做运维的朋友们都知道,Kafka就像个贪吃的小孩,数据量一大就开始嚷嚷"磁盘不够用了"。上周我就遇到了这个情况:凌晨三点收到报警,某个业务集群的磁盘使用率已经突破90%,消息积压量像坐火箭一样往上窜。
这种情况其实很常见,特别是在业务快速增长期。比如我们有个电商平台,大促期间订单消息量突然暴增5倍,原本能撑3个月的磁盘空间,2周就被塞得满满当当。这时候就需要我们像老中医一样,既要治标(快速扩容),又要治本(合理清理)。
二、紧急扩容:给Kafka"加餐"
当磁盘空间告急时,最直接的解决方案就是扩容。这里我以AWS环境为例,演示如何给Kafka broker节点动态添加EBS卷。
# 技术栈:AWS CLI + Linux
# 首先查看当前磁盘情况
df -h | grep /kafka_data # 假设Kafka数据目录挂载在/kafka_data下
# 在AWS控制台创建新的EBS卷后,附加到EC2实例
aws ec2 attach-volume \
--volume-id vol-1234567890abcdef0 \
--instance-id i-0123456789abcdef \
--device /dev/sdf
# 在实例上格式化新磁盘(注意:这会清空磁盘数据!)
sudo mkfs -t xfs /dev/nvme1n1 # 根据实际设备名调整
# 创建挂载点并更新fstab
echo "/dev/nvme1n1 /kafka_data2 xfs defaults,nofail 0 2" | sudo tee -a /etc/fstab
sudo mkdir /kafka_data2
sudo mount -a
# 修改Kafka配置,添加新的日志目录
vim /etc/kafka/server.properties
# 找到log.dirs参数,添加新路径(多个路径用逗号分隔)
log.dirs=/kafka_data,/kafka_data2
# 滚动重启Kafka broker
sudo systemctl restart kafka
注意事项:
- 生产环境建议在业务低峰期操作
- XFS文件系统对Kafka性能更友好
- 确保新磁盘的IOPS配置足够高
- 记得更新监控系统的磁盘告警阈值
三、数据清理:给Kafka"瘦身"
扩容只是权宜之计,合理的清理策略才是长久之道。Kafka提供了多种数据清理机制,我们来详细看看。
3.1 基于时间的保留策略
# Kafka配置示例
log.retention.hours=168 # 保留7天数据
log.segment.bytes=1073741824 # 每个日志段1GB
log.cleanup.policy=delete # 删除过期数据
这个配置表示:
- 消息保存7天(168小时)
- 每个日志文件达到1GB就会切分新文件
- 采用删除策略而非压缩
3.2 基于大小的保留策略
log.retention.bytes=53687091200 # 每个分区保留50GB
实用技巧:可以通过kafka-topics.sh动态调整已有topic的配置:
bin/kafka-configs.sh --zookeeper localhost:2181 \
--entity-type topics --entity-name order_events \
--alter --add-config retention.bytes=107374182400 # 设置为100GB
3.3 手动清理大法
有时候自动清理不够及时,我们可以手动删除旧数据:
# 首先找出需要清理的topic分区
ls -lh /kafka_data/order_events-*/ | sort -rh
# 使用kafka-delete-records.sh删除旧偏移量之前的数据
cat << EOF > offsets.json
{
"partitions": [
{
"topic": "order_events",
"partition": 0,
"offset": 15234500
}
],
"version": 1
}
EOF
bin/kafka-delete-records.sh \
--bootstrap-server localhost:9092 \
--offset-json-file offsets.json
四、进阶优化:让Kafka"吃得更健康"
4.1 分区再平衡
当添加新磁盘后,可以使用kafka-reassign-partitions.sh工具将部分分区迁移到新磁盘:
// reassign.json
{
"version": 1,
"partitions": [
{"topic": "order_events", "partition": 0, "replicas": [1,2], "log_dirs": ["/kafka_data","/kafka_data2"]},
{"topic": "payment_events", "partition": 3, "replicas": [2,3], "log_dirs": ["/kafka_data2","/kafka_data"]}
]
}
执行命令:
bin/kafka-reassign-partitions.sh \
--bootstrap-server localhost:9092 \
--reassignment-json-file reassign.json \
--execute
4.2 监控与告警配置
建议监控以下关键指标:
- 磁盘使用增长率
- 消息保留时间与实际业务需求差距
- 清理线程是否正常工作
# 示例Prometheus告警规则
- alert: KafkaDiskUsageCritical
expr: kafka_log_log_size / kafka_log_log_size_limit > 0.8
for: 30m
labels:
severity: critical
annotations:
summary: "Kafka disk usage high on {{ $labels.instance }}"
description: "Disk usage is {{ $value }}% for topic {{ $labels.topic }}"
五、实战经验分享
去年我们遇到过一个典型案例:某金融系统Kafka集群每天产生2TB数据,但业务要求必须保留30天。直接扩容成本太高,我们最终采用的方案是:
- 热数据(7天内):保留在性能型SSD上
- 温数据(8-15天):迁移到标准云盘
- 冷数据(16-30天):压缩后转存到对象存储
实现这个方案的关键配置:
# 分层存储配置
log.dirs=/ssd_data,/hdd_data
log.retention.hours=360
log.retention.check.interval.ms=300000
log.segment.bytes=536870912 # 512MB分段更利于冷数据迁移
六、避坑指南
- 不要直接删除磁盘文件:这会导致消息位移错乱,应该通过Kafka内置机制清理
- 注意副本同步:扩容时要确保新磁盘的副本同步不会拖慢整个集群
- 监控清理线程:我们曾遇到cleaner线程卡死导致磁盘爆满的情况
- 考虑Zookeeper影响:大规模分区重新分配会给ZK带来压力
七、总结与展望
处理Kafka磁盘问题就像管理一个不断膨胀的仓库:既要及时扩建货架,又要定期清理滞销品。随着Kafka 3.0+版本的推出,分层存储功能越来越成熟,未来我们可以更灵活地在性能和成本之间取得平衡。
最后提醒大家,每个业务场景都是独特的,文中的方案需要根据实际情况调整。比如物联网设备日志和金融交易消息的保留策略就截然不同。记住:没有最好的方案,只有最适合的方案。
评论