From 0c88a409d27fc634cbf444bccd8e6c3120083a8c Mon Sep 17 00:00:00 2001 From: ArcueidType <10225101440@stu.ecnu.edu.cn> Date: Mon, 25 Nov 2024 04:36:56 +0800 Subject: [PATCH] Complete Part 2, 3, 4 of Plan --- PLAN.md | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ assets/kv-sep.png | Bin 0 -> 16644 bytes assets/vLog.png | Bin 0 -> 9668 bytes 3 files changed, 163 insertions(+) create mode 100644 PLAN.md create mode 100644 assets/kv-sep.png create mode 100644 assets/vLog.png diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..52bdb0c --- /dev/null +++ b/PLAN.md @@ -0,0 +1,163 @@ +## 1. 项目概述 + +## 2. 功能设计 + +#### 2.1. 字段设计 + +- 设计目标 + + - 将 LevelDB 中的 `value` 组织成字段数组,每个数组元素对应一个字段(字段名:字段值)。 + + - 不改变LevelDB原有的存储方式,通过对字段数组的序列化和对字符串解析得到字段数组来实现字段功能 + + - 在作为key-value对存储进LevelDB之前可以任意调整字段 + + - 可以通过字段查询对应的key + +- 实现思路 + + - 将字段数组设计为一个class `Fields` ,其拥有对于字段进行操作的各种方法,方便对字段的修改,该类也作为 `Get` 方法和 `Put` 方法返回和插入的对象 + - 根据key查询时如果指定字段名则返回对应的字段,如果未指定字段名则返回所有字段 + - Put仅有value时(原本的Put方法)自动给value增加递增的字段 + - (暂定)对于给定的字段,遍历LevelDB得到其对应的所有keys + +#### 2.2. KV分离 + +- 设计目标 + - 拓展key-value存储结构,分离key和value的存储,从而对写放大进行优化 + - 不影响LevelDB原本接口的正常功能 + - 分离存储Value的Value-Log需要有对应的GC(Garbage Collection)功能,在达到一定条件(如Value -Log超过大小阈值)时触发,回收Value-Log中已经失效的Value + - 确保操作的原子性 +- 设计思路 + - 存入LSM-tree中的kv对为 `` ,value-addr保存了 `` ,对应value在vLog开始位置的便宜和value的大小 + - vLog的写入可以仿照LevelDB的Memtable机制,以防止频繁的写磁盘 + - vLog采用Append-Only,新数据仅在head添加,在回收时从tail处取得一块chunk,将其中有效的数据Append到head处,同时保证tail被永久保存到LSM-tree中,最后将整块chunk释放 + - 为了优化GC的效率,vLog同时存储key和value,而不是仅存入value + - **`(可能的优化)`** 因为vLog同时存入了key和value,因此LSM-tree不再需要log file,因为在恢复时可以通过vLog进行恢复,但对整个vLog扫描是不可取的,因此可以定期在LSM-tree中更新head(vLog的末尾),在恢复时从该head恢复到当前vLog的最末端 + +## 3. 数据结构设计 + +#### 3.1. 字段功能 + +- Field, FieldArray + + - ```c++ + using Field = std::pair; + using FieldArray = std::vector>; + ``` + +- Fields + + - 封装有 `std::map` 的class,其接口在 **[4](#4. 接口/函数设计)**中详细描述,用map实现在字段较多时可以获得较高的查询效率 + +#### 3.2. KV分离 + +- Key-Value分离结构图示: + +![kv-sep](D:\program\leveldb\assets\kv-sep.png) + +- Value Log中实际存储的内容 : + +![vLog](D:\program\leveldb\assets\vLog.png) + +## 4. 接口/函数设计 + +#### 4.1. 字段功能 + +- Fields + + - ```c++ + class Fields { + private: + std::map _fields; + public: + // 从FieldArray构建Fields + Fields(FieldArray field_array); + // 从LevelDB存储的Value中解码出Fields + Fields(std::string fields_str); + ~Fields(); + + // 重载[]运算符简便对字段的修改和访问操作 + std::string& Fields::operator[](const std::string& field_name); + + // 获取当前Fields对应的FieldArray + FieldArray GetFieldArray(); + + // 将Fields编码为存入LevelDB的Value + std::string Serialize(); + } + ``` + +#### 4.2. KV分离 + +- ```c++ + // 将value写入vLog,并把将要写入LSM-tree的地址返回为value_addr + // 该函数在Put中被调用 + void WriteValue(const Slice& key, const Slice& value, Slice& value_addr, + bool sync); + ``` + +- ```c++ + // 通过value_addr从vLog中获得value并返回 + void GetValue(const Slice& value_addr, Slice& value); + ``` + +- ```c++ + // ValueLog在LevelDB启动时即作为LevelDB的一个成员初始化一个实例 + // 后续db都使用该实例进行ValueLog相关操作 + class ValueLog { + private: + WriteBuff _buff; + uint64_t _head; + uint64_t _tail; + + // 将缓存内容真正写入磁盘的vLog中 + bool WirteDisk(); + public: + ValueLog(); + ~ValueLog(); + + // 返回vLog中head处的offset + uint64_t Head(); + + // 返回vLog中tail处的offset + uint64_t Tail(); + + // 将key-value对插入Value Log,返回对应的value_addr + // 若用户要求同步写入,即sync为true,则立即将数据写入磁盘 + Slice Append(const Slice& key, const Slice& value, bool sync); + + // 通过value_addr获得value,首先在buff中寻找,然后才真正访问vLog + Slice Get(const Slice& value_addr); + + // 对ValueLog文件进行GC操作,释放空间 + void GarbageCollection(uint64_t chunk_size); + } + ``` + +- ```c++ + // WriteBuff的功能与Memtable极其相似,实现可以大量仿照Memtable,甚至直接使用Memtable + // 因此,此处仅列出WriteBuff需要提供的两个接口,其他成员不再列出 + class WriteBuff { + // 向buff中插入一条value_addr-vLogValue()对 + void Add(const Slice& value_addr, const Slice& key, const Slice& value); + + // 在buff中查询对应value_addr对应的value + // 找到返回true,否则返回false + bool Get(const Slice& value_addr); + + // 将缓存内容写入磁盘 + bool WirteDisk(); + } + ``` + +## 5. 功能测试 + +## 6. 可能遇到的挑战与解决方案 + +## 7. 分工和进度安排 + + + + + diff --git a/assets/kv-sep.png b/assets/kv-sep.png new file mode 100644 index 0000000000000000000000000000000000000000..a2fe9b55149916f2cffc13d942c4c70632d3898d GIT binary patch literal 16644 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 Y4DNd=w#8BjKt6(^>@%4!PtAh=KWX45lK=n! literal 0 HcmV?d00001 diff --git a/assets/vLog.png b/assets/vLog.png new file mode 100644 index 0000000000000000000000000000000000000000..bcb6a52a1b97d10143766f627b3c92247781e3ae GIT binary patch literal 9668 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 K>g8ALqW=$}p*Ru% literal 0 HcmV?d00001