TigerBeetle показала protocol-aware DST: тестирование базы данных не только снаружи, но и изнутри

TigerBeetle показала protocol-aware DST: тестирование базы данных не только снаружи, но и изнутри

Команда распределённой базы данных TigerBeetle опубликовала в блоге разбор своей технологии protocol-aware DST (protocol-aware Deterministic Simulation Testing), расширенной версии детерминированного симуляционного тестирования, которая теперь проверяет инварианты безопасности и живучести не только на уровне внешнего API базы данных, но и внутри состояния каждой отдельной реплики.

В статье авторы напоминают базовые понятия тестирования распределённых систем. Инвариант безопасности (safety) означает, что «ничего плохого никогда не происходит», например, два узла никогда не возвращают разные ответы на один и тот же запрос. Инвариант живучести (liveness) означает, что «рано или поздно происходит что-то хорошее», например, запрос в итоге получает ответ, пока в сети остаётся достаточно узлов. Протокол консенсуса обеспечивает оба свойства: отказоустойчивость через репликацию данных и согласованность через выборную главную реплику (primary), через которую проходят все запросы. В качестве иллюстрации авторы приводят пример: в системе с 3 репликами, где большинство, это 2 реплики, протокол типа Viewstamped Replication выдерживает до 1 отказа.

TigerBeetle использует протокол Viewstamped Replication (VSR) и за счёт маршрутизации всех запросов через главную реплику гарантирует строгую сериализуемость (strict serializability), самый строгий уровень изоляции, который может обеспечить база данных: если одна операция завершилась раньше, чем началась другая, база обязана отразить именно этот порядок. Строгая сериализуемость, это инвариант безопасности TigerBeetle, а живучесть системы, это способность VSR оставаться отзывчивой, пока большинство узлов кластера онлайн. В прошлом году независимый Jepsen-тест подтвердил, что интеграция VSR с гибкими кворумами не нарушила инвариант строгой сериализуемости.

Однако и Jepsen-тестирование, и подход конкурирующей платформы Antithesis (детерминированные гипервизоры) проверяют систему только «снаружи», через видимые пользователю API, они не видят инварианты, которые не проявляются на границе API. TigerBeetle спроектирована как детерминированная база данных: она обладает логическим детерминизмом (весь код детерминирован, в контрольной плоскости нет многопоточной конкуренции, как у FoundationDB) и физическим детерминизмом (реплики кластера сходятся к побайтово идентичному состоянию на диске). Именно детерминизм позволяет запускать настоящий код консенсуса и хранилища внутри симулятора VOPR: сеть, диск и время в нём заменены управляемыми версиями, поэтому сценарии, которые в проде заняли бы месяцы, в симуляторе воспроизводятся за минуты, а найденный баг детерминированно повторяется сколько угодно раз.

Protocol-aware DST даёт симулятору полную видимость внутреннего состояния консенсуса и хранилища каждой реплики и добавляет две дополнительные, более глубокие проверки. Первая, согласованность WAL (write-ahead log, журнала упреждающей записи): в проде бэкап сверяет свой WAL с главной репликой только по периодическим коммит-сообщениям, а при расхождении падает по ассерту и остаётся лежать (нарушение безопасности превращается в недоступность). В protocol-aware DST симулятор сверяет контрольные суммы WAL при каждом отдельном закоммиченном запросе на каждой реплике, а не только периодически. Вторая проверка, детерминизм хранилища: в проде расхождение проверяется по одной контрольной сумме чекпоинта (checkpoint_id), а в protocol-aware DST симулятор идёт глубже и сверяет контрольные суммы метаданных всех таблиц LSM-дерева на всех уровнях (структура Manifest, индекса над данными на диске), подтверждая, что дерево полностью идентично на всех репликах.

Сохранённый текст статьи обрывается на середине фразы («мы также физически проверяем, детерминировано ли наше хранилище...»), поэтому итоговая часть материала и, возможно, заключительные выводы в пересказ не попали. В статье также не приводятся ни число багов, найденных именно благодаря protocol-aware-проверкам, ни оценка накладных расходов на производительность по сравнению с обычным DST.

Ключевые факты

  • TigerBeetle, распределённая финансовая база данных на протоколе Viewstamped Replication (VSR); маршрутизация всех запросов через главную реплику даёт ей строгую сериализуемость, самый строгий уровень изоляции.
  • В прошлом году независимый Jepsen-тест подтвердил, что интеграция VSR с гибкими кворумами не нарушила инвариант строгой сериализуемости.
  • Внутренний симулятор VOPR запускает настоящий код консенсуса и хранилища на одной машине с ускоренным симулированным временем, благодаря логическому (как у FoundationDB) и физическому детерминизму TigerBeetle (реплики сходятся к побайтово идентичному состоянию, здесь TigerBeetle идёт дальше FoundationDB).
  • Protocol-aware DST добавляет две проверки поверх обычного DST: сверку контрольных сумм WAL при каждом закоммиченном запросе на каждой реплике и сверку контрольных сумм всех таблиц LSM-дерева (индекс Manifest) по всем уровням.
  • В статье не приводится ни число багов, найденных именно protocol-aware-проверками, ни оценка накладных расходов; сохранённый текст обрывается на середине фразы.

Почему это важно

Классические методы тестирования распределённых систем, генеративное тестирование по Jepsen и детерминированные гипервизоры вроде Antithesis, проверяют систему только «снаружи», через видимый пользователю API. Это значит, что нарушение внутреннего инварианта в протоколе консенсуса или в движке хранения может долго оставаться незамеченным, если оно ещё не успело просочиться наружу и исказить ответ клиенту. Protocol-aware DST закрывает этот разрыв: симулятор получает полную видимость состояния каждой реплики и ловит нарушение инварианта в момент его возникновения, а не по косвенным симптомам. Для TigerBeetle это особенно важно, поскольку поверх неё строятся финансовые приложения, полагающиеся на её гарантию строгой сериализуемости.

Кому это важно

Материал адресован инженерам, которые строят распределённые системы на протоколах консенсуса (VSR, Raft, Paxos и их варианты), разработчикам баз данных и SRE-командам, отвечающим за надёжность инфраструктуры. Также полезен тем, кто оценивает TigerBeetle как базу для финансовой или другой критичной нагрузки: пост показывает, какими внутренними проверками подкреплены её внешние гарантии.

Как это применить

Подход требует, чтобы детерминизм был заложен в архитектуру системы с самого начала: логический, весь код детерминирован, в контрольной плоскости нет многопоточной конкуренции; и физический, реплики сходятся к побайтово идентичному состоянию на диске. Только это делает возможным симулятор вроде VOPR, где реальный код консенсуса и хранилища прогоняется на одной машине с управляемыми сетью, диском и временем. На этой основе команда переносит дорогие, требующие глобального контекста проверки (сверка WAL при каждом коммите, сверка контрольных сумм всей структуры LSM-дерева) из продакшена, где они были бы слишком затратны, в симулятор, где скорость не ограничена.

Можно ли доверять

Источник, инженерный блог самой TigerBeetle с фрагментами реального кода на Zig, поэтому механизм описан достаточно подробно и проверяемо. Но это самоотчёт без независимого аудита: в отличие от прошлогоднего Jepsen-теста, который проводила сторонняя команда, утверждения о protocol-aware DST в статье никем извне не подтверждены. Число багов, пойманных именно этим методом, и его накладные расходы на производительность в тексте не приводятся, так что оценить практическую отдачу метода по одному этому источнику нельзя. Кроме того, сохранённый текст обрывается на середине фразы, так что часть материала до пересказа не дошла.

Риски и подводные камни

Метод неуниверсален: он работает только для систем, изначально спроектированных как детерминированные, для большинства существующих распределённых систем это означало бы серьёзную переработку архитектуры, а не добавление отдельного тестового инструмента. Protocol-aware DST также не заменяет внешнее тестирование через Jepsen или Antithesis, а дополняет его: сама TigerBeetle подчёркивает, что нужно тестировать и «снаружи», и «изнутри» одновременно. Наконец, в статье нет количественных данных о том, сколько дополнительных багов метод реально нашёл, эффективность подхода в тексте утверждается, но не подтверждена цифрами.

«Интеграция Viewstamped Replication с гибкими кворумами и восстановлением с учётом протокола, судя по всему, не нарушила ключевой инвариант, строгую сериализуемость.»

— из прошлогоднего отчёта Jepsen о тестировании TigerBeetle (цитата в статье)