通过toLocalIterator加载到LevelDB的Spark RDD会创建损坏的数据库

时间:2015-03-19 17:52:52

标签: java scala apache-spark leveldb

我有一个Spark计算,我希望将其保存到一个简单的leveldb数据库中 - 一旦所有繁重的工作都由Spark完成(在Scala中)。

所以我的代码是这样的:

private def saveRddToLevelDb(rdd: RDD[(String, Int)], target: File) = {
    import resource._

    val options = new Options()
    options.createIfMissing(true)
    options.compressionType(CompressionType.SNAPPY)

    for (db <- managed(factory.open(target, options))) { // scala-arm
        rdd.map { case (key, score) =>
            (bytes(key), bytes(score.toString))
        }.toLocalIterator.foreach { case (key, value) =>
            db.put(key, value)
        }
    }
}

一切都与世界是对的。但是如果我尝试打开创建的数据库并对其执行 get

org.fusesource.leveldbjni.internal.NativeDB$DBException: IO error: .../leveldb-data/000081.sst: Invalid argument
    org.fusesource.leveldbjni.internal.NativeDB.get(NativeDB.java:316)
    org.fusesource.leveldbjni.internal.NativeDB.get(NativeDB.java:300)
    org.fusesource.leveldbjni.internal.NativeDB.get(NativeDB.java:293)
    org.fusesource.leveldbjni.internal.JniDB.get(JniDB.java:85)
    org.fusesource.leveldbjni.internal.JniDB.get(JniDB.java:77)

我设法做到了,不仅仅是打开创建的leveldb数据库,而是事先修复它...(在这次java中):

factory.repair(new File(levelDbDirectory, "leveldb-data"), options);
DB db = factory.open(new File(levelDbDirectory, "leveldb-data"), options);

那么,一切都好吗?! 是的,但我唯一的问题是为什么? 当我所有数据放入leveldb时,我做错了什么:

  • 数据库的开放流由scala-arm管理,因此之后正确关闭
  • 我的JVM没有被杀死或什么
  • 只有一个进程,即使只有一个线程 - 驱动程序一个,访问数据库(通过 toLocalIterator 方法)
  • 最后,如果我使用偏执模式打开数据库,leveldb在我尝试获取之前并不关心。因此,数据库并没有完全被破坏。

我已经读过 put 写实际上是异步的事实,但我没有尝试将 WriteOptions 更改为已同步,但不会&#39 ; 关闭方法等待进程刷新所有内容?

0 个答案:

没有答案