【存储引擎】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 -lpthread
demo 执行结果
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
相关文章