Хранение данных с помощью memtx | Tarantool
Документация на русском языке
поддерживается сообществом
Движки базы данных Хранение данных с помощью memtx

Хранение данных с помощью memtx

Движок базы данных memtx используется в Tarantool по умолчанию. Он хранит все данные в оперативной памяти (RAM), поэтому значение задержки чтения у него очень низкое.

Очевидный вопрос: если все данные хранятся в памяти, как можно предотвратить их потерю в случае чрезвычайной ситуации, например при отключении электропитания или сбое экземпляра Tarantool?

Прежде всего, Tarantool сохраняет все изменения данных, записывая запросы в журнал упреждающей записи (WAL), хранящийся на диске. Подробнее это описано в разделе Персистентность данных. В случае распределенного приложения возможна синхронная репликация, которая обеспечивают согласованность данных в кворуме реплик. Хотя репликация напрямую не относится к механизму хранения, она отчасти способствует безопасности данных. Подробности можно найти в разделе Репликация данных.

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

There is a fixed number of independent execution threads. The threads don’t share state. Instead they exchange data using low-overhead message queues. While this approach limits the number of cores that the instance uses, it removes competition for the memory bus and ensures peak scalability of memory access and network throughput.

Only one thread, namely, the transaction processor thread (further, TX thread) can access the database, and there is only one TX thread for each Tarantool instance. In this thread, transactions are executed in a strictly consecutive order. Multi-statement transactions exist to provide isolation: each transaction sees a consistent database state and commits all its changes atomically. At commit time, a yield happens and all transaction changes are written to WAL in a single batch. In case of errors during transaction execution, a transaction is rolled-back completely. Read more in the following sections: Transaction model, Transaction mode: MVCC.

Внутри потока TX есть область памяти, в которой Tarantool хранит данные. Эта область называется Arena.

../../../../_images/arena2.svg

Данные хранятся в спейсах. Спейсы содержат записи базы данных — кортежи. Чтобы обращаться к данным, хранящимся в спейсах и кортежах, и изменять их, Tarantool создаёт индексы.

Распределением памяти для спейсов, кортежей и индексов внутри области Arena управляют специальные аллокаторы. Для хранения кортежей главным образом используется аллокатор slab. В Tarantool встроен модуль под названием box.slab, предоставляющий статистику распределения slab. С помощью этой статистики можно отслеживать общее использование памяти и ее фрагментацию. Подробности см. в руководстве по модулю box.slab.

../../../../_images/spaces_indexes.svg

Also inside the TX thread, there is an event loop. Within the event loop, there are a number of fibers. Fibers are cooperative primitives that allows interaction with spaces, that is, reading and writting the data. Fibers can interact with the event loop and between each other directly or by using special primitives called channels. Due to the usage of fibers and cooperative multitasking, the memtx engine is lock-free in typical situations.

../../../../_images/fibers-channels.svg

To interact with external users, there is a separate network thread also called the iproto thread. The iproto thread receives a request from the network, parses and checks the statement, and transforms it into a special structure—a message containing an executable statement and its options. Then the iproto thread ships this message to the TX thread and runs the user’s request in a separate fiber.

../../../../_images/iproto.svg

Чтобы обеспечить персистентность данных, Tarantool выполняет следующие действия.

  • Исполнив в памяти запросы на изменение данных, Tarantool записывает все эти запросы в файлы журнала упреждающей записи (WAL) (с расширением .xlog), хранящиеся на диске. Это делается в отдельном потоке, называемом поток WAL.
../../../../_images/wal.svg
  • Tarantool периодически делает снимок всей базы данных и сохраняет его на диск. Это необходимо для ускорения перезапуска экземпляра, так как если файлов WAL слишком много, то Tarantool не сможет быстро перезапуститься.

    Специальный файбер под названием демон снимков (snapshot daemon) позволяет сохранять снимки. Он читает консистентное содержимое всей области Arena и записывает его на диск в файл снимка (с расширением .snap). Из-за кооперативной многозадачности Tarantool не может записывать данные непосредственно на диск, так как это блокирующая операция. Поэтому Tarantool взаимодействует с диском через отдельный пул потоков из библиотеки fio.

../../../../_images/snapshot03.svg

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

Что происходит при перезапуске:

  1. Tarantool находит и читает последний файл снимка.
  2. Tarantool также находит и читает все файлы WAL, созданные после этого снимка.
  3. Как только снимок и файлы WAL будут прочитаны, набор данных в памяти будет полностью восстановлен. Он будет соответствовать состоянию экземпляра Tarantool на момент, когда тот прекратил работу.
  4. Во время чтения снимка и файлов WAL Tarantool строит первичные индексы.
  5. Когда все данные снова в памяти, Tarantool строит вторичные индексы.
  6. Tarantool запускает приложение.

Чтобы обращаться к данным, хранящимся в оперативной памяти, и работать с ними, Tarantool строит индексы, которые хранятся внутри области памяти Arena.

Tarantool поддерживает несколько типов индексов: TREE, HASH, BITSET, RTREE. Все они предназначены для разных сценариев использования.

Можно выполнять SELECT-запросы как по первичным, так и по вторичным ключам индекса. Ключи могут быть составными.

Подробности про индексы можно найти на странице Индексы.

Хотя эта тема не имеет прямого отношения к движку memtx, она дополняет общую картину того, как работает Tarantool, когда приложение распределенное.

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

Чтобы отправить данные на реплику, Tarantool запускает еще один поток, называемый relay. Этот поток читает файлы WAL и отправляет их репликам. На каждой реплике выполняется файбер под названием applier. Он получает изменения от удаленного узла и применяет их к области Arena реплики. Все изменения записываются в файлы WAL через поток WAL реплики так же, как если бы они были сделаны локально.

../../../../_images/replica-xlogs.svg

В Tarantool репликация по умолчанию асинхронна: то, что транзакция проходит коммит локально на главном узле, не означает, что она отправляется на какие-то другие реплики.

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

Более подробные сведения вы найдете в главе о репликации.

Вот главные принципы, по которым работает движок:

  • Все данные находятся в оперативной памяти.
  • Доступ к данным производится только из одного потока.
  • Tarantool записывает все изменения данных в файлы WAL.
  • Периодически создаются снимки данных.
  • Для доступа к данным создаются индексы.
  • Файлы WAL можно реплицировать.