LEVELDB介绍

基本信息

特性

● keys 和 values 是任意的字节数组。

● 数据按 key 值排序存储,调用者可以重载函数来重写排序顺序。

● 提供基本的 Put(key,value),Get(key),Delete(key),Batch() 操作。

● 多个更改可以在一个原子批处理中生效。

● 用户可以创建一个瞬时快照(snapshot),以获得数据的一致性视图。

● 在数据上支持向前和向后迭代。

● 使用 Snappy 压缩库对数据进行自动压缩

● 与外部交互的操作都被抽象成了接口(如文件系统操作等),因此用户可以根据接口自定义的操作系统交互。

局限

● 不是一个关系数据库,它没有关系数据模型,不支持 SQL 查询,也不支持索引。

● 同时只能有一个进程(可能是具有多线程的进程)访问一个特定的数据库。

● 该程序库没有内置的 client-server 支持,有需要的用户必须自己封装。

读写特点

● leveldb是一个写性能十分优秀的存储引擎,是典型的LSM树(Log Structured-Merge Tree)实现。LSM树的核心思想就是放弃部分读的性能,换取最大的写入能力。

● LSM树写性能极高的原理,简单地来说就是尽量减少随机写的次数。对于每次写入操作,并不是直接将最新的数据驻留在磁盘中,而是将其拆分成(1)一次日志文件的顺序写(2)一次内存中的数据插入。leveldb正是实践了这种思想,将数据首先更新在内存中,当内存中的数据达到一定的阈值,将这部分数据真正刷新到磁盘文件中,因而获得了极高的写性能(顺序写60MB/s, 随机写45MB/s)。

架构

MemTable:之前提到,leveldb的一次写入操作并不是直接将数据刷新到磁盘文件,而是首先写入到内存中作为代替,memtable就是一个在内存中进行数据组织与维护的结构。memtable中,所有的数据按用户定义的排序方法排序之后按序存储,等到其存储内容的容量达到阈值时(默认为4MB),便将其转换成一个不可修改的memtable,与此同时创建一个新的memtable,供用户继续进行读写操作。memtable底层使用了一种跳表数据结构,这种数据结构效率可以比拟二叉查找树,绝大多数操作的时间复杂度为O(log n)。

immutable:memtable的容量到达阈值时,便会转换成一个不可修改的memtable,也称为immutable memtable。这两者的结构定义完全一样,区别只是immutable memtable是只读的。当一个immutable memtable被创建时,leveldb的后台压缩进程便会将利用其中的内容,创建一个sstable,持久化到磁盘文件中。

下载安装

参见GitHub - google/leveldb: LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.

Step1

下载git(以centos为例)

yum install git

Step2

下载原码

git clone --recurse-submodules https://github.com/google/leveldb.git

Step3

编译安装

cd leveldb
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .

Step4

移动库和头文件

cd ..
cp build/libleveldb.a /usr/local/lib/
cp -r include/leveldb/ /usr/local/include/

使用

参照leveldb/index.md at main · google/leveldb · GitHub

原码头文件在include,实现在db以及util里。

●api整理

// 打开(创建)数据库
Static Status Open(const Options& options, const std::string& dbname, DB** dbptr);
// 删除数据库
LEVELDB_EXPORT Status DestroyDB(const std::string& dbname, const Options& options);
// 恢复数据库
LEVELDB_EXPORT Status RepairDB(const std::string& dbname, const Options& options);
// 写入键值
Status Put(const WriteOptions& opt, const Slice& key, const Slice& value) = 0;
// 读键值
Status Get(const ReadOptions& options, const Slice& key, std::string* value)= 0;
// 删除键值对
virtual Status Delete(const WriteOptions& options, const Slice& key) = 0;

●编译.cpp文件

g++ demo.cpp -o demo -lpthread -lleveldb

●打开(创建)数据库

leveldb::DB *db = nullptr; //数据库指针
leveldb::Options options;  //控制数据库的一些操作
​
// 如果数据库不存在就创建
options.create_if_missing = true;
​
// 创建的数据库在 /tmp/testdb
leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
assert(status.ok());

 

●关闭数据库

delete db;

●删除数据库

DestroyDB("/tmp/testdb", options);

●读写操作

std::string key = "test_key";
std::string value = "test_value";
std::string get;
 
leveldb::Status s = db->Put(leveldb::WriteOptions(), key, value);
  
if (s.ok()) 
	s = db->Get(leveldb::ReadOptions(), key, &get);
if (s.ok()) 
	std::cout << "key=" << key << "\nvalue=" << get  << std::endl;
else 
	std::cout << "failed to find the key!" << std::endl;

●同步读写

LevelDB默认不使用同步写,将数据write后,不调用sync就返回了,数据很有可能还在缓冲区里。可以手动开启同步写。

leveldb::WriteOptions woptions;
options.sync = true;
leveldb::DB* db;
db->Put(options, "hello", "LevelDB");

●批量处理(原子更新)

有时候需要一些更新同时生效,也就是要支持多个操作的原子性。可以把DeletePut加入到一个WriteBatch中,一次性写入数据库。

leveldb::WriteBatch batch;
batch.Delete(key1);
batch.Put(key2, value);
s = db->Write(leveldb::WriteOptions(), &batch);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值