在磁盘上存储 thrift 序列化对象
Storing thrift-serialized objects on disk
要求
- 我需要将 Thrift 序列化对象流存储在一个文件中,以便我可以稍后读取该文件并获取反序列化对象。
- 对象可以是不同的类型。
问题
(i) 分隔文件中每个对象的最佳方式是什么。例如,在文本文件中,我可以用换行符分隔每个对象。这种方法对二进制文件也有效吗?
(ii) 为了标记每个对象的类型(在反序列化过程中使用),我打算在每个字节序列的开头添加一个类型字段。有没有更好的方法?
最重要的问题是您打算如何访问文件:顺序访问还是随机访问?
顺序访问(某种程度上)或少量数据
What's the best way to delimit each object in the file. For example, in a text file, I could separate each object with a newline character. Is that approach valid for binary files as well?
显然不是 ;-)。不过别担心,还有更好的解决办法。要存储数据列表,可以简单地直接存储一个 list<data>
。换句话说,像这样:
struct foo { 1: string field, 2: i32 otherfield }
list<foo>
如果数据不仅是foo
,而且是不同类型的,则在两者之间放置一个并集:
struct foo { 1: string field, 2: i32 otherfield }
struct bar { 1: map<string,wtf> seinfield, 2: double cloverfield }
struct wtf { 1: list<double> even_more_fields }
union MyDataRecord {
1: foo foo
2: bar bar
3: wtf wtf
}
list<MyDataRecord>
因为我们仍然一次读取和写入所有内容,所以不需要人工限制器。
To mark the type of each object (to be used during deserialization), I'm planning to add a type field at the beginning of each byte sequence. Is there a better approach?
如果您像上面概述的那样将数据放入 list<>
中,Thrift 会处理它。您只需将整个列表作为一个整体来读写。
随机访问and/or大量数据
如果你想随机访问你的数据,事情将会发生巨大的变化。这个问题是,为了让它高效和快速 - 你需要以某种方式确定给定元素在文件中的位置 而不是总是先扫描整个文件1)。在大多数情况下,写入的条目的字节大小会有所不同。即使它们都只是一种类型foo
,仍然不能假设某个元素位于
position = sizeof(foo) * index_of_desired_element
因为 foo
有一个可变大小的数据成员:string
字段。
要解决这个问题,我们基本上有两个选择。
(1) Fixed-size records:我们可以确保所有元素不超过预定义的最大大小,并将其用作文件记录大小。我们也不再使用 list<>
,而是将数据写入文件中的正确位置。 n-th 元素的位置又是
position = N * predefined_record_size
缺点显然是我们可能会浪费很多 space,加上数据量有限。
(2) 索引文件:第二个选项是维护一个单独的索引文件,它保存每个条目在数据文件中的位置。这又可以是一个简单的整数列表:
list<i32>
这里的缺点是,您需要确保索引的形状正确,尤其是在文件中间进行插入、删除和更新操作时。
以上两个选项的更普遍的问题是,尤其是插入和删除操作可能会变得很痛苦,因为您可能不得不移动大量数据。为了解决这个问题,您会发现自己在解决方案中添加了更多的技巧,例如删除标记等。
底线
如果您只有一堆数据,list<union>
方法可能就是您要寻找的方法。因为 union
是可以随时扩展的,所以解决方案也为以后添加其他元素做好了准备。
如果您绝对只想按顺序访问数据,请选择 list<union>
方法,或者 read/write union
个元素一个接一个。 Thrift 支持 Skip()
功能,可以在需要时跳过不需要的数据。
但是,如果您想随机访问数据and/or有很多数据要处理,真实的数据库可能更合适。
1) 扫描一个可能很大的文件以查找记录分隔符不是 the kind of O(?) you want.
要求
- 我需要将 Thrift 序列化对象流存储在一个文件中,以便我可以稍后读取该文件并获取反序列化对象。
- 对象可以是不同的类型。
问题
(i) 分隔文件中每个对象的最佳方式是什么。例如,在文本文件中,我可以用换行符分隔每个对象。这种方法对二进制文件也有效吗?
(ii) 为了标记每个对象的类型(在反序列化过程中使用),我打算在每个字节序列的开头添加一个类型字段。有没有更好的方法?
最重要的问题是您打算如何访问文件:顺序访问还是随机访问?
顺序访问(某种程度上)或少量数据
What's the best way to delimit each object in the file. For example, in a text file, I could separate each object with a newline character. Is that approach valid for binary files as well?
显然不是 ;-)。不过别担心,还有更好的解决办法。要存储数据列表,可以简单地直接存储一个 list<data>
。换句话说,像这样:
struct foo { 1: string field, 2: i32 otherfield }
list<foo>
如果数据不仅是foo
,而且是不同类型的,则在两者之间放置一个并集:
struct foo { 1: string field, 2: i32 otherfield }
struct bar { 1: map<string,wtf> seinfield, 2: double cloverfield }
struct wtf { 1: list<double> even_more_fields }
union MyDataRecord {
1: foo foo
2: bar bar
3: wtf wtf
}
list<MyDataRecord>
因为我们仍然一次读取和写入所有内容,所以不需要人工限制器。
To mark the type of each object (to be used during deserialization), I'm planning to add a type field at the beginning of each byte sequence. Is there a better approach?
如果您像上面概述的那样将数据放入 list<>
中,Thrift 会处理它。您只需将整个列表作为一个整体来读写。
随机访问and/or大量数据
如果你想随机访问你的数据,事情将会发生巨大的变化。这个问题是,为了让它高效和快速 - 你需要以某种方式确定给定元素在文件中的位置 而不是总是先扫描整个文件1)。在大多数情况下,写入的条目的字节大小会有所不同。即使它们都只是一种类型foo
,仍然不能假设某个元素位于
position = sizeof(foo) * index_of_desired_element
因为 foo
有一个可变大小的数据成员:string
字段。
要解决这个问题,我们基本上有两个选择。
(1) Fixed-size records:我们可以确保所有元素不超过预定义的最大大小,并将其用作文件记录大小。我们也不再使用 list<>
,而是将数据写入文件中的正确位置。 n-th 元素的位置又是
position = N * predefined_record_size
缺点显然是我们可能会浪费很多 space,加上数据量有限。
(2) 索引文件:第二个选项是维护一个单独的索引文件,它保存每个条目在数据文件中的位置。这又可以是一个简单的整数列表:
list<i32>
这里的缺点是,您需要确保索引的形状正确,尤其是在文件中间进行插入、删除和更新操作时。
以上两个选项的更普遍的问题是,尤其是插入和删除操作可能会变得很痛苦,因为您可能不得不移动大量数据。为了解决这个问题,您会发现自己在解决方案中添加了更多的技巧,例如删除标记等。
底线
如果您只有一堆数据,list<union>
方法可能就是您要寻找的方法。因为 union
是可以随时扩展的,所以解决方案也为以后添加其他元素做好了准备。
如果您绝对只想按顺序访问数据,请选择 list<union>
方法,或者 read/write union
个元素一个接一个。 Thrift 支持 Skip()
功能,可以在需要时跳过不需要的数据。
但是,如果您想随机访问数据and/or有很多数据要处理,真实的数据库可能更合适。
1) 扫描一个可能很大的文件以查找记录分隔符不是 the kind of O(?) you want.