You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark Executor在K8s中RocksDB状态存储占用空间过大咨询

RocksDB状态存储初始阶段异常占用磁盘空间问题

问题背景

我维护一个运行在Kubernetes集群上的Scala Spark应用,正在测试使用RocksDB作为状态存储的效果。

初始磁盘空间不足问题

应用运行时出现临时存储不足错误:
临时存储不足

查看Spark Executor日志,发现RocksDB因磁盘空间不足无法创建文件:

{"log_timestamp": "2023-11-15T23:20:27.964+0000", "log_level":
"ERROR", "process_id": 1, "process_name": "kqi", "thread_id": 1,
"thread_name": "Executor task launch worker for task 33.0 in stage 6.1
(TID 464)", "action_name": "org.apache.spark.executor.Executor",
"log_message": "Exception in task 33.0 in stage 6.1 (TID 464)
org.rocksdb.RocksDBException: While open a file for appending:
/var/data/spark-1c317e23-92e3-41b6-9543-7a98db12faf3/spark-dc0e0bee-e012-4227-83cf-75024f80f8fa/StateStoreId(opId=0,partId=90,name=left-keyToNumValues)-ed47b686-9148-4d08-9ba0-5af507cc5c26/workingDir-f5f1bc0f-afa9-46c9-a139-efd65077e1b4/000004.dbtmp:
No space left on device\n at org.rocksdb.RocksDB.open(Native
Method)\n at org.rocksdb.RocksDB.open(RocksDB.java:251)\n at
org.apache.spark.sql.execution.streaming.state.RocksDB.openDB(RocksDB.scala:426)\n
at
org.apache.spark.sql.execution.streaming.state.RocksDB.load(RocksDB.scala:114)\n
at
org.apache.spark.sql.execution.streaming.state.RocksDBStateStoreProvider.getStore(RocksDBStateStoreProvider.scala:192)\n
at
org.apache.spark.sql.execution.streaming.state.StateStore$.get(StateStore.scala:496)\n
at
org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$StateStoreHandler.getStateStore(SymmetricHashJoinStateManager.scala:414)\n
at
org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$KeyToNumValuesStore.(SymmetricHashJoinStateManager.scala:438)\n
at
org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager.(SymmetricHashJoinStateManager.scala:382)\n
at
org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec$OneSideHashJoiner.(StreamingSymmetricHashJoinExec.scala:508)\n
at
org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec.processPartitions(StreamingSymmetricHashJoinExec.scala:257)\n
at
org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec.$anonfun$doExecute$1(StreamingSymmetricHashJoinExec.scala:228)\n
at
org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec.$anonfun$doExecute$1$adapted(StreamingSymmetricHashJoinExec.scala:228)\n
at
org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinHelper$StateStoreAwareZipPartitionsRDD.compute(StreamingSymmetricHashJoinHelper.scala:235)\n
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373)\n

at org.apache.spark.rdd.RDD.iterator(RDD.scala:337)\n at
org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:52)\n
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373)\n

at org.apache.spark.rdd.RDD.iterator(RDD.scala:337)\n at
org.apache.spark.sql.execution.SQLExecutionRDD.compute(SQLExecutionRDD.scala:55)\n
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373)\n

at org.apache.spark.rdd.RDD.iterator(RDD.scala:337)\n at
org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:52)\n
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373)\n

at org.apache.spark.rdd.RDD.iterator(RDD.scala:337)\n at
org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:52)\n
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373)\n

at org.apache.spark.rdd.RDD.iterator(RDD.scala:337)\n at
org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:52)\n
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373)\n

at org.apache.spark.rdd.RDD.iterator(RDD.scala:337)\n at
org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:52)\n
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373)\n

at org.apache.spark.rdd.RDD.iterator(RDD.scala:337)\n at
org.apache.spark.shuffle.ShuffleWriteProcessor.write(ShuffleWriteProcessor.scala:59)\n
at
org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:99)\n
at
org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:52)\n
at org.apache.spark.scheduler.Task.run(Task.scala:131)\n at
org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$3(Executor.scala:506)\n
at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:1491)\n
at
org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:509)\n
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)\n
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)\n
at java.base/java.lang.Thread.run(Thread.java:829)\n"}

PVC配置调整

随后为每个Spark Executor的本地目录分配了250Gi的PVC(当前运行3个Executor):

- --conf
- spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.claimName=OnDemand
- --conf
- spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.storageClass=vsphere-thin
- --conf
- spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.sizeLimit=250Gi
- --conf
- spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.path=/data/spark/
- --conf
- spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.readOnly=false

异常空间占用现象

调整后观察到,Spark启动阶段RocksDB状态存储就快速占用空间,每个Executor的占用量可达约200Gi,且此时应用尚未处理任何数据:

bash-4.4$ du -h --max-depth=1
32G     ./spark-bc3a977f-d380-4adc-bfb2-229e8d02d650
16K     ./lost+found
5.4M    ./blockmgr-f5de30e5-683c-443a-a0b4-6360ee516cb3
32G     .
bash-4.4$ du -h --max-depth=1
35G     ./spark-bc3a977f-d380-4adc-bfb2-229e8d02d650
16K     ./lost+found
5.8M    ./blockmgr-f5de30e5-683c-443a-a0b4-6360ee516cb3
35G     .
bash-4.4$ du -h --max-depth=1
39G     ./spark-bc3a977f-d380-4adc-bfb2-229e8d02d650
16K     ./lost+found
6.3M    ./blockmgr-f5de30e5-683c-443a-a0b4-6360ee516cb3
39G     .
bash-4.4$ du -h --max-depth=1
41G     ./spark-bc3a977f-d380-4adc-bfb2-229e8d02d650
16K     ./lost+found
6.7M    ./blockmgr-f5de30e5-683c-443a-a0b4-6360ee516cb3
41G     .
bash-4.4$ du -h --max-depth=1
43G     ./spark-bc3a977f-d380-4adc-bfb2-229e8d02d650
16K     ./lost+found
7.1M    ./blockmgr-f5de30e5-683c-443a-a0b4-6360ee516cb3
43G     .

Spark相关配置

以下是当前Spark的配置:

spark:
  submit:
    extraConf:
      "spark.sql.streaming.stateStore.providerClass": "org.apache.spark.sql.execution.streaming.state.RocksDBStateStoreProvider"
      "spark.sql.streaming.stateStore.rocksdb.compactOnCommit": true
      "spark.sql.streaming.stateStore.rocksdb.blockSizeKB": 4
      "spark.sql.streaming.stateStore.rocksdb.blockCacheSizeMB": 8
      "spark.sql.streaming.stateStore.rocksdb.lockAcquireTimeoutMs": 60000
      "spark.sql.streaming.stateStore.rocksdb.resetStatsOnLoad": true
  driver:
    memory: 8g
    memoryOverhead: 2g
    request:
      cores: 5800m
    limit:
      cores: 6
    extraJavaOptions: -XX:+UseG1GC
  executor:
    instances: 3
    cores: 10
    memory: 9g
    memoryOverhead: 3g
    request:
      cores: 5800m
    limit:
      cores: 6
    extraJavaOptions: -XX:MaxMetaspaceSize=2100m -XX:+UseG1GC
properties:
  sqlShufflePartitions: "200"
  sparkUiEnabled: "true"
  spark:
    streaming:
      maxOffsetsPerTrigger: "1000000"

疑问

请问RocksDB状态存储在未处理任何数据的情况下占用如此大空间是否正常?哪些参数会影响其初始大小?怀疑是RocksDB进行了空间预分配,如何验证及调整?


内容的提问来源于stack exchange,提问作者Manfred Von Karma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:08:15