额外的字节被添加到BooPickle和RocksDb的序列化中



因此,在将Scala类写入RocksDB之前,我使用BooPickle序列化它们。要序列化类,

case class Key(a: Long, b: Int) {
def toStringEncoding: String = s"${a}-${b}"
}

我有这个隐含类

implicit class KeySerializer(key: Key) {
def serialize: Array[Byte] = 
Pickle.intoBytes(key.toStringEncoding).array
}

方法toStringEncoding是必要的,因为BooPickle序列化case类的方式不能很好地满足RocksDb对密钥排序的要求。然后,我在几个SST文件中写了一堆键值对,并将它们吸收到RocksDb中。然而,当我从数据库中查找密钥时,却找不到它们。

如果我迭代数据库中的所有键,我会发现键被成功写入,但额外的字节会写入数据库中的字节表示。例如,如果key.serialize输出类似的内容

Array[Byte] = Array( 25, 49, 54, 48, 53, 55, 52, 52, 48, 48, 48, 45, 48, 45, 49, 54, 48, 53, 55, 52, 52, 48, 51, 48, 45, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...)

我会在数据库中找到类似于这个的东西

Array[Byte] = Array( 25, 49, 54, 48, 53, 55, 52, 52, 48, 48, 48, 45, 48, 45, 49, 54, 48, 53, 55, 52, 52, 48, 51, 48, 45, 48, 51, 101, 52, 97, 49, 100, 102, 48, 50, 53, 5, 8, ...)

额外的非零字节将替换字节数组末尾的零字节。此外,字节数组的大小也不同。当我调用serialize方法时,字节数组的大小是512,但当我从数据库检索密钥时,大小是4112。有人知道是什么原因造成的吗?

我没有RocksDb或BooPickle的经验,但我想问题出在调用ByteBuffer.array上。它返回支持字节缓冲区的整个数组,而不是相关部分。

您可以查看例如here从java中的ByteBuffer获取字节数组如何正确地从ByteBuffer中提取数据。

BooPickle文档建议将BooPickled数据作为字节数组:

val data: Array[Byte] = Array.ofDim[Byte](buf.remaining)
buf.get(data)

所以在你的情况下,它会像一样

def serialize: Array[Byte] = {
val buf = Pickle.intoBytes(key.toStringEncoding)
val arr = Array.ofDim[Byte](buf.remaining)
buf.get(arr)
arr
}

最新更新