【发布时间】:2011-07-22 13:37:12
【问题描述】:
我正在尝试使用 C++ 为键值对开发主内存索引。我需要确保索引在崩溃后是可恢复的。我正在使用我发现的 CSB+-Tree 实现(BSD 许可证)here 我面临的主要挑战是在重新实例化节点后维护父子关系数据。 我已经搜索了各种策略来将“树结构”保存到磁盘或从磁盘恢复。其中一些是:
- 以 Pre-order 保存节点对象并为空子指针写入 NULLS。
- 为节点提供 IDS 并在写入时保存节点的 ID 而不是指针 到磁盘,然后在使用 ID 重新实例化期间解析指针。
- 保存时使用文件偏移值(物理内存中的地址)而不是子节点的主内存地址。这可能意味着我必须从叶子向上保存。
我还查看了几个序列化库。 Google ProtocolBuffers 和 Boost 序列化。
现在实现中的“节点”有许多指针变量。其中一些是指向其他节点的指针,而另一些是指向“键值”的指针。下面的代码是简化版,保留了本质。
struct NodeHead
{
NodeHead *null; // null indicates internal node
char *children; // ptr to children
NodeEntry entries[1]; // entry array
}
struct NodeEntry
{
uint16_t offset; // offset to NodeHead of the key in byte
uint8_t next; // index of the next entry; 0xff means null
uint8_t num; // [0]: number of entries in use
};
我正在考虑将条目值直接写入节点头的数据中,而不是保存链接。并为每个 NodeHead 实例提供一个 ID 并使用它来维护“子”关系。如果能以更好的方式做到这一点,我想要一些建议。
【问题讨论】:
-
如果崩溃时您说的是流产或任何硬中断,您将无法序列化任何内容...那么您的策略是什么让数据持久之前 i> 你崩溃了?在每次修改时对所有内容进行序列化不太可能。
-
我不会在每次修改时进行序列化。我将有定期检查站。在检查点期间,我更愿意将索引的“快照”(连同叶子中的数据)保存到磁盘上。这样启动后我可以恢复索引结构。在 2 个检查点之间,我将保留所有事务的日志,以便在恢复到最新提交的操作后更新索引快照。关于将快照保存到磁盘,我发现了一个类似的问题问stackoverflow.com/questions/872070/…。我被困在如何继续
-
您也可以执行选项 3,让索引本身引用(没有指针仅引用页面偏移量 - 在页面中分配索引),然后当您对索引进行快照时,您可以检查索引 @ 987654324@ 并检查该索引页是否已更新,然后将整个脏索引页复制到磁盘。无需遍历树,只需索引页的索引。 [我提出了类似于 CUDA 内存复制问题的建议——我一定是个小马驹 :) ]
标签: c++ database data-structures indexing