Основы использования RocksDB в коде на C++

25 октября 2017

RocksDB — это встраиваемая база данных на основе LSM-tree с открытым исходным кодом (лицензция Apache 2.0) от компании Facebook. Является форком LevelDB, созданной в Google. В RocksDB устранены многие недостатки LevelDB и, кроме того, существенно расширен функционал. Из известных пользователей RocksDB можно привести в пример Facebook, Yahoo, LinkedIn, Airbnb, Pinterest, Uber и Netflix. Кроме того, RocksDB используется в таких проектах, как CockroachDB, TiDB и Apache Flink. Из этой статьи вы узнаете, как использовать RocksDB в своих проектах.

Многие дистрибутивы Linux предлагают готовый пакет RocksDB. Например, в Ubuntu пакет называется librocksdb-dev, а в Arch Linux пакет rocksdb доступен на AUR.

В проектах, использующих CMake, подключить RocksDB проще простого:

# ...

find_library(ROCKSDB_LIBRARY rocksdb)

# ...

target_link_libraries(main ${ROCKSDB_LIBRARY})

Рассмотрим примеры кода. Открытие и закрытие базы данных производится так:

/* ... */

using namespace rocksdb;

PersistentStorage::PersistentStorage() {
    _db = nullptr;

    Options options;

    options.IncreaseParallelism();
    options.OptimizeLevelStyleCompaction();
    options.create_if_missing = true;

    Status s = DB::Open(options, "hurma_data", &_db);
    if(!s.ok())
        throw std::runtime_error("DB::Open failed");
}

PersistentStorage::~PersistentStorage() {
    if(_db != nullptr)
        delete _db;
}

… где _db — это private член класса:

/* ... */

#include <rocksdb/db.h>

class PersistentStorage : public Storage {

/* ... */

    PersistentStorage(PersistentStorage const&) = delete;
    void operator=(PersistentStorage const&) = delete;
private:
    rocksdb::DB* _db;
};

Чтение, запись и удаление данных:

std::string PersistentStorage::get(const std::string& key,
                                   bool* found) {
    std::string value = "";
    Status s = _db->Get(ReadOptions(), key, &value);
    *found = s.ok();
    return value;
}

void PersistentStorage::set(const std::string& key,
                            const std::string& value) {
    /* ... */
    Status s = _db->Put(WriteOptions(), key, value);
    if(!s.ok())
        throw std::runtime_error("_db->Put failed");
}

void PersistentStorage::del(const std::string& key, bool* found) {
    std::string value = "";
    Status s = _db->Get(ReadOptions(), key, &value);
    *found = s.ok();
    if(!*found)
        return;
    s = _db->Delete(WriteOptions(), key);

    *found = s.ok();
}

Заметьте, что для индикации ошибок RocksDB не бросает исключения, а использует специальный класс Status. Это было сделано специально, чтобы библиотеку можно было использовать в проектах на C++ как использующих исключения, так и не использующих (такая практика принята в некоторых компаниях).

Сканирование по диапазону ключей делается так:

#include "defer.h"

/* ... */

std::string PersistentStorage::getRange(const std::string& key_from,
                                        const std::string& key_to) {
    Iterator* it = _db->NewIterator(ReadOptions());
    defer(delete it);

    /* ... */

    for(it->Seek(key_from);
        it->Valid() && it->key().ToString() <= key_to;
        it->Next())
    {
        std::string key = it->key().ToString();
        std::string value = it->value().ToString()

        /* ... */
    }

    // Check for any errors found during the scan
    if(!it->status().ok())
        throw std::runtime_error("Error during the scan");

    /* ... */
}

Здесь используется библиотека deferxx, уже знакомая нам по заметке Продолжаем изучение OpenGL: управление камерой при помощи мыши и клавиатуры. Библиотека реализует оператор defer, автоматический выполняющий кусок кода при выходе из метода, независимо от того, вернул ли он управление штатно, или же было брошено исключение.

Как видите, все достаточно просто. Полную версию исходного кода вы найдете в этом репозитории на GitHub. По крайней мере, он там точно был в районе коммита 9c2033ae, но в будущем ситуация может и измениться. Вам нужен файл PersistentStorage.cpp.

Дополнительные материалы:

А доводилось ли вам работать с RocksDB и если да, то каковы ваши впечатления от него?

Дополнение: Пример простейшей key-value СУБД на основе Badger

Метки: .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.