InfluxDb高内存占用优化(Flink监控)【干货】

4,524 阅读4分钟

在监控Flink的技术选型上,我选择了Prometheus+Influxdb作为存储,因为Prometheus不支持Checkpoint的指标存储,因此增加了influxdb。但由于乐观估计,有指标比没有指标好,没有对InfluxDbReporter进行定制,因此以下的测量数据是原生的,全指标收集的情况。

Influxdb长期运行的内存使用量

基本情况说明
flink原生InfluxdbReporter全指标收集
retention_policy设置为one_hourflink官方文档默认
influxdb版本1.8
作业规模内存用量Min (Influxdb启动时)内存用量Max(运行较长时间)
约1001GB40GB

优化过程

起初,内存用量比较小,只有几GB,调整索引方案index_version = tsi1。 REF: www.influxdata.com/blog/how-to…

后来,一段时间后观察,发现内存用量先是很有规律的在10GB左右起伏,再过一段时间,还是水涨船高,超过20GB。于是将内存设置翻倍到40GB

再后来通过influx客户端,发现默认数据库monitor的retention_policy时间比较长,duration是168h。 于是修改monitor的retention policy

alter retention policy monitor on _internal duration 1d replication 1 shard duration 30m
alter retention policy autogen on flink duration 1h replication 1

内存稳定了一段时间,之后内存占用90%的报警又发出来了。。。这下,着急了,干脆直接禁用monitor数据库

[monitor]
store-enabled = false

修改以上配置,关闭influxdb的monitor数据库后,重启。进入influx客户端,输入show shards,发现没有了monitor。但问题仍然依旧。这次没有办法了,着急。

柳暗花明又一村

登陆influx客户端,执行 show measurements;发现有特别多的指标,例如以下的Kafka消费组对应的指标

taskmanager_job_task_operator_KafkaConsumer_committed_offsets_video_bc-0
taskmanager_job_task_operator_KafkaConsumer_committed_offsets_video_bc-1
taskmanager_job_task_operator_KafkaConsumer_committed_offsets_video_bc-2
taskmanager_job_task_operator_KafkaConsumer_committed_offsets_video_bc-3
taskmanager_job_task_operator_KafkaConsumer_committed_offsets_video_bc-4
taskmanager_job_task_operator_KafkaConsumer_committed_offsets_video_bc-5

大概有了新的思路,那就是数据量太大了,但这个时候,不能让用户一个一个停止作业啊。 于是找文档:

docs.influxdata.com/influxdb/v1…

In general, having more RAM helps queries return faster. There is no known downside to adding more RAM.

The major component that affects your RAM needs is series cardinality. A series cardinality around or above 10 million can cause OOM failures even with large amounts of RAM. If this is the case, you can usually address the problem by redesigning your schema.

根据官方文档,

如果SERIES CARDINALITY超过1000万,无论内存多大,都会导致OOM. 唯一的办法就是限制schema的复杂程度。

执行SHOW SERIES CARDINALITY查看,发现已经有100万了。惊,这下问题原因清晰了,大道至简,就是无用数据太多了。回想当初,出发点就是收集个别指标,不应该全收集的。

大道至简,少即是多

这个时候,已经胸有成竹了,于是,停止了influxdb服务。登陆到influxdb的服务器,rm -rf /。 将数据全部删除,再重新启动influxdb。内存占用恢复到了1GB~6GB

虽然问题临时得以解决,前后经历了很长时间,但整个过程是很快乐的。

不要试图用更复杂的方式去解决复杂的问题

根据前面所说的需求,可以修改org.apache.flink.metrics.influxdb.AbstractReporter, 去掉除了LastCheckpointExternalPath以外的配置,重新编译,部署到生产环境。。。

@Override
public void notifyOfAddedMetric(Metric metric, String metricName, MetricGroup group) {
   if (!metricName.equals("lastCheckpointExternalPath")) {
      return;
   }
...   

后续观察

经过大约一周时间的观察,发现以下联合措施有效:

  1. 删除所有监控数据
  2. 环境变量INFLUXDB_MONITOR_STORE_ENABLED=false未生效,可能是没有加载到容器内,无需深究。
  3. 修改配置文件[monitor] store-enabled=false后重启,再无内存高占用。

所以,目前依旧是全指标上报,但禁用monitor数据库。 内存浮动在 2GB - 3GB左右。

如下图所示(手绘,因为内部系统不方便截图):

总结

通常解决问题的办法不只有一种,最终解决问题的有效方案也可能是多种。 通过修改monitor的store-enabled=false,并删除物理数据,可以临时解决高CPU占用高内存占用。 但要从根本上解决问题,需要修改InfluxdbMetricReporter.