From 7a9af6d41c3e7aa2117acb864af8498328d53b9f Mon Sep 17 00:00:00 2001 From: augurier <14434658+augurier@user.noreply.gitee.com> Date: Sun, 5 Jan 2025 22:26:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E4=BA=9B=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ test/helper.cc | 4 ++++ test/parallel_test.cc | 1 + 3 files changed, 8 insertions(+) diff --git a/README.md b/README.md index 74268a0..20dba8a 100644 --- a/README.md +++ b/README.md @@ -804,6 +804,9 @@ batchsize=1000下,线程数对性能的影响: 3) 对于创删索引:没有比较对象,但是总体可以接受 4) 对于创删索引和写并发:如果是无关的,那么还是保持了高吞吐;如果是相关的,那么不得不受限于创删索引。考虑到数据库的创删索引请求还是比较少的(不太可能出现我们测试中,不停并发创删索引和写入的情况),一定的性能牺牲可以接受 +#### 3.2.4 写放大问题的一些讨论 +相比原版leveldb,我们的写放大问题主要在于metadb需要多一次日志写入。但leveldb的写放大本身比较严重,问题在于文件合并时的处理。这一具体的数值,取决于数据量变化造成的文件数量变化(通常在30~50倍)。我们在测试中进行了一些插桩,比较数据本身和log中统计得到的磁盘写入,在不触发大合并、不插入重复数据、不删除数据的前提下,kv本身写放大大约在1.8倍(索引不计入其中)。即使加上kv和meta的两份日志,和合并时几十倍相比仍然很少,并不是系统的主要问题。至于metadb本身的数据,我们会在写完后进行清理,不会进行实际的落盘,所以也没有额外的开销。(当然上述前提是写入数据有索引,需要写meta,否则我们的写是和原版保持一致的) + ## 4. 问题与解决 ### 设计层面 1. 我们对并发的写入请求进行了合并,但在测试中发现了一个问题:之前提到,putfield和delete都需要先读一次原来的数据,但他们读不到合并在一起的请求中,之前的那个数据。这就导致了不一致(e.g. 将对于同一个key的putfield和delete请求合并,处理putfield时本次处理要写kv和index,处理delete时先读,发现数据库原来的数据中字段没有索引,于是删kv但没有删index)。我们的解决方式是,对于并发的写入只处理第一个相同的key。这同样提高了处理请求的效率。 diff --git a/test/helper.cc b/test/helper.cc index 2ce5e2d..87a8833 100644 --- a/test/helper.cc +++ b/test/helper.cc @@ -84,6 +84,7 @@ void GetOneField(FieldDB *db, std::string key = "0") { void InsertFieldData(FieldDB *db, int seed = 0/*随机种子*/) { std::cout << "-------inserting-------" << std::endl; + // size_t writeSize = 0; WriteOptions writeOptions; int key_num = data_size / value_size; // srand线程不安全,这种可以保证多线程时随机序列也一致 @@ -94,6 +95,7 @@ void InsertFieldData(FieldDB *db, int seed = 0/*随机种子*/) { //让批量写入的key>0, 单独写入的key<=0,方便测试观察 int key_ = std::abs(randThisTime) % key_num + 1; std::string key = std::to_string(key_); + // std::string key = std::to_string(seed*key_num+i+1); std::string name = "customer#" + std::to_string(key_); std::string address = cities[randThisTime % cities.size()]; @@ -111,7 +113,9 @@ void InsertFieldData(FieldDB *db, int seed = 0/*随机种子*/) { } Status s = db->PutFields(WriteOptions(), key, fields); ASSERT_TRUE(s.ok()); + // writeSize += key.size() + SerializeValue(fields).size(); } + // std::cout << writeSize << std::endl; } void DeleteFieldData(FieldDB *db, int seed = 0/*随机种子*/) { diff --git a/test/parallel_test.cc b/test/parallel_test.cc index 6406c16..0a6e763 100644 --- a/test/parallel_test.cc +++ b/test/parallel_test.cc @@ -48,6 +48,7 @@ TEST(TestReadPut, Parallel) { GetFieldData(db, allowNotFound, 1); findKeysByCity(db); checkDataInKVAndIndex(db); + // db->CompactRange(nullptr, nullptr); delete db; }