Хранение данных

Отказались от баз данных. Используем Event Sourcing. Пишем в файл.

Почему базы данных не подходят

Обычно в базе данных хранят текущее состояние приложения. Так для Trading Engine в базе данных могли храниться балансы пользователей:

user

balance

John

100 USD

Bill

10 USD

Представим, что Джон решил отправить 10 USD Биллу. Trading Engine снимает 10 USD со счета Джона и зачисляет 10 USD на счет Биллу. Но сервер выходит из строя в середине процесса. Так у Джона уже сняли 10 USD, но пользователю Биллу 10 USD не зачислили. Деньги потерялись.

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

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

Event Sourcing

Вместо балансов пользователей мы храним события пользователя: сделал депозит, выставил ордер. Этот подход называется EventSourcing. Текущий баланс пользователя на диске не хранится.

Раньше хранили финальное состояние, а теперь храним все события:

  • Bill зарегистрировался

  • John зарегистрировался

  • John пополнил счет на $100

  • Bill пополнил счет на $10

  • John перевел $10 пользователю Bill

Если во время исполнения события сервер выйдет из строя, деньги не потеряются.

События сохраняются в файл

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

Так как события между модулями кодируются с помощью Simple Binary Encoding, кодировать их второй раз для сохранения на диск не нужно.

Бинарный буфер событий пишется напрямую в файл. При перезапуске системы файл вычитывается в такой же бинарный буфер.

Текущее состояние — в оперативной памяти

Текущее состояние Trading Engine (балансы, открытые ордера) имеется только в оперативной памяти. Если событие изменило баланс пользователя — меняем его только в оперативной памяти.

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