4

我在数据库单元格中将一系列 protobuf-net 对象保存为以长度为前缀的 protobuf-net 对象的 Byte[]:

//retrieve existing protobufs from database and convert to Byte[]
object q = sql_agent_cmd.ExecuteScalar();
older-pbfs = (Byte[])q;

// serialize the new pbf to add into MemoryStream m
//now write p and the new pbf-net Byte[] into a memory stream and retrieve the sum

var s = new System.IO.MemoryStream();
s.Write(older-pbfs, 0, older-pbfs.Length);
s.Write(m.GetBuffer(), 0, m.ToArray().Length); // append new bytes at the end of old
Byte[] sum-pbfs = s.ToArray();

//sum-pbfs = old pbfs + new pbf. Insert sum-pbfs into database

这工作正常。我担心的是如果有轻微的数据库损坏会发生什么。将不再可能知道哪个字节是长度前缀,并且必须丢弃整个单元格内容。是否建议也使用某种类型的 pbf 对象结束指示符(有点像文本文件中使用的 \n 或 EOF 指示符)。这样,即使一条记录损坏,其他记录也可以恢复。

如果是这样,在每个 pbf 末尾添加记录结束指示符的推荐方法是什么。

在 Visual Studio 2010 上使用 protobuf-netv2 和 C#。

谢谢马尼什

4

2 回答 2

3

如果您通过Serialize/使用普通消息Deserialize,那么不:这不是规范的一部分(因为格式被设计为可附加的)。

但是,如果您使用SerializeWithLengthPrefix,它将在消息开头转储长度;然后它将提前知道需要多少数据。你用 反序列DeserializeWithLengthPrefix化,如果它没有足够的数据它会大声抱怨。然而!如果您有额外的数据,它不会抱怨,因为这也是可附加的。

根据 Jon 的回复,该*WithLengthPrefix方法的默认用法是存储的数据与 Jon 建议的完全相同;它假装有一个包装对象并做出相应的行为。区别在于:

  • 实际上不存在包装对象
  • "withlengthprefix" 方法在单次出现后显式停止,而不是将任何以后的数据合并到同一个对象中(例如,用于将多个离散对象发送到单个文件或单个套接字)

这里两个“可附加”的区别在于,第一个表示“合并为一个对象”,而第二个表示“我期望多个记录”。

无关建议:

s.Write(m.GetBuffer(), 0, m.ToArray().Length);

应该:

s.Write(m.GetBuffer(), 0, (int)m.Length);

(无需创建额外的缓冲区)

于 2012-05-15T19:27:55.833 回答
2

(注:我对 protobuf-net 本身了解不多,但这一般适用于 Protocol Buffer 消息。)

通常,如果您想记录多条消息,只需放置一个“包装”消息 - 使“真实”消息成为其中的重复字段。然后,每个“真实”消息的长度都会以 Protocol Buffers 的自然线路格式为前缀。

这当然不会检测到损坏 - 但老实说,如果数据库最终损坏,您就会遇到更大的问题。您可能会检测到损坏,例如通过将哈希与每条记录一起保存...但是您需要考虑损坏发生在长度前缀内或哈希本身内的可能性。想一想您在这里真正想要实现的目标——您想要防范的场景,以及您需要的恢复水平。

于 2012-05-15T19:04:33.043 回答