使用leveldb
C++引入leveldb
编译安装:
git clone --recurse-submodules https://github.com/google/leveldb.git
cd leveldb
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .
sudo make install
C++工程引入leveldb库,需链接-lleveldb -lpthread
leveldb使用示例
#include <iostream>
#include <leveldb/db.h>
int main(int argc, char const *argv[])
{
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options, "testdb", &db);
if (!status.ok()) {
std::cout << "open db failed" << std::endl;
return -1;
}
std::cout << "open db success" << std::endl;
status = db->Put(leveldb::WriteOptions(), "rc", "Hello rc!");
if (!status.ok()) {
std::cout << "put db failed" << std::endl;
return -1;
}
std::cout << "put db success" << std::endl;
std::string res;
status = db->Get(leveldb::ReadOptions(), "rc", &res);
if (!status.ok()) {
std::cout << "get db failed" << std::endl;
return -1;
}
std::cout << "get db success" << std::endl;
std::cout << "get " << res << std::endl;
delete db;
return 0;
}
options选项含义
struct Options {
const Comparator* comparator; // 用来决定key在表中的排列顺序,默认按字典序存放
bool create_if_missing = false; // 为true表示数据库不存在则创建,否则会报错
bool error_if_exists = false; // 为true表示数据库存在则报错
bool paranoid_checks = false; // 为true表示,严格检错模式,出错后可能会导致数据库不可用
Env* env; // 平台兼容性相关,默认为Env::Default()
Logger* info_log = nullptr; // 为null则日志信息和数据内容写在同一个文件,否则单独写到info_log文件
size_t write_buffer_size = 4 * 1024 * 1024; // 大的写缓存可以提升性能,特别是大块数据加载的时候,但会增加内存占用,降低数据库打开速度
int max_open_files = 1000; // 数据库最多能打开的文件数
Cache* block_cache = nullptr; // 缓存块总的大小,为null则使用内部的8MB缓存块
size_t block_size = 4 * 1024; // 缓存块的大小,大缓存块可以提升大块扫描的性能,也能提升压缩性能
size_t max_file_size = 2 * 1024 * 1024; // leveldb最大写文件的大小,达到该值将创建新的文件
CompressionType compression = kSnappyCompression;// 压缩算法,kSnappyCompression或KNoCompression
bool reuse_logs = false; // 为true的话,会采用追加模式写manifest和log,可以提升数据库开启速度
const FilterPolicy* filter_policy = nullptr; // 如果用NewBloomFilterPolicy可以减少磁盘读取次数,但是会增加内存占用
}
struct ReadOptions {
bool verify_checksums = false; // 是否对查询出的数据做校验和运算
bool fill_cache = true; // 是否缓存这次查询结果(如果是做大块数据的扫描/遍历,那么最好设为false)
const Snapshot* snapshot = nullptr; // 指定从哪次快照中执行查询,为null则表示最新的状态查询
}
struct WriteOptions {
// 是否用同步的方式写入,若为true写入操作将会阻塞到数据成功存储到文件中
// 若为false,则机器崩溃后可能会丢失最近写入的数据
// 但如果只是程序崩溃,不是机器reboot,那么即使为false也不会丢失最近写入的数据
bool sync = false;
}
status错误代码
class Status {
public:
// 运行成功
bool ok() const;
// 未找到错误
bool IsNotFound() const;
// 崩溃错误
bool IsCorruption() const
// IO错误
bool IsIOError() const;
// 不支持错误
bool IsNotSupportedError() const;
// 参数非法错误
bool IsInvalidArgument() const;
};
Slice
Slice可以和string和char*类型相互转换,这里为了减少数据拷贝,Slice只保存传入的字符串的指针,所以string转换为Slice需要注意string对象的生存周期
class Slice {
public:
Slice(const char* s) : data_(s), size_(strlen(s)) {}
Slice(const std::string& s) : data_(s.data()), size_(s.size()) {}
std::string ToString() const { return std::string(data_, size_); }
const char* data() const { return data_; }
private:
const char* data_;
size_t size_;
};