概述

LevelDB是一个由Google开发的快速键值存储库,提供了有序映射从字符串键到字符串值。它采用LSM-Tree(Log-Structured Merge-Tree)架构,优化了写入性能。

基本API使用示例

1. 基本的增删改查操作

#include <iostream>
#include <cassert>
#include "leveldb/db.h"

int main() {
    leveldb::DB* db;
    leveldb::Options options;
    leveldb::Status status;

    // 配置选项
    options.create_if_missing = true;  // 如果数据库不存在则创建
    
    // 打开数据库
    status = leveldb::DB::Open(options, "/tmp/testdb", &db);
    assert(status.ok());

    // 写入数据
    status = db->Put(leveldb::WriteOptions(), "key1", "value1");
    assert(status.ok());
    
    // 读取数据
    std::string value;
    status = db->Get(leveldb::ReadOptions(), "key1", &value);
    assert(status.ok());
    std::cout << "读取到的值: " << value << std::endl;
    
    // 删除数据
    status = db->Delete(leveldb::WriteOptions(), "key1");
    assert(status.ok());
    
    // 验证删除
    status = db->Get(leveldb::ReadOptions(), "key1", &value);
    assert(status.IsNotFound());
    
    delete db;
    return 0;
}

2. 批量操作示例

#include "leveldb/db.h"
#include "leveldb/write_batch.h"

void batch_operations_example() {
    leveldb::DB* db;
    leveldb::Options options;
    options.create_if_missing = true;
    
    leveldb::Status status = leveldb::DB::Open(options, "/tmp/batchdb", &db);
    assert(status.ok());
    
    // 创建批量操作
    leveldb::WriteBatch batch;
    batch.Put("key1", "value1");
    batch.Put("key2", "value2"); 
    batch.Put("key3", "value3");
    batch.Delete("old_key");  // 删除可能不存在的键
    
    // 原子性执行所有操作
    status = db->Write(leveldb::WriteOptions(), &batch);
    assert(status.ok());
    
    delete db;
}

3. 迭代器遍历示例

#include "leveldb/db.h"

void iterator_example() {
    leveldb::DB* db;
    leveldb::Options options;
    options.create_if_missing = true;
    
    leveldb::Status status = leveldb::DB::Open(options, "/tmp/iterdb", &db);
    assert(status.ok());
    
    // 插入一些测试数据
    db->Put(leveldb::WriteOptions(), "apple", "fruit");
    db->Put(leveldb::WriteOptions(), "banana", "fruit");
    db->Put(leveldb::WriteOptions(), "carrot", "vegetable");
    
    // 创建迭代器
    leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
    
    // 遍历所有键值对
    std::cout << "正向遍历:" << std::endl;
    for (it->SeekToFirst(); it->Valid(); it->Next()) {
        std::cout << it->key().ToString() << " => " << it->value().ToString() << std::endl;
    }
    
    // 反向遍历  
    std::cout << "\n反向遍历:" << std::endl;
    for (it->SeekToLast(); it->Valid(); it->Prev()) {
        std::cout << it->key().ToString() << " => " << it->value().ToString() << std::endl;
    }
    
    // 定位到特定键
    it->Seek("b");
    if (it->Valid()) {
        std::cout << "\n从'b'开始的第一个键: " << it->key().ToString() << std::endl;
    }
    
    delete it;
    delete db;
}

4. 快照(Snapshot)使用示例

#include "leveldb/db.h"

void snapshot_example() {
    leveldb::DB* db;
    leveldb::Options options;
    options.create_if_missing = true;
    
    leveldb::Status status = leveldb::DB::Open(options, "/tmp/snapdb", &db);
    assert(status.ok());
    
    // 写入初始数据
    db->Put(leveldb::WriteOptions(), "key1", "initial_value");
    
    // 创建快照
    const leveldb::Snapshot* snapshot = db->GetSnapshot();
    
    // 修改数据
    db->Put(leveldb::WriteOptions(), "key1", "modified_value");
    
    // 从快照读取(看到的是旧值)
    leveldb::ReadOptions read_options;
    read_options.snapshot = snapshot;
    std::string value;
    
    status = db->Get(read_options, "key1", &value);
    assert(status.ok());
    std::cout << "快照中的值: " << value << std::endl;  // 输出: initial_value
    
    // 正常读取(看到的是新值)
    status = db->Get(leveldb::ReadOptions(), "key1", &value);
    assert(status.ok());
    std::cout << "当前值: " << value << std::endl;  // 输出: modified_value
    
    // 释放快照
    db->ReleaseSnapshot(snapshot);
    delete db;
}

5. 配置选项示例

#include "leveldb/db.h"
#include "leveldb/cache.h"
#include "leveldb/filter_policy.h"

void advanced_options_example() {
    leveldb::DB* db;
    leveldb::Options options;
    
    // 基本设置
    options.create_if_missing = true;
    options.error_if_exists = false;
    options.paranoid_checks = true;
    
    // 性能调优参数
    options.write_buffer_size = 64 * 1024 * 1024;  // 64MB写入缓冲区
    options.max_open_files = 500;
    options.block_size = 64 * 1024;  // 64KB块大小
    options.block_restart_interval = 32;
    options.max_file_size = 64 * 1024 * 1024;  // 64MB最大文件大小
    
    // 压缩设置
    options.compression = leveldb::kSnappyCompression;
    
    // 缓存设置
    leveldb::Cache* cache = leveldb::NewLRUCache(256 * 1024 * 1024);  // 256MB缓存
    options.block_cache = cache;
    
    // 布隆过滤器
    const leveldb::FilterPolicy* filter = leveldb::NewBloomFilterPolicy(10);
    options.filter_policy = filter;
    
    leveldb::Status status = leveldb::DB::Open(options, "/tmp/advanceddb", &db);
    if (!status.ok()) {
        std::cerr << "打开数据库失败: " << status.ToString() << std::endl;
        return;
    }
    
    // 执行一些操作...
    db->Put(leveldb::WriteOptions(), "test_key", "test_value");
    
    // 清理资源
    delete db;
    delete cache;
    delete filter;
}

6. 范围查询示例

#include "leveldb/db.h"

void range_query_example() {
    leveldb::DB* db;
    leveldb::Options options;
    options.create_if_missing = true;
    
    leveldb::DB::Open(options, "/tmp/rangedb", &db);
    
    // 插入有序数据
    for (int i = 0; i < 100; i++) {
        std::string key = "key" + std::to_string(i);
        std::string value = "value" + std::to_string(i);
        db->Put(leveldb::WriteOptions(), key, value);
    }
    
    // 范围查询: 查询key10到key20之间的数据
    leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
    
    std::cout << "key10到key20范围内的数据:" << std::endl;
    for (it->Seek("key10"); it->Valid() && it->key().ToString() <= "key20"; it->Next()) {
        std::cout << it->key().ToString() << " => " << it->value().ToString() << std::endl;
    }
    
    delete it;
    delete db;
}

7. 错误处理示例

#include "leveldb/db.h"

void error_handling_example() {
    leveldb::DB* db;
    leveldb::Options options;
    leveldb::Status status;
    
    // 尝试打开不存在的数据库且不创建
    options.create_if_missing = false;
    status = leveldb::DB::Open(options, "/tmp/nonexistentdb", &db);
    
    if (!status.ok()) {
        std::cout << "预期的错误: " << status.ToString() << std::endl;
        
        if (status.IsNotFound()) {
            std::cout << "数据库文件不存在" << std::endl;
        } else if (status.IsCorruption()) {
            std::cout << "数据库文件损坏" << std::endl;
        } else if (status.IsIOError()) {
            std::cout << "IO错误" << std::endl;
        }
    }
    
    // 正确打开数据库
    options.create_if_missing = true;
    status = leveldb::DB::Open(options, "/tmp/errordb", &db);
    assert(status.ok());
    
    // 读取不存在的键
    std::string value;
    status = db->Get(leveldb::ReadOptions(), "nonexistent_key", &value);
    if (status.IsNotFound()) {
        std::cout << "键不存在(这是正常情况)" << std::endl;
    }
    
    delete db;
}

8. 数据库属性查询示例

#include "leveldb/db.h"

void property_query_example() {
    leveldb::DB* db;
    leveldb::Options options;
    options.create_if_missing = true;
    
    leveldb::DB::Open(options, "/tmp/propdb", &db);
    
    // 插入一些数据
    for (int i = 0; i < 1000; i++) {
        std::string key = "key" + std::to_string(i);
        std::string value = "value" + std::to_string(i);
        db->Put(leveldb::WriteOptions(), key, value);
    }
    
    // 查询数据库统计信息
    std::string stats;
    if (db->GetProperty("leveldb.stats", &stats)) {
        std::cout << "数据库统计信息:\n" << stats << std::endl;
    }
    
    // 查询SSTable信息
    std::string sstables;
    if (db->GetProperty("leveldb.sstables", &sstables)) {
        std::cout << "SSTable信息:\n" << sstables << std::endl;
    }
    
    // 查询大概的内存使用量
    std::string memory_usage;
    if (db->GetProperty("leveldb.approximate-memory-usage", &memory_usage)) {
        std::cout << "大概内存使用量: " << memory_usage << " bytes" << std::endl;
    }
    
    delete db;
}

9. 手动压缩示例

#include "leveldb/db.h"

void compaction_example() {
    leveldb::DB* db;
    leveldb::Options options;
    options.create_if_missing = true;
    
    leveldb::DB::Open(options, "/tmp/compactdb", &db);
    
    // 写入大量数据
    for (int i = 0; i < 10000; i++) {
        std::string key = "key" + std::to_string(i);
        std::string value = std::string(1000, 'a' + (i % 26));  // 1KB值
        db->Put(leveldb::WriteOptions(), key, value);
    }
    
    // 删除一半数据
    for (int i = 0; i < 5000; i++) {
        std::string key = "key" + std::to_string(i);
        db->Delete(leveldb::WriteOptions(), key);
    }
    
    std::cout << "压缩前的数据库状态:" << std::endl;
    std::string stats;
    if (db->GetProperty("leveldb.stats", &stats)) {
        std::cout << stats << std::endl;
    }
    
    // 手动触发全量压缩
    db->CompactRange(nullptr, nullptr);
    
    std::cout << "压缩后的数据库状态:" << std::endl;
    if (db->GetProperty("leveldb.stats", &stats)) {
        std::cout << stats << std::endl;
    }
    
    delete db;
}

编译和链接

CMake示例

cmake_minimum_required(VERSION 3.10)
project(LevelDBExample)

set(CMAKE_CXX_STANDARD 14)

# 查找LevelDB库
find_package(PkgConfig REQUIRED)
pkg_check_modules(LEVELDB REQUIRED leveldb)

# 添加可执行文件
add_executable(leveldb_example main.cpp)

# 链接LevelDB库
target_link_libraries(leveldb_example ${LEVELDB_LIBRARIES})
target_include_directories(leveldb_example PRIVATE ${LEVELDB_INCLUDE_DIRS})
target_compile_options(leveldb_example PRIVATE ${LEVELDB_CFLAGS_OTHER})

Makefile示例

CXX = g++
CXXFLAGS = -std=c++14 -Wall -O2
LIBS = -lleveldb -lsnappy -lpthread

all: leveldb_example

leveldb_example: main.cpp
	$(CXX) $(CXXFLAGS) -o $@ $< $(LIBS)

clean:
	rm -f leveldb_example

.PHONY: all clean

性能优化建议

1. 写入优化

  • 使用WriteBatch进行批量写入
  • 合理设置write_buffer_size
  • 考虑设置sync=false以提高写入性能(但会有数据丢失风险)

2. 读取优化

  • 使用布隆过滤器减少磁盘访问
  • 调整block_cache大小
  • 使用快照避免读写冲突

3. 存储优化

  • 启用压缩(默认Snappy)
  • 定期进行手动压缩
  • 合理设置max_file_size

这些示例展示了LevelDB的基本使用方法和高级特性。在实际项目中,应根据具体需求调整配置参数以获得最佳性能。