From 7d96557d457ce23d892e816a408ce83497333ef9 Mon Sep 17 00:00:00 2001 From: VirgilZhu <94546750@qq.com> Date: Tue, 7 Jan 2025 09:44:17 +0800 Subject: [PATCH] update README --- README.md | 49 ++++++++++++----------------------------------- benchmarks/db_bench.cc | 2 +- include/leveldb/options.h | 4 ++-- 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 5cf21ab..97c0140 100755 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@
小组成员:谷杰 10222140408 朱维清 10215300402 -
+[TOC] ## 项目概述 @@ -111,7 +111,7 @@ ## KV 分离 -> ​ KV 分离部分,由于我们小组最后定版设计为,使 VLog 代替原 LevelDB 中 WAL 的作用,同时具有从 LSM-Tree 中分离并保存超过某个 value 大小阈值(`separate_threshold`)的 kv 对数据的作用,关于 VLog 的读写类 `VlogReader/VlogWriter` 的实现参考了 `LogReader/LogWriter` 的部分内容,并能共享 `LogReader/LogWriter` 使用的所有读写接口(参见`env_posix.cc`,读写均为磁盘I/O)(去除了 CRC 校验功能)。 +> ​ KV 分离部分,由于我们小组最后定版设计为,使 VLog 代替原 LevelDB 中 WAL 的作用,同时具有从 LSM-Tree 中分离并保存超过某个 value 大小阈值(`separate_threshold`)的 kv 对数据的作用,关于 VLog 的读写类 `VlogReader/VlogWriter` 的实现参考了 `LogReader/LogWriter` 的部分内容,并能共享 `LogReader/LogWriter` 使用的所有读写接口(参见`env_posix.cc`,读写均为磁盘I/O)。 > > + **结构图/写入流程图**: > ![kv_sep](./image/kv_sep.png) @@ -407,7 +407,7 @@ Status VlogWriter::EmitPhysicalRecord(const char* ptr, size_t length, } ``` -vlog_writer.cc文件中则是对于构造函数,AddRecord()以及EmitPhysicalRecord()。实现上与LogWriter基本一致,只是去除了Crc校验码的部分。对于EmitPhysicalRecord()函数,由于去除了校验码,则其header要从原本的8字节改为4字节,只保留length部分(4字节)。 +vlog_writer.cc文件中则是对于构造函数,AddRecord()以及EmitPhysicalRecord()。实现上与LogWriter基本一致。对于EmitPhysicalRecord()函数,由于去除了校验码,则其header要从原本的8字节改为4字节,只保留length部分(4字节)。 改完vlog_writer部分后,让我们重新来梳理一遍写入过程。 @@ -644,7 +644,7 @@ class SeparateManagement { #### 介绍部分函数 + `ConvertQueue`: - 每次把 VLog 加入 GC 队列前需要更新数据库的 last_sequence,并确保所有 `need_updates_` 队列里的 VLog 都更新了 `last_sequence_`,以便对 VLog 中的有效 keys 重新插入新的 VLog 中: + 每次把 VLog 加入 GC 队列前需要更新数据库的 last_sequence,并确保所有 `need_updates_` 队列里的 VLog 都更新了 `last_sequence_`,以便对 VLog 中的有效 keys 重新插入数据库: ```C++ bool SeparateManagement::ConvertQueue(uint64_t& db_sequence) { @@ -736,15 +736,14 @@ void SeparateManagement::CollectionMap(){ ### GC 的具体实现 -> 1. 我们采用了类似 Compaction 的后台多线程调度机制来实现 GC; +> 1. 我们采用了类似 Compaction 的后台线程调度机制来实现 GC; > 2. 支持在线自动 GC,也支持离线手动触发 GC; -> 3. GC 与 Snapshot 互相冲突:若数据库运行期间有 Snapshot 产生,则该 Snapshot 之后的所有数据不再进行任何在线 GC,直到该 Snapshot 被释放才会重启在线 GC; -> -> **VLog 的 GC 的回收阈值: `Options::garbage_collection_threshold = max_value_log_size / 4 ( = 4MB)`** +> +>**VLog 的 GC 的回收阈值: `Options::garbage_collection_threshold = max_value_log_size / 4 ( = 4MB)`** + 所有 GC 流程都由 `SeparateManagement *DBImpl::garbage_collection_management_` 进行管理,并向所有 VLogs 的 `ValueLogInfo` 更新 GC 的结果。 -#### 后台多线程调度机制 +#### 后台线程调度机制 参考 Compaction 线程互斥锁的实现与后台调度机制: @@ -880,7 +879,7 @@ Status DBImpl::OutLineGarbageCollection(){ } else if (!bg_error_.ok()) { // Already got an error; no more changes } else { - // 设置调度变量,通过 detach 线程调度; detach 线程即使主线程退出,依然可以正常执行完成 + // 设置调度变量 background_GarbageCollection_scheduled_ = true; env_->ScheduleForGarbageCollection(&DBImpl::GarbageCollectionBGWork, this); } @@ -1002,31 +1001,9 @@ Status DBImpl::OutLineGarbageCollection(){ --- -#### GC 与 Snapshot 的冲突机制 - -```c++ -const Snapshot* DBImpl::GetSnapshot() { - MutexLock l(&mutex_); - // 建立快照,对快照之后的信息不用进行 GC - finish_back_garbage_collection_ = true; - return snapshots_.New(versions_->LastSequence()); -} - -void DBImpl::ReleaseSnapshot(const Snapshot* snapshot) { - MutexLock l(&mutex_); - snapshots_.Delete(static_cast(snapshot)); - // 没有快照,重新进行后台 GC - if (snapshots_.empty()) { - finish_back_garbage_collection_ = false; - } -} -``` - ---- - ## 断电恢复 -> 实现断电恢复的主要函数为 `DBImpl::Recover()`、`DBImpl::RecoverLogFile`、`DB::Open()`; +> 实现断电恢复的主要函数为 `DBImpl::Recover()`、`DBImpl::RecoverLogFile()`、`DB::Open()`; ### 大致恢复流程 @@ -1487,7 +1464,7 @@ fillsync : 985.150 micros/op; 0.0 MB/s (100 ops) fillrandom : 4.337 micros/op; 4.0 MB/s overwrite : 4.503 micros/op; 3.8 MB/s fillgivenseq : 4.472 micros/op; 3.6 MB/s -fillgivenrandom : 9.076 micros/op; 1.8 MB/s +fillgivenrandom : 9.076 micros/op; 1.8 MB/s ``` + kv分离: @@ -1498,7 +1475,7 @@ fillsync : 1005.810 micros/op; 0.0 MB/s (100 ops) fillrandom : 4.374 micros/op; 3.9 MB/s overwrite : 4.461 micros/op; 3.8 MB/s fillgivenseq : 4.503 micros/op; 3.6 MB/s -fillgivenrandom : 4.789 micros/op; 3.4 MB/s +fillgivenrandom : 4.789 micros/op; 3.4 MB/s ``` #### 分析结论 @@ -1516,7 +1493,6 @@ readrandom : 2.460 micros/op; (86501 of 100000 found) readrandom : 2.096 micros/op; (86354 of 100000 found) readseq : 0.258 micros/op; 188.5 MB/s readreverse : 1.250 micros/op; 38.9 MB/s -findkeysbyfield : 1474764.000 micros/op; (3873 of 10000 found) ``` + kv分离: @@ -1526,7 +1502,6 @@ readrandom : 13.775 micros/op; (86501 of 100000 found) readrandom : 9.095 micros/op; (86354 of 100000 found) readseq : 0.231 micros/op; 90.2 MB/s readreverse : 0.950 micros/op; 22.0 MB/s -findkeysbyfield : 231171.000 micros/op; (0 of 10000 found) ``` #### 分析结论 diff --git a/benchmarks/db_bench.cc b/benchmarks/db_bench.cc index eb1c40b..3543300 100644 --- a/benchmarks/db_bench.cc +++ b/benchmarks/db_bench.cc @@ -85,7 +85,7 @@ static int FLAGS_num_fields = 10000; static int FLAGS_threads = 1; // Size of each value -static int FLAGS_value_size = 100; +static int FLAGS_value_size = 1000; // Arrange to generate values that shrink to this fraction of // their original size after compression diff --git a/include/leveldb/options.h b/include/leveldb/options.h index 7832b2b..a397e07 100644 --- a/include/leveldb/options.h +++ b/include/leveldb/options.h @@ -114,7 +114,7 @@ struct LEVELDB_EXPORT Options { // compactions and hence longer latency/performance hiccups. // Another reason to increase this parameter might be when you are // initially populating a large database. - size_t max_file_size = 2 * 1024 * 1024; + size_t max_file_size = 64 * 1024 * 1024; // Compress blocks using the specified compression algorithm. This // parameter can be changed dynamically. @@ -149,7 +149,7 @@ struct LEVELDB_EXPORT Options { /* 注释:重要的 VLog 与 GC 设置 */ // value log 的文件大小 - uint64_t max_value_log_size = 16 * 1024 * 1024; + uint64_t max_value_log_size = 64 * 1024 * 1024; // VLog 的 gc 的回收阈值。 uint64_t garbage_collection_threshold = max_value_log_size / 4; // gc 后台回收时重新 put 的时候,默认的 kv 分离的值。