Отчёты тормозят основную работу
Тяжёлые выборки по тем же таблицам, что и приём заказов, конкурируют за блокировки. Менеджеры ждут, пока бухгалтер строит свод. Иногда это проблема индексов, иногда разных нагрузок на одни данные.
CQRS разделяет модель записи и модель чтения, Event Sourcing хранит не текущее состояние, а ряд фактов, из которых оно собирается. Первое нужно заметно чаще второго, а вместе они нужны реже, чем о них пишут. Мы не продаём шаблон: сначала проверяем, решает ли вашу проблему индекс, представление в базе или таблица истории. Если нет, внедряем по ступеням и так, чтобы вернуться на предыдущую можно было без переписывания.
Обследование, где ответ может быть «не нужно», — от 200 000 ₽Четыре ступени сложности, остановиться можно на любойИсходный код и правила пересборки данных в вашем репозитории
Тяжёлые выборки по тем же таблицам, что и приём заказов, конкурируют за блокировки. Менеджеры ждут, пока бухгалтер строит свод. Иногда это проблема индексов, иногда разных нагрузок на одни данные.
В таблице лежит текущий статус, а как заявка пришла к нему, видно только по журналу приложения. Аудитор или клиент просит восстановить состояние на дату.
Склад, страховой полис, договор с этапами: у объекта десятки переходов, и каждый имеет условия. Логика размазана по контроллерам и триггерам.
Задержка между записью и чтением пугает пользователей, пересобрать данные нельзя, события менялись без версий. Нужен разбор, что оставить, а что упростить.
Большинство задач решается на первой-второй ступени. Каждая следующая добавляет эксплуатационные расходы, поэтому переходим на неё только по замеру.
Схема из двух прямоугольников ничего не объясняет. Разберём путь одной операции, чтобы стало видно, что именно меняется.
Пользователь нажимает «Согласовать заявку». Приложение принимает не «обновить строку», а команду с именем и параметрами. Модель записи проверяет правила: заявка в нужном статусе, у пользователя есть право, лимит не превышен. Если правила нарушены, команда отклоняется с понятной причиной. Если нет, меняется состояние и фиксируется факт, например «заявка согласована».
Экраны получают данные из таблиц, заточенных под показ: список заявок уже содержит имя заявителя, статус и срок, без пяти соединений. Эти таблицы обновляются либо в той же транзакции (ступень 2), либо отдельным процессом по событиям (ступень 3).
На ступени 3 пользователь нажал «Согласовать», обновил страницу и видит старый статус. Это не ошибка, а свойство схемы, и с ним работают в интерфейсе: после команды показывается результат из ответа на неё, список обновляется по готовности, а при сбое появляется понятное сообщение. Если задержка недопустима в конкретном сценарии, он остаётся на ступени 2.
На выборке реальных запросов определяем, что именно тормозит: запись, чтение или конкуренция за блокировки. Ступень выбираем по замеру. Если хватало индекса и представления, честно говорим, что остальное не нужно.
Основная польза Event Sourcing — в истории и пересборке. Если эти два свойства вам не нужны, цена почти наверняка выше пользы.
Журнал хранится годами, а код меняется. Поле появилось позже, смысл поля поменялся, событие разделили на два. Старые события должны читаться новым кодом: для этого у каждого события есть версия, а при чтении старые версии приводятся к текущей. Без такого механизма журнал через два года превращается в архив, который никто не может прочитать. Правило для всех изменений записывается в каталоге событий, а совместимость проверяется в сборке на сохранённых образцах реальных событий.
Чем длиннее журнал, тем дольше строится проекция с нуля. Для этого вводят снимки состояния, и пересборка идёт с последнего снимка. Время полной пересборки измеряется и записывается заранее, иначе в день, когда проекция оказалась неверной, выяснится, что исправление займёт сутки при простое. Пересборку проверяем на копии данных, а переключаем проекцию, когда новая готова.
Событие, которое уже записано, не меняют. Если оно ошибочно, добавляют исправляющее событие, и проекции учитывают обе записи.
Неизменяемый журнал плохо сочетается с требованием удалять данные по запросу. Технически это решается тем, что персональные данные хранятся отдельно, а в событии лежит ссылка, или шифруются ключом субъекта, который можно уничтожить. Какие данные и на каких основаниях удалять, определяет юрист заказчика; мы закладываем техническую возможность. Подробнее о мерах — на странице защиты персональных данных.
Состояние не лежит в одном месте, его нужно собирать. Поэтому в проект входят инструменты: просмотр потока событий по объекту, воспроизведение на копии, сравнение проекции с источником.
Создали, прочитали, изменили, удалили. Здесь модель записи и модель чтения совпадают, и разделение только удваивает код.
Если вся логика сводится к проверке обязательных полей, а история нужна для редкого разбора, достаточно таблицы истории и журнала действий.
Event Sourcing требует дисциплины в версиях, пересборке и инструментах. Если некому это поддерживать, система через год станет сложнее той, которую заменяла.
Экраны, где пользователь сразу после действия должен видеть результат из базы. Такие сценарии остаются на единой модели или на ступени 2.
Цены совпадают со страницей тарифов. Остановиться можно после любой ступени, сделанное остаётся у вас.
Замеры запросов и блокировок, разбор требований к истории. На выходе рекомендация по ступени (возможно, «добавить индексы») и вилка бюджета. Вычитается из первого этапа.
Когда журнал или проекции затрагивают учёт, склад и отчётность: схема обменов, источники истины, порядок перехода.
Один объект (заявка, заказ) переводится на выбранную ступень, рядом со старым путём. Проверка пересборки и задержки на ваших данных.
Event Sourcing для критичного объекта с версиями событий, снимками, инструментами просмотра и пересборки.
Перенос остальных объектов по одному, регламент пересборки, обучение вашей команды, передача инструкций и тестов.
Мониторинг отставания проекций, разбор расхождений, плановые доработки с пакета на 60 000 ₽. Сверх пакета 5 000 ₽ в час.
Снимаем журнал медленных запросов, блокировки, профиль нагрузки; отдельно выясняем, какая история и какие срезы нужны бизнесу и аудиту.
Записываем, какую ступень выбрали, какую отвергли и по каким замерам. Задаём пороги: допустимая задержка чтения, время пересборки.
Новый путь работает рядом со старым. Сравниваем результаты чтения и записи, проверяем сценарии: сбой обработчика, повтор, ошибочное событие.
Просмотр потока событий, сравнение проекции с источником, скрипт полной пересборки с замером времени. Ими пользуется ваша команда.
Полная пересборка на копии боевых данных, проверка версий событий на сохранённых образцах, нагрузочная проверка чтения.
Переводим следующий объект, если первый показал пользу. Остановиться можно после пилота.
Вторая ступень стоит заметно меньше четвёртой. Журнал событий добавляет версии, снимки, инструменты и обучение команды.
Число объектов, переходов и правил. Простая сущность с тремя статусами и объект с двадцатью переходами оцениваются по-разному.
Если история нигде не сохранялась, прошлое восстановить нельзя. Если данные нужно перенести в журнал, миграция входит в бюджет отдельной строкой.
Допустимое отставание чтения, срок хранения журнала, время пересборки: чем жёстче, тем больше проверок и инструментов.
Пять признаков, что вам это не нужно, и более простые решения: таблица истории, снимки, представления, реплика для отчётов.
Как устроены события, чем событие отличается от вызова и на каких задачах подход окупается.
Что платите за распределённость и как резать систему по понятиям. Пригодится, если проекции планируется строить в отдельных сервисах.
Сорок минут созвона: что тормозит, какую историю вы теряете и какие срезы данных нужны бизнесу или аудиту. По итогам скажем, хватит ли индекса или таблицы истории, и если нет, с какой ступени начинать.
Начинаем с обследования: 200 000 ₽ за один-два процесса, 350 000 ₽ при нескольких системах. Оно вычитается из первого этапа, если продолжаете с нами. Пилот одного объекта 150 000–400 000 ₽, журнал событий для ядра процесса 400 000–1 200 000 ₽. Вывод в эксплуатацию от 1 500 000 ₽ этапами по 300 000–700 000 ₽. Итог зависит от ступени: вторая стоит заметно меньше четвёртой.
CQRS разделяет модель записи (команды с правилами) и модель чтения (таблицы под экраны). Event Sourcing хранит изменения как ряд фактов и собирает состояние из них. Первое можно применять без второго, и это встречается чаще. Второе почти всегда идёт вместе с разделением чтения и записи, потому что состояние из журнала читать неудобно.
Часто да. Таблица истории с полями «что, кто, когда, было, стало», снимки состояния по расписанию и журнал действий закрывают большинство требований аудита. Журнал событий оправдан, когда на истории строится логика или нужно задним числом строить новые срезы.
Показывать результат из ответа на команду, обновлять список по готовности, оставлять сценарий на единой модели, если задержка недопустима. Задержка на третьей ступени неизбежна, это свойство схемы; допустимое отставание задаётся порогом и контролируется мониторингом.
Записанное событие не меняют. Добавляют исправляющее событие, проекции учитывают обе записи. Для ошибок в схеме событий используются версии и приведение старых к текущей. Правила исправления записываются в инструкцию для вашей команды.
Технически: хранить их отдельно от событий и класть в событие ссылку либо шифровать ключом субъекта, который можно уничтожить. Какие данные и на каких основаниях удалять, решает юрист заказчика; мы закладываем возможность и описываем процедуру.
Да. Выбираем один объект, строим новый путь рядом со старым, сравниваем результаты, при расхождении откатываемся. Остальные объекты переводим по одному. Остановиться можно после пилота.
На ваших серверах или у выбранного вами хостера. Исходный код, каталог событий и скрипты пересборки лежат в вашем репозитории с первого коммита. Результат работ передаётся вам по акту; порядок передачи прав записывается в договоре; открытые компоненты остаются под своими лицензиями, их список входит в документацию.
Мы в Ростове-на-Дону, работаем с заказчиками по всей России: удалённо и в вашем контуре. Доступ к системам и обследование согласуем на старте с вашей службой безопасности.