[leveldb] 初探 leveldb

[TOC]

1、 leveldb 简介

leveldb 是 Google 用 C++ 开发的一个快速的 键值对存储数据库(持久化KV单机数据库),提供从字符串键到字符串值的有序映射,具有很高的随机写,顺序读/写性能,但是随机读的性能很一般,也就是说,LevelDB很适合应用在查询较少,而写很多的场景。

LevelDB应用了 LSM (Log Structured Merge) 策略,lsm_tree对索引变更进行延迟及批量处理,并通过一种类似于归并排序的方式高效地将更新迁移到磁盘,降低索引插入开销,关于LSM,本文在后面也会简单提及。

根据LevelDB官方网站的描述,LevelDB的特点和限制如下:

1-1 特点

  • 1、key和value都是任意长度的字节数组;
  • 2、entry(即一条K-V记录)默认是按照key的字典顺序存储的,当然开发者也可以重载这个排序函数;
  • 3、提供的基本操作接口:Put()、Delete()、Get()、Batch();
  • 4、支持批量操作以原子操作进行;
  • 5、可以创建数据全景的snapshot(快照),并允许在快照中查找数据;
  • 6、可以通过前向(或后向)迭代器遍历数据(迭代器会隐含的创建一个snapshot);
  • 7、自动使用Snappy压缩数据;
  • 8、可移植性;

1-2 限制

  • 1、非关系型数据模型(NoSQL),不支持sql语句,也不支持索引;
  • 2、一次只允许一个进程访问一个特定的数据库;
  • 3、没有内置的C/S架构,但开发者可以使用LevelDB库自己封装一个server;

LevelDB本身只是一个lib库,在源码目录make编译即可,然后在我们的应用程序里面可以直接include leveldb/include/db.h头文件

2、 leveldb 安装

2-1 下载 leveldb

wu_being@UbuntuKylin1704:~/Github/leveldb$ git clone https://github.com/google/leveldb

2-2 编译 leveldb

wu_being@UbuntuKylin1704:~/Github/leveldb$ cd leveldb/
wu_being@UbuntuKylin1704:~/Github/leveldb$ make

编译的动态库和静态库分别在 out-shared,out-static 下:

wu_being@UbuntuKylin1704:~/Github/leveldb$ ls leveldb/out-shared/libleveldb.so.1.20
wu_being@UbuntuKylin1704:~/Github/leveldb$ ls leveldb/out-static/libleveldb.a

2-3 安装 leveldb

只有动态库需要安装如果静态库在编译后直接链接即可。 (动态库静态库请看文章后来更多链接)

# cp leveldb header file
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo cp -r /leveldb/include/ /usr/include/

# cp lib to /usr/lib/
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo cp /leveldb/out-shared/libleveldb.so.1.20 /usr/lib/

# create link
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo ln -s /usr/lib/libleveldb.so.1.20 /usr/lib/libleveldb.so.1
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo ln -s /usr/lib/libleveldb.so.1.20 /usr/lib/libleveldb.so

# update lib cache
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo ldconfig

查看动态库安装是否成功


wu_being@UbuntuKylin1704:~/Github/leveldb$ ls /usr/lib/libleveldb.so*
# 显示下面 3 个文件即安装成功
/usr/lib/libleveldb.so.1.20
/usr/lib/libleveldb.so.1
/usr/lib/libleveldb.so

3、 leveldb 使用

我们的 leveldb目录下编写一个 test.cpp 来测试我们的 leveldb。将key1对应的value值,移到key2对应的值。。

#include <iostream>
#include <string>
#include <assert.h>    
#include "leveldb/db.h"    

using namespace std;

int main(void) 
{       

    leveldb::DB      *db;    
    leveldb::Options  options;    
    options.create_if_missing = true;    
    // options.error_if_exists = true;

    // open
    leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb2", &db);    
    assert(status.ok());    

    string key1  = "name1";
    string key2  = "name2";    
    string value = "wuchengbing12";    

    // write key1
    status = db->Put(leveldb::WriteOptions(), key1, value);    
    assert(status.ok());    

    // read key1
    status = db->Get(leveldb::ReadOptions(), key1, &value);    
    assert(status.ok());    

    cout<<value<<endl;    

    // write key2
    status = db->Put(leveldb::WriteOptions(), key2, value);    
    assert(status.ok());    

    // delete key1
    status = db->Delete(leveldb::WriteOptions(), key1);    
    assert(status.ok());        

    status = db->Get(leveldb::ReadOptions(),key2, &value);    
    // assert(status.ok());        
    if(!status.ok()) {
        cerr<<key2<<"    "<<status.ToString()<<endl;
    } else {
        cout<<key2<<"==="<<value<<"==="<<status.ToString()<<endl;    
    }   

    // close 
    delete db;    

    return 0;    
} 

3-1 编译 - 静态链接

wu_being@UbuntuKylin1704:~/Github/leveldb$ cp out-static/libleveldb.a ./
wu_being@UbuntuKylin1704:~/Github/leveldb$ g++ test.cpp -o test ./libleveldb.a -lpthread -Iinclude

3-2 编译 - 动态链接

wu_being@UbuntuKylin1704:~/Github/leveldb$ g++ test.cpp -o test -lpthread -lleveldb -Iinclude

3-3 运行结果


# 输出值为 a,说明成功存储和获取
wu_being@UbuntuKylin1704:~/Github/leveldb$ ./test 
wuchengbing12
name2===wuchengbing12===OK
wu_being@UbuntuKylin1704:~/Github/leveldb$

# 查看数据库
wu_being@UbuntuKylin1704:~/Github/leveldb$ ls /tmp/testdb2/ -l
总用量 24
-rw-r--r-- 1 wu_being wu_being 166 11月 13 13:14 000005.ldb
-rw-r--r-- 1 wu_being wu_being 106 11月 13 13:14 000006.log
-rw-r--r-- 1 wu_being wu_being  16 11月 13 13:14 CURRENT
-rw-r--r-- 1 wu_being wu_being   0 11月 13 13:14 LOCK
-rw-r--r-- 1 wu_being wu_being 310 11月 13 13:14 LOG
-rw-r--r-- 1 wu_being wu_being  57 11月 13 13:14 LOG.old
-rw-r--r-- 1 wu_being wu_being  83 11月 13 13:14 MANIFEST-000004
wu_being@UbuntuKylin1704:~/Github/leveldb$ 

4、 代码解释

4-1 打开一个数据库实例

一个leveldb数据库有一个对应一个文件系统目录的名字。该数据库的所有内容都存储在这个目录下。下面的代码描述了怎样打开一个数据库或者建立一个新的数据库。

#include <assert.h>    
#include "leveldb/db.h"    
     
leveldb::DB* db;    
leveldb::Options options;    
options.create_if_missing = true; //如果要打开的数据库不存在就创建新的   
leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb", &db);    
assert(status.ok());   

如果打开已存在数据库的时候,需要抛出错误。将以下代码插在leveldb::DB::Open方法前面:

options.error_if_exists = true;

4-2 对数据库的简单读、写操作

LevelDB提供了Put,Delete和Get三个方法对数据库进行修改和查询。例如,下面的代码片段描述了怎样将key1对应的value值,移到key2对应的值。

std::string value;    
leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);    
if(s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);    
if(s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);

4-3 关闭数据库

在对数据库进行了一系列的操作之后,需要对数据库进行关闭。该操作比较简单:

... open the db as described above...    
... do something with db ...    
delete db;

5、 更多链接

C语言的静态库与共享库使用:http://blog.csdn.net/u014134180/article/details/78335274

Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《[leveldb] 初探 leveldb》: https://yq.aliyun.com/articles/241407/

[leveldb] 初探 leveldb

如果你看完这篇博文,觉得对你有帮助,并且愿意付赞助费,那么我会更有动力写下去。

上一篇:[从C到C++] 1.3 C++布尔类型(bool)


下一篇:[从C到C++] 1.4 C++命名空间(namespace)