因为自己对数据库比较感兴趣,所以听说LevelDB时间比较早,但因种种原因一直没有写过相关的文章。这段时间不忙,准备做一个系列相关的主题。
我们知道,现在主流的数据库有从关系型数据库逐渐往分布式数据库迁移的趋势,比如大名鼎鼎的TiDB和PolarDB。而TiDB底层存储引擎使用的是RocksDB,RocksDB则使用了LevelDB(这就是开源的力量,相互借鉴)。从这方面看,LevelDB的性能可见一斑。
本篇文章主要介绍LevelDB的一些特点和基础概念。LevelDB是LSM (Log Structured Merge)算法的实现。里面涉及大量关于文件系统读写技术的真实案例。我们可以从中收货很多重要信息。
当前官方的源码地址:C 版本,另外还有两个移植版本分别是GoLevelDB和javaLevelDB。工程从结构和文件命名上基本保持了跟C 版本的一致。各位看官可以根据自己的喜好各取所需。不过建议还是从C 官方版本看起。有位老哥之前做过一版注释,不过可能是基于main主分支为母版,但是并不影响代码阅读。我使用当前版本为1.22。
我自己用的是Mac电脑,主要开发语言是Java。对于C 的使用,更倾向于使用centos系统。所以我平时都是自建虚拟机,然后通过VSCode插件Remote Development“远程”控制来完成项目编译和调试工作。
获取源代码:
git clone --recurse-submodules https://github.com/google/leveldb.git
构建:
mkdir -p build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .
注:编译完是没有out-shared,out-static这两个文件夹 。
头文件介绍:
leveldb 对外暴露的接口都在 include/*.h 中,用户不应该依赖任何其它目录下的头文件,这些内部 API 可能会在没有警告的情况下被改变。
我们可以编写一段代码,来进行简单的测试:
#include <assert.h>
#include <string.h>
#include <leveldb/db.h>
#include <iostream>
using namespace leveldb;
int main()
{
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
// 打开一个数据库,不存在就创建
leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
assert(status.ok());
// 插入一个键值对
status = db->Put(leveldb::WriteOptions(), "hello", "LevelDB");
assert(status.ok());
// 读取键值对
std::string value;
status = db->Get(leveldb::ReadOptions(), "hello", &value);
assert(status.ok());
std::cout << value << std::endl;
delete db;
return 0;
}
编译命令:
g test_db.cc -o test_db -L /usr/local/lib64 -lleveldb -lpthread -D_GLIBCXX_USE_CXX11_ABI=0 -std=c 11
指定静态库路径:-L /usr/local/lib64 ,静态库名称:-lleveldb D_GLIBCXX_USE_CXX11_ABI:GCC版本1.5前后接口兼容性问题闭坑参数。
执行test_db文件后,进入/tmp/testdb目录下,看到以下几个文件:
[root@localhost testdb]# cd /tmp/testdb/
[root@localhost testdb]# ll
total 16
-rw-r--r-- 1 root root 34 Oct 14 03:45 000003.log
-rw-r--r-- 1 root root 16 Oct 14 03:45 CURRENT
-rw-r--r-- 1 root root 0 Oct 14 03:45 LOCK
-rw-r--r-- 1 root root 77 Oct 14 03:45 LOG
-rw-r--r-- 1 root root 50 Oct 14 03:45 MANIFEST-000002
[root@localhost testdb]# pwd
/tmp/testdb
[root@localhost testdb]#
喜欢用Java的同学可以引入对应的文件包同样可以完成上面的操作,POM文件:
<dependency>
<groupId>org.iq80.leveldb</groupId>
<artifactId>leveldb-api</artifactId>
<version>0.12</version>
</dependency>
<dependency>
<groupId>org.iq80.leveldb</groupId>
<artifactId>leveldb</artifactId>
<version>0.12</version>
</dependency>
Java代码:
import org.iq80.leveldb.DB;
import org.iq80.leveldb.DBFactory;
import org.iq80.leveldb.Options;
import org.iq80.leveldb.impl.Iq80DBFactory;
import java.io.File;
import java.io.IOException;
public class TestLevelDB {
public static void main(String[] args) throws IOException {
DBFactory factory = new Iq80DBFactory();
Options options = new Options();
options.createIfMissing(true);
DB db = factory.open(new File("/tmp/testdb"), options);
db.put(Iq80DBFactory.bytes("leveldb") , Iq80DBFactory.bytes("It is leveldb."));
byte[] bytes = db.get(Iq80DBFactory.bytes("leveldb"));
System.out.println(Iq80DBFactory.asString(bytes));
}
}
总结
通过以上内容,我大概了解到了一些leveldb的特性和不足,并且做了简单的上机实验。更多功能测试,可以参考官方文档。后续我们将系统阐述leveldb各模块实现以及模块之间如何协作高效完成文件的读写能力。
资料参考:
基本概念 — leveldb-handbook 文档
Leveldb 基本介绍和使用指南 - 掘金 (juejin.cn)
头条居然不支持外链!
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved