RocksDB - база данных, созданная Facebook. Он не поддерживает SQL, не предоставляет гарантий ACID и не может работать в распределенном режиме. Тем не менее, это одна из самых популярных баз данных в экосистеме разработчиков. Он используется в крупномасштабных фреймворках, таких как Apache Flink и CockroachDB.

Так что же делает RocksDB привлекательной альтернативой своим конкурентам?

Чтобы понять его вариант использования, во-первых, нам нужно взглянуть на мир встроенных баз данных.

Встроенная база данных

Как следует из названия, разработчики помещают встроенные базы данных в службу / приложение, использующее его. Это означает, что если ваше приложение работает в контейнере / сервере A, база данных также будет находиться в том же месте. Сетевые вызовы приводят к значительной задержке. Избегая их, вы можете на порядок сократить время доступа к БД.

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

Когда следует использовать встроенную базу данных?

Вам следует использовать встроенные БД в случаях, когда необходимо сохранить много данных, но данные могут быть быстро воссозданы и не являются критичными. Хранение таких данных в памяти вашего приложения ненадежно, тогда как хранение на диске в каком-либо простом формате приведет к большим задержкам.

Одна из самых популярных баз данных в этом домене - SQLite. Он широко используется приложениями Android для хранения информации, например, если пользователь уже вошел в систему или нет, вместе с идентификатором пользователя, dob, адресом и т. Д. Получение всех данных с сервера является дорогостоящим, в то время как после закрытия приложения данные в памяти исчезнут.

RocksDB

Хотя SQLite в большинстве случаев подходит, он страдает критическим ограничением. SQLite - это однопоточная база данных, которая не поддерживает одновременный доступ. Эта неспособность к многопоточности делает его чрезвычайно медленным в сценариях с высокой пропускной способностью.

Из-за этого ограничения Google создал LevelDB, который поддерживает многопоточность. Facebook использовал LevelDB в качестве основы для создания RocksDB. Еще одна популярная встроенная база данных, созданная за это время, - LMDB. LMDB имеет совершенно другую архитектуру, чем LevelDB, и работает значительно лучше в определенных сценариях. Однако, чтобы содержание было кратким, в этой статье я сосредоточусь на RocksDB.

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

SSTables

Google создал BigTable, который использовал SSTable внизу для хранения данных. Те же SSTables используются в RocksDB. SSTables хранят данные по типу "ключ-значение". Данные также сортируются по ключам. Сортировка обеспечивает быстрый доступ к данным, поскольку их легко искать в отсортированном диапазоне ключей.

SSTables также неизменны по своей природе. Это означает, что вы можете читать данные из SSTable, не беспокоясь о том, что они будут изменены в середине (если есть один SSTable).

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

<beginning_of_file>
[data block 1]
[data block 2]
...
[data block N]
[meta block 1]
...
[meta block K]
[metaindex block]
[index block]
[Footer]        (fixed size; starts at file_size - sizeof(Footer))
<end_of_file>

Файл содержит внутренние указатели. Каждый такой указатель называется BlockHandle и содержит следующую информацию:

offset:   varint64
size:     varint64

Объединенное дерево структуры журнала

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

LSM-деревья были созданы для решения указанной проблемы. Когда SSTable фиксированного размера превышает число, они объединяются в одну SSTable большего размера. Этот шаг известен как уплотнение, которое происходит в фоновом режиме. например, если количество файлов SSTable размером 10 МБ превышает 10, они объединяются в один файл SSTable размером 100 МБ. Для новых данных будет создана новая таблица SSTable наименьшего размера, например, 1 МБ.

Самые новые данные всегда находятся в самых маленьких файлах, а самые старые данные находятся в файлах большего размера.

Memtables

БД сначала вставляет данные в простую упорядоченную структуру в памяти, известную как Memtable, а также в файл на диске, известный как журнал фиксации. Это делает доступ к последним данным чрезвычайно быстрым, поскольку они уже присутствуют в памяти.

Поскольку Memtable уже отсортирована, она выгружается на диск для создания SSTable.

Почему бы тогда просто не использовать LevelDB?

RocksDB улучшает уровень DB почти во всех аспектах, что делает его привлекательным выбором по сравнению с предложениями Google.

Давайте посмотрим на меры, которые RocksDB предприняла для улучшения своих предшественников.

Не читайте несуществующие

BloomFilters позволяет пользователю быстро узнать, присутствует ли ключ в базе данных или нет. Они помогают предотвратить ненужное чтение в базу данных и значительно ускоряют ответ на запросы.

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

Обновляйте ключи без забот

Семейства столбцов - это механизм, который помогает пользователю логически разделить данные в одной БД. Пользователь может выполнять безопасную атомарную запись в несколько ключей в семействах столбцов.

Семейства столбцов совместно используют журнал упреждающей записи и не передают файлы memtables и таблиц. Разделяя журналы упреждающей записи, вы получаете преимущества атомарной записи. Разделив таблицы памяти и файлы таблиц, вы можете независимо настраивать семейства столбцов и быстро их удалять. Пример использования - хранить метаданные в одном семействе столбцов, а фактические данные - в другом. Затем вы можете применить другой тип сжатия и стратегии сжатия к метаданным и данным. При необходимости вы можете отбросить семейство столбцов метаданных, сохранив данные.

Сделать снимок

Поскольку RocksDB не предоставляет гарантии ACID, данные, которые вы читаете, могут изменяться при нескольких запросах, например, из-за сжатия, заменяющего одно значение другим.

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

Избегайте частичных обновлений

RocksDB обеспечивает поддержку транзакций как с пессимистичным, так и с оптимистичным контролем параллелизма.

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

Помимо основных изменений, упомянутых ранее, RocksDB также предоставляет некоторые дополнительные функции:

  • Стандартный ограничитель скорости для контроля пропускной способности вашей БД
  • Многопоточные уплотнения, которые делают их быстрее
  • Множественные алгоритмы сжатия, такие как LZ4, GZIP, SNAPPY и т. Д.

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

  1. SSTable и лог-структурированное хранилище: LevelDB
  2. История RocksDB
  3. Технический разговор RocksDB