RocksDB сервер – быстрое key-value хранилище для SSD накопителей

    RocksDB RocksDB – постоянное хранилище «ключ-значение» для быстрых накопителей. Основное ее предназначение — хранение данных на flash дисках.

    Узким местом в производительности часто является обращение к БД.
    Эта проблема может решаться по разному.
    Использование кэша решает проблему производительности, но существенно усложняет архитектуру программы. Графовые базы данных выходят из ситуации за счет оптимальных для данной задачи алгоритмов. Другим типом решений являются хранилища, достигающие высокой производительности за счет использования быстрого носителя.
    В последнее время появилось много NoSQL хранилищ полностью хранящих данные в памяти. Но память все еще стоит дорого и ее объем ограничен. Увеличение памяти за счет шардинга опять таки упирается в стоимость.
    Логичным выходом из ситуации было бы использование SSD дисков. Они имеют относительно невысокую стоимость и при этом вполне небольшое время отклика.



    К сожалению, не смотря на то что SSD диски существуют уже несколько лет, не так много баз данных оптимизированы для работы с ними. Основная проблема при использовании SSD диска в качестве носителя для БД – это многократная перезапись одних и тех же блоков. Т.н.з. «замозоливание».

    RocksDB – гибкое производительное встраиваемое NoSQL хранилище. Расчитана она на использование на быстрых носителях, таких как SSD диски. Она написана в Facebook и базируется на гугловской LevelDB.
    Если не углубляться в детали, то главными отличиями от LevelDB являются оптимизированный для работы с флеш-накопителями движок; оптимизация для работы с большими объемами данных; большая гибкость и расширяемость и как следствие много вкусных плюшек, отсутствующих в LevelDB.

    Как я уже говорил, RocksDB – встраиваемое решение. И для того что бы ее можно было использовать ее нужно либо встроить в свое приложение, либо обернуть в сервер. Мне она нужна была для использования в веб-приложениях. И, по определенным причинам, связанным с тем что одновременно доступ к ней может иметь только один процесс (но не поток), мне нужен был именно сервер.
    Я узнал о RocksDB примерно год назад и терпеливо ждал пока кто-нибудь начнет писать для нее сервер. Все что появилось за это время в полной мере меня не устроило. Поэтому я решил написать собственную серверную обертку над RocksDB.

    RocksServer – однопоточный http сервер реализующий доступ к RocksDB.

    Сервер написан на C++. Для реализации http слоя был использован Libevent.
    Кроме Libevent и RocksDB код не содержит никаких других зависимостей.

    RocksDB обладает весьма богатыми возможностями. Я реализовал только базовый, необходимый мне в настоящий момент, функционал. В дальнейшем, конечно, по мере возможностей, я планирую расширять функциональные возможности сервера.

    Я не проводил масштабных бенчмарков, но предварительные замеры производительности показали вполне приличные результаты.

    Поддерживаемые в настоящий момент операции:
    Get получить одно значение по ключу
    Multi get атомарно получить несколько значений по набору ключей
    Set установить одно значение по ключу
    Multi set атомарно установить несколько значений по набору ключей
    Delete key удалить ключ из БД
    Multi delete атомарно удалить несколько ключей
    Check key exist быстрая проверка существования ключа в БД (с возможностью быстрого извлечения значения)
    Imcrement атомарное увеличение/уменьшение значения на заданную величину

    В случае необходимости список операций можно легко расширить. Для этого всего лишь нужно реализовать интерфейс:

        struct RequestBase 
        { 
            virtual ~RequestBase() {} 
    
            /** 
             *  Runs request listener 
             *  @param       event request object 
             *  @param       event buffer object 
             */ 
            virtual void run(const EvRequest &, const EvBuffer &) = 0; 
        }; 
    


    Например, в зависимости от вашей схемы данных, вам может понадобиться реализовать атомарную вставку/обновление набора ключей.
    Подключить ваш обработчик к серверу тоже не сложно. Делается это одной строчкой:

    server.onRequest("/castom_handler",   new RequestСastom());
    


    Компиляция/Установка


    Как я уже говорил, RocksServer имеет две зависимости: собственно RocksDB и http слой в виде Libevent. Можно установить их отдельно, а можно обойтись без установки ограничившись компиляцией (за счет статического связывания). Лично для меня последний способ предпочтительней т. к. позволяет запускать RocksServer в т.ч. на старых серверах не имеющих всех необходимых подзависимостей.

    Итак.
    Клонируем репозитарий:

    git clone --recursive git@github.com:valmat/RocksServer.git
    cd RocksServer
    

    или
    git clone git@github.com:valmat/RocksServer.git
    cd RocksServer
    git submodule update
    

    После клонирования Libevent и RocksDB окажутся в каталоге deps.
    Затем компилируем зависимости:

    ./deps/make.sh
    

    После этого шага можно, если хотите, запустить тесты либо установить Libevent и RocksDB в вашу систему.
    А можно сразу перейти к компиляции RocksServer

    cd src
    make
    

    Ваш компилятор должен поддерживать стандарт C++11
    Срузу после компиляции RocksServer можно запускать, предварительно отредактировав конфигурационный файл:

    ./RocksServer.bin config.ini
    

    А можно произвести его установку.
    make install
    

    В последнем случая для запуска/перезапуска/остановки нужно использовать init.d скрипт:
    /etc/init.d/rocksserver start
    

    Скорее всего, вы захотите настроить сервер под себя. Все имеющиеся настройки записаны в файле config.ini.

    Для тестирования я положил простенький драйвер на php (да я знаю что его надо переписать) либо вы можете напрямую использовать протокол. В том числе и с помощью таких программ как Curl и Wget.
    Протокол очень простой. При выборе между RPC и HTTP простота протокола обмена была одним из решающих моментов.

    В настоящий момент, не смотря на не очень богатый функционал, RocksServer полностью готов к работе. Во всяком случае, я планирую использовать его в продакшене в проекте над которым сейчас работаю (для этого и писал).

    Кроме меня Valgrind'а и CppCheck'а ревью кода никто не проводил. Поэтому опасения что, что-то может пойти не так вполне нормальны.
    На этот случай есть возможность логгирования RocksServer'а и возможность делать бэкапы в том числе в человекочитаемом формате.

    Для включения логгирования в конфигурационном файле нужно просто указать лог файл:

    ; Error log file name 
    ; default value: /var/log/rocksserver/error.log 
    ; 
    ; error_log = 
    

    И указать уровень подробности лога:
    ; Error level 
    ; Possible values: debug | msg |  warn | error | fatal | none 
    ; default value: none 
    ; 
    ; log_level = 
    

    Для бэкапа вам нужно указать каталог, в который будут складываться бэкапы:
    ; RocksDB backup path 
    ; The directory in which a backup will be stored
    ; default value: /var/rocksserver/backup 
    ; 
    ; backup_path = 
    

    и выполнить POST запрос к 127.0.0.1:5577/backup

    Для восстановления БД из бэкапа используйте команду
    restore -f/path/to/backup -t/path/to/db
    

    Для конвертирования БД в человекочитаемый вид:
    human_readable -f/path/to/db  -t/path/to/restore_file
    

    У себя я планирую следующую схему бэкапов:
    wget "http://localhost:5577/backup" --post-data="" -O -
    restore -f/path/to/backup -t/path/to/db_on_hdd
    human_readable -f/path/to/db_on_hdd  -t/path/to/restore_file
    


    Буду признателен за конструктивную критику.
    Готов помочь с установкой и настройкой.
    Ну и, разумеется, Pull Requests приветствуются.
    Спасибо за внимание.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 39
    • +8
      хранение данных на flesh дисках
      Ого! Это какая-то новая технология? Диски из плоти :)
      Прошу прощения за оффтоп
      • +1
        Спасибо, поправил.
      • +1
        Было бы интересно посмотреть на сравнения между leveldb и rocksdb.
        • 0
          Сам я такие бенчмарки не проводил. Но думаю нет оснований не верить Фэйсбуку: github.com/facebook/rocksdb/wiki/Performance-Benchmarks
          • 0
            Только стоит обратить внимание на конфигурацию стенда, на таком стенде действительно есть профит в силу правок в архитектуру LevelDB.
            • +1
              На счет стенда согласен. У Фэйсбука действительно уникальные условия использования.
              Тут важно два момента: LevelDB изначально не проектировалась для больших объемов данных, RocksDB наоборот; LevelDB не проектировалась для работы на SSD накопителях. Как следствие LevelDB на SSD потенциально может обернуться проблемами преждевременного износа SSD диска.
              • +1
                Полностью согласен, у LevelDB действительно выше нагрузка при записи. Вы замеряли производительность RocksDB или RocksServer на своем железе? Можете привести конфиг и rps на random write/read (желательно с key 8b, value 250b, но если есть другие бенчи — норм)? Кстати, какое отношение объема базы / RAM у вас в проекте?
          • 0
            У них разные задачи и подразумевается разная инфраструктура под ними. KVS нужно подбирать не по бенчмаркам на чужом железе и чужих средах, а исключительно под свою задачу и окружение. И да, если ваша инфраструктура windows-based можно забыть про rocksdb, слишком велика завязка на *nix особенностях. Если LevelDB можно адаптировать (и это успешно сделано ребятами из Bitcoin'а), то тут грусть печаль.

            Если есть желание, можете рассказать про условия своей задачи и как вы используете LevelDB, дам совет здесь же. Перебрал множество современных key value storages, есть опыт, с удовольствием поделюсь. Статья не потяну сейчас, но обсудить и обменяться опытом — было бы круто.
          • +1
            Хотелось бы сравнения с другими популярными NoSQL хранилищами. То, что это написано в Facebook — безусловно круто. Хорошо бы знать на сколько круто.
            • +1
              У RocksDB специфичная область применения. Поэтому сравнивать его нужно с хранилищами одного класса. Разумеется Redis'у она проиграет (по крайней мере при старте точно должна). Логичным было бы сравнивать, я думаю, с RethinkDB т.к. это тоже зрелое решение пригодное для установки на SDD носитель. Но я таких тестов не видел, а у самого пока руки не дошли их написать.
              • 0
                Как можно сравнивать RocksDB и Redis? Тогда уже RocksServer / Redis и то сравнение будет не совсем корректным.
                • 0
                  Я как раз и имел в виду, что некорректно сравнивать разные по своей природе NoSQL хранилища. Если говорить конкретно о RocksServer, то его основную область применения я вижу в достижении высокой производительности за счет переноса данных с HDD на более быстрый носитель и экономия на инфраструктуре за счет использования SDD вместо памяти. Тут не так уж и много вариантов для сравнения.
            • +2
              есть еще такой вариант — github.com/ideawu/ssdb-rocks от автора ssdb (LevelDB + net interface, очень клевая штука, имеет аналогичный с редисом интерфейс, все планирую написать статью о ней, использую в продакшине уже больше года)
              • 0
                Да я ее видел. Я тоже изначально хотел ее использовать. Честно, сейчас уже не вспомню что мне не понравилось, но отказался я от нее поковыряв исходники. Сейчас еще раз посмотрю попробую ответить подробнее.
                • 0
                  Посмотрел еще раз. К сожалению, наскоком так не смог найти почему я от нее отказался. На первый взгляд, с того момента когда я последний раз ее смотрел, код очень сильно поменялся.
                  Каково ваше впечатление от использования? Какие-нибудь глюки ловили? В последнее время я часто вижу ее в топе Гитхаба в разделе C++. Может быть ее уже допилили и там действительно все хорошо.
                  • +1
                    Мы кстати сравнивали RocksDB и в итоге остановились именно на SSDB. Уже не вспомню почему. Но SSDB работает вполне стабильно у нас на продакшене, крутит порядка 300ГБ данных в общей сложности. Полет нормальный.
                  • +2
                    make install

                    ну сколько же раз писали про это и пакетные дистрибутивы… checkinstall же!
                    • 0
                      Я у себя так и собираю. src/description-pak у меня как раз для checkinstall и лежит. Просто по идее сборка может проходить на любом Линукс дистрибутиве. Поэтому я не стал про это здесь писать. Тем более на Хабре уже много раз про checkinstall писали, поэтому мне показалось что не обязательно еще раз напоминать. Кстати для удаления я не забыл добавит команду make uninstall. Так что в данном конкретном случае make install вполне безопасен.
                    • +1
                      > Для реализации http слоя был использован Libevent.

                      Весьма похвально. Libevent используется в memcached.
                      • 0
                        Updated: Извините, ошибся уровнем комментария
                      • +1
                        Отличное решение! Вам стоит расширить набор бэкэндов для своего RocksServer'а, в силу практически идентичного API можно добавить LevelDB и HyperLevelDB. Это сделает проект еще интереснее, да и для своего проекта сможете выбрать тот бэкэнд, который действительно даст максимальный профит.
                        • 0
                          Спасибо за отзыв.
                          Никогда не сталкивался с HyperLevelDB. Если честно, я досконально не разбирался с API LevelDB. И сейчас мне трудно сказать в какой части они перестают быть совместимыми. Знаю точно, что то что я сейчас использую от RocksDB есть и в LevelDB. С другой стороны различные итераторы появившиеся в поздних версях RocksDB или семейства столбцов, скорее всего, в LevelDB отсутствую.
                          Вообще планы развивать RocksServer и добавлять бэкенды есть. Но сначала я хотел перейти к его практическому использованию. В текущем виде он решает те задачи которые есть у меня в настоящий момент и сама архитектура предполагает не сложное его расширение.
                          • +1
                            Как раз не смотрел итераторы в RocksDB и доп. фишки, но базовые вещи 1-в-1. HyperLevelDB полностью совместим с LevelDB в плане API. А можете рассказать больше про текущие задачи, действительно интересно (можно без функционала, если нельзя раскрывать, просто конфиг / требования / объемы / среда и т.д.).
                            • +2
                              Не уверен что верно понял ваш вопрос, но попробую ответить как понял.
                              Году где-то в 2012 я переписывал один довольно посещаемый проект (в то время посещаемость была ~50 000 хостов/сутки ). Сервер справлялся с нагрузкой но время отклика оставляло желать лучшего. Оптимизация MySQL кардинально ситуацию не улучшила. В итоге было решено добавить кэширующий слой. В качестве бекенда для кэширующий библиотеки были поставлены Redis и Memcached. В итоге время отклика стало экстремально низким: 2-6 мс, но поддержка проекта стала вызывать боль. Появилась сильная связанность. Вот собственно тогда размышляя над тем как такое получилось пришло понимание, что кэширования должно быть ровно столько, что бы оно не увеличивало связанность компонентов внутри проекта.

                              Теперь что меня привело к написанию RocksServer'a. Сейчас у меня наконец то представилась возможность поучаствовать в написании большого интересного проекта. Я не знаю заранее какой будет посещаемость но изначально время отклика должно быть экстремально низким. Собственно, обоснование того, почему какой бы эффективный алгоритм не использовало хранилище данных, все упирается в носитель (HDD) я описал в статье. Поэтому изначально рассматривал хранилища оптимизированные под SSD.

                              Инфраструктура. Планируется использовать Debian сервер (может быть будет Ubuntu). Структуру каталогов я планирую хранить в Resdis. Под него будет отведено 2-3 Гб. Все остальные данные пойдут в RocksServer. Под данные ожидается выделить 100-300 Гб. Мне уже писали в личку, что такой объем данных вполне можно засунуть в ОЗУ, но это существенно увеличит стоимость архитектуры. Поэтому из практических соображений SSD является для меня оптимальным компромиссом.
                              Что касается тонкой настройки самого RocksDB, то, как я уже говорил, в боевых условиях я его еще не испытывал, поэтому ничего полезного по этому поводу пока сказать не могу.
                          • 0
                            Если я верно вас понял, то вы имеете опыт работы с такими системами. Было бы очень интересно услышать с какими нюансами вы сталкивались.
                            • 0
                              Просто прошел тернистый путь подбора KVS под свои задачи. LevelDB, HyperLevelDB, Sophia, тайгер, решение от Symas'а и куча наркомании уровня BangDB. Причем как *nix, так и Windows среды (это было страшно). Какие нюансы вас интересуют?
                              • НЛО прилетело и опубликовало эту надпись здесь
                                • +2
                                  Пожалуй, самый забавный проект, начиная от оффсайта, заканчивая производительностью и API. Его, как и всех остальных, нужно уметь готовить. Играться компараторами, к примеру (настроек у него минимум). Его однозначный плюс — это автор, в отличии от того же Говарда Чу из OpenLDAP'а, к примеру, Дмитрий из mail.ru готов выслушать, помочь (в рамках проекта) и пообщаться за жизнь.

                                  Гонялся под виндой и линухом. Кстати, виндовый порт (написал биндинги под C#) не смотря на disclaimer создателя относительно содержимого — оказался вполне стабильный на небольшой нагрузке, LevelDB он обошел на поставленных задачах. Но в продакшен так и не ушел пока что. Для меня он в TOP-3 по совокупности и на втором месте по скорости в рамках поставленных задач.
                                  • НЛО прилетело и опубликовало эту надпись здесь
                          • +3
                            Добро пожаловать в мир Key/Value ;),

                            На мой взгляд, было бы очень логично использовать мемкешовый протокол. Есть куча готовых клиентов.
                            Хотя в проектах можно использовать и курл…

                            спаисбо за разработку…
                            • 0
                              Да вы правы. В текущем виде Memcache протокол смотрелся бы там очень логично. Я даже подумаю над тем, что бы добавить еще один уровень абстракции и сделать протокол заменяемым.
                              Поясню, почему я изначально не остановился на Memcache протоколе. RocksDB предоставляет бо`льшие возможности нежели Memcached и в дальнейшем я планирую расширять функциональные возможности. соответственно на каком то этапе Memcache протокол будет исчерпан.
                              Но, безусловно, никто не обязан использовать все возможности сервера. И вполне можно обойтись только базовыми. Так что ваше замечание очень полезно. Спасибо.
                              • +1
                                Просто по опыту скажу, что мемкешед более подходящее решение, так как сам написал пару оберток к существующим key/value (Sophia & Tokyo). Скажу больше, у нас в компании большинство демонов общаются с фронтэндом используя мемкешовый протокол. А недостаточную функциональность просто расширяем, добавляя префикс к ключам, или иным способом.
                                Например мультидел для ключей 123,456 и 789 можно реализовать так:
                                delete 123,456,789

                                в клиент передаем строку «123,456,789» которая не противоречит концепции ключа.

                                Принципиально, можно поддерживать два и более протоколов, как реализовано, например, в TokyoTyrant или тот же мемкеш поддерживает текстовый и бинарный протокол.
                                • 0
                                  А вам как Софья? Сравнивали с LMDB, кстати?
                            • 0
                              Насколько оно быстрее TokuDB?
                              • 0
                                Мне кажется некорректно сравнивать движок для MySQL со специфичным key/value хранилищем.
                                • 0
                                  TokuDB — такое же специфичное хранилище для SSD.
                                  Его достоинство в том, что оно умеет эффективно сжимать данные (в разы меньше места занимают, чем на mysql), получается экономия на дисковом пространстве — актуально для SSD.
                                  Плюс быстрая запись, оптимизированная под SSD.

                                  Так что вполне уместно было бы сравнить эти движки по параметрам: скорость записи, скорость чтения, сколько данные места на диске занимают.
                                  • 0
                                    Как то упустил этот MySQL движок из виду. Надо будет его «пощупать».
                              • 0
                                Судя по результатам теста, память неиспользуеться?
                                А почему такой маленький объем данных?
                                Сколько времени длился тест?
                                Какой размер на диске занимала база?
                                Какова была конфигурация тестового стенда?
                                Сколько клиентов запрашивало данные?
                                Клиент запускался на той же машине?

                                Возможно имело смысл использовать датасет с размером заведомо большим чем объем оперативной памяти.
                                Например 20М записей размером по 150 байт или 150% от объема оперативной памяти.
                                • +1
                                  В подобных проектах датасет должен быть однозначно больше объема памяти, иначе это чистый in-memory с индексом. А еще лучше в пропорции 10:1 и более, иначе прочувствовать IO-bounds сложно. По остальным вопросам автор уже отвечад — толком еще не гонялось, специальных бенчей не было.

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

                                Самое читаемое