简介
LevelDB是一个Google编写的快速键值存储库,它提供从字符串键到字符串值的有序映射。
基本架构
LSM树存储引擎
先说什么是存储引擎:
- 存储引擎是存储系统的发动机,直接决定了存储系统能够提供的性能和功能
存储系统的基本功能包括:增删读改,读取操作又可以分为随机读取和顺序扫描
- 哈希存储引擎是哈希表的持久化表现,不支持顺序扫描,对应的存储系统为键值存储系统
- B-Tree存储引擎是B-Tree的持久化实现,支持顺序扫描,对应的存储系统为关系数据库
- LSM树存储引擎和B-Tree支持顺序扫描,它通过批量转储技术规避磁盘随机写入问题
LevelDB的LSM存储引擎
LSM树的想法很简单,就是将对数据的修改增量保持在内存中,达到能指定的大小限制后将这些修改操作批量写入磁盘,读取时需要合并磁盘中的历史数据和内存中最近的修改操作。LSM树有效的规避了磁盘随机写入的问题,丹读取时可能需要访问较多的磁盘文件
存储结构
- 如图所示,LevelDB存储引擎主要包括:内存中的MemTable和不可变MemTable以及磁盘上的几种主要文件;当前文件、清单文件、操作日志文件以及SSTable文件
- 当引用写入一条记录时,LevelDB会首先将修改操作写入到操作日志文件,成功后再将操作应用到MemTable,这样就完成了写入操作。
当MemTable占用的内存到达一个上限值后,需要将内存的数据转储到外存文件中
LevelDB会将原先的MemTable冻结成为不可变MemTable,并生成一个新的MemTable
新到来的数据被记入新的操作日志文件和新生成的MemTable中
LevelDB后台线程将不可变MemTable的数据排序后转出到磁盘,形成一个新的SSTable文件,注册操作成为Compaction
SSTable文件是内存中的数据不断进行Compaction操作后形成的
SSTable中的文件是按照记录的主键排序的,每个文件中都有最小的主键和最大的主键
LevelDB的写入操作很简单,但读取操作比较复杂,需要在内存以及各个层级文件中按照从新到老一次查找,为了加快速度,LevelDB内部会执行Compaction操作来对已有的记录进行整理压缩,从而删除一些不再有效的记录,减少数据规模和文件数量
安装和使用
下载后解压
下载地址
LevelDB只支持POSIX系统,如Linux和Mac等
编译
cd leveldb-1.20
make
安装
sudo cp -r leveldb-1.20/include/leveldb/ /usr/include/
sudo cp leveldb-1.20/out-shared/libleveldb.so.1.20 /usr/lib
sudo ln -s /usr/lib/libleveldb.so.1.20 /usr/lib/libleveldb.so.1
sudo ln -s /usr/lib/libleveldb.so.1.20 /usr/lib/libleveldb.so
sudo ldconfig
测试程序
#include <assert.h>
#include <string.h>
#include <leveldb/db.h>
#include <iostream>
using namespace leveldb;
using namespace std;
int main(int argc, char** argv)
{
DB* db;
Options options;
// 如果打开已存在数据库的时候,需要抛出错误,将以下代码插在DB::Open方法前面
options.create_if_missing = true;
// 打开一个数据库实例
Status status = DB::Open(options, "/tmp/testdb", &db);
assert(status.ok());
// LevelDB提供了Put、Get和Delete三个方法对数据库进行添加、查询和删除
string key = "Hello";
string value = "leveldb";
// 添加key=value
status = db->Put(WriteOptions(), key, value);
assert(status.ok());
// 根据key查询value
status = db->Get(ReadOptions(), key, &value);
assert(status.ok());
cout << "key = " << key << endl;
cout << "value = " << value << endl;
// 删除key
status = db->Delete(WriteOptions(), key);
// 查询key
status = db->Get(ReadOptions(), key, &value);
if (!status.ok()) {
cerr << key << ": " << status.ToString() << endl;
} else {
cout << key << "==" << value << endl;
}
delete db;
return 0;
}
all:
g++ -g -Wall -o test test.cpp -lleveldb
clean:
rm test
注意:要加上链接库-lleveldb
运行结果:
key = Hello
value = leveldb
Hello: NotFound:
现在leveldb就已经安装成功了