【存储引擎】LevelDB 编译使用
代码获取
git clone --recurse-submodules https://github.com/google/leveldb.git代码结构
leveldb 的代码结构如下,重要的是 db、table、util 三个文件夹,里面包含了 leveldb 核心的代码实现,还有 include,包含了使用 leveldb 需要引用的头文件:
编译使用
编译静态库
在源代码所在的文件夹(···/leveldb)里执行下面的命令,创建 build 文件夹 && 进入 build 文件夹:
mkdir -p build && cd build用 cmake 命令进行编译:
// release 版本cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build . // debug 版本cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .编译完成后,可以在 build 目录下看到编译出的静态库 libleveldb.a
demo 代码(建议横屏或用 PC 浏览)
using namespace std;
int main() { leveldb::DB* db; leveldb::Options opt; leveldb::Status status;
// 打开 /workspace/leveldb/test/testdb 目录里的数据库,若不存在则新建 opt.create_if_missing = true; status = leveldb::DB::Open(opt, "/workspace/leveldb/test/testdb", &db); if (!status.ok()) { cout << "Failed to open db! " << status.ToString() << endl; return ; } // 插入键值对 "test_key_A" - "test_value_a" string strKey = "test_key_A"; string strVal = "test_value_a"; status = db->Put(leveldb::WriteOptions(), strKey, strVal); if (!status.ok()) { cout << "Failed to exec put opt! " << status.ToString() << endl; delete db; return ; } // 根据键 "test_key_A" 查询存储的值 "test_value_a" string strSavedVal; status = db->Get(leveldb::ReadOptions(), strKey, &strSavedVal); if (!status.ok()) { cout << "Failed to find val for key " << strKey << "! " << status.ToString() << endl; delete db; return ; }
cout << "Got saved val[" << strSavedVal << "] for key " << strKey << endl; // 删除键为 "test_key_A" 的键值对 status = db->Delete(leveldb::WriteOptions(), strKey); if (!status.ok()) { cout << "Failed to del key-val for key " << strKey << "! " << status.ToString() << endl; delete db; return ; } // 根据键 "test_key_A" 查询存储的值 "test_value_a" status = db->Get(leveldb::ReadOptions(), strKey, &strSavedVal); if (!status.ok()) { cout << "Failed to find val for key " << strKey << "! " << status.ToString() << endl; delete db; return ; }
cout << "Got saved val[" << strSavedVal << "] for key " << strKey << endl;
delete db; return ;}demo 编译
把编译出的静态库 libleveldb.a 复制到 /usr/local/lib/ 把 leveldb 源码中 include 文件夹里相关的头文件复制到 /usr/local/include/ 保存 demo 代码为 demo.cpp,编译 demo:
g++ demo.cpp -o demo -lleveldb -lpthreaddemo 执行结果
PS:如果是在 wsl 中使用 leveldb,需要升级到 wsl 2,在 wsl 1 中无法启动 leveldb。
按照 demo 实现,会在 /workspace/leveldb/test/testdb 目录下创建一个新的数据库:
数据库文件在上一篇文章【存储引擎】LevelDB 概述 里已经有部分提及。目录里 .ldb 后缀的文件就是上一篇文章里所说的持久化存储在硬盘中的 ssttable。.log 后缀的文件里存储的就是 WAL 日志(先写日志数据,再写用户数据,以保证用户数据的持久化):
目录里,还有 LOG 和 LOG.old 日志文件,记录的是数据库运行过程中打印出来的日志,也就是通常意义上所说的日志(给人看的,用来调试、定位问题用的),每次重新打开数据库,都会创建新的 LOG,之前的 LOG 文件被重命名为 LOG.old:
目录中的 LOCK 是 leveldb 的文件锁。因为 leveldb 不允许多个进程同时访问数据库目录,所以每次打开数据库,leveldb 都会先获取 LOCK,获取成功才能下行流程,以此避免一个数据库被多个进程打开操作。
MANIFEST 文件包含的是 leveldb 的元信息,每次打开数据库,都会生成一个新的 MANIFEST 文件,新生成的 MANIFEST 文件有更大的版本号。
MANIFEST 文件可能会存在多个,CURRENT 文件记录的就是当前有效的 MANIFEST 的文件名:
来自:https://mp.weixin.qq.com/s/y_foxhvDzmLaUmpJ4HRr1Q
相关文章