Репликация AccountsDB для служб RPC

Проблема

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

Обзор решения

«Реплики» AccountsDB, которые запускаются отдельно от основного валидатора, могут использоваться для разгрузки запросов на сканирование учетных записей. Реплики будут только: запрашивать и извлекать обновления учетной записи из валидатора, обслуживать запросы RPC состояния учетной записи клиента и управлять очисткой + сжатием AccountsDb и AccountsBackgroundService.

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

При начальном запуске узла-реплики он загружает последний снимок из валидатора и создает из него банк и AccountsDb. После этого он запрашивает у своего основного валидатора новые слоты и просит валидатор отправить обновленные учетные записи для этого слота и обновить его собственный AccountsDb.

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

На стороне обслуживания клиентского RPC JsonRpcAccountsService отвечает за обслуживание клиентских вызовов RPC для информации, связанной с учетными записями, аналогичной существующей JsonRpcService.

Реплика также будет периодически делать моментальные снимки, чтобы ее можно было быстро запустить после перезапуска, если моментальный снимок не слишком старый.

Подробное решение

В следующих разделах содержится более подробная информация о конструкции.

Модель согласованности

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

Узел реплики Solana

Будет введен новый узел с именем solana-replica-node, основной обязанностью которого является поддержка реплики AccountsDb. Узел RPC или узел реплики используются в этом документе взаимозаменяемо. Это будет отдельный исполняемый файл от валидатора.

Реплика состоит из следующих основных компонентов:

ReplicaSlotConfirmationRequestor: эта служба отвечает за периодическую отправку запроса ReplicaSlotConfirmationRequest своему одноранговому валидатору или реплике для последних слотов. Он указывает последний слот (last_replicated_slot), для которого реплика уже получила информацию об учетных записях. Это поддерживает ReplWorkingSlotSet и управляет жизненным циклом BankForks, BlockCommitmentCache (для самого высокого подтвержденного слота) и оптимистически подтвержденного банка.

ReplicaSlotConfirmationServer: эта служба отвечает за обслуживание ReplicaSlotConfirmationRequest и отправляет ReplicaSlotConfirmationResponse обратно запрашивающей стороне. Ответ состоит из вектора новых слотов, о которых известно валидатору, которые позже, чем указанный last_replicated_slot. Этот сервис также работает в основном валидаторе. Этот сервис получает слоты для репликации от BankForks, BlockCommitmentCache и OpmiscallyConfirmBank.

ReplicaAccountsRequestor: эта служба отвечает за отправку запроса ReplicaAccountsRequest своему одноранговому валидатору или реплике для ReplicaAccountInfo для слота, для которого не была завершена репликация базы данных учетных записей. ReplicaAccountInfo содержит ReplicaAccountMeta, Hash и AccountData. ReplicaAccountMeta содержит информацию о существующей AccountMeta в дополнение к длине данных учетной записи в байтах.

«ReplicaAccountsServer»: эта служба отвечает за обслуживание «ReplicaAccountsRequest» и отправляет «ReplicaAccountsResponse» запрашивающей стороне. Ответ содержит счетчик ReplAccountInfo и вектор ReplAccountInfo. Эта служба работает как в валидаторе, так и в реплике, передающей информацию о репликации. Сервер может передавать информацию об учетной записи из своего AccountCache или из хранилища, если оно уже очищено. Это похоже на создание пакета моментальных снимков из AccountsDb с той разницей, что хранилище не нужно сбрасывать на диск перед потоковой передачей клиенту. Если данные учетной записи находятся в кеше, их можно передавать напрямую. Необходимо соблюдать осторожность, чтобы избежать очистки данных учетной записи для слота во время обслуживания потоковой передачи. При попытке репликации слота, если слот уже очищен с данными учетных записей, очищенными в результате обновления в более поздних корневых слотах, реплика должна отказаться от этого слота и попробовать более поздний неочищенный корневой слот.

Во время репликации нам также необходимо реплицировать информацию об учетных записях, которые были очищены из-за нулевых лампортов, т. е. мы должны иметь возможность определить разницу между учетной записью в данном слоте, которая не была обновлена ​​и, следовательно, не имеет записи в хранилище в этом слот, и тот, который содержит 0 лэмпортов и был очищен в истории. Мы можем записать это через какой-нибудь механизм "Tombstone" - запись удаленных мертвых учетных записей для слота. Сами надгробия могут быть удалены по истечении срока хранения, выраженного в эпохах. Любая попытка реплицировать слоты с удаленными надгробиями потерпит неудачу, и реплика должна пропустить этот слот и попробовать более поздние.

JsonRpcAccountsService: это служба RPC, обслуживающая клиентские запросы на информацию об учетной записи. Существующий JsonRpcService обслуживает другие клиентские вызовы, кроме AccountsDb. Узел реплики обслуживает только вызовы AccountsDb.

Существующему JsonRpcService требуются BankForks, OptimisticallyConfirmedBank и BlockCommitmentCache для загрузки банка. Службе JsonRpcAccountsService потребуется использовать информацию, полученную из ReplicaSlotConfirmationResponse, для создания AccountsDb.

AccountsBackgroundService: эта служба также работает в реплике, которая отвечает за периодическое создание моментальных снимков, сжатие AccountsDb и очистку учетных записей. Существующий код также использует BankForks, которые нам нужно сохранить в реплике.

Вопросы совместимости

Из соображений совместимости протокола все запросы имеют версию репликации, которая изначально установлена ​​​​на 1. В качестве альтернативы мы можем использовать версию валидатора. Сторона сервера RPC должна проверить версию запроса и завершиться ошибкой, если она не поддерживается.

Настройка репликации

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

Отказоустойчивость

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

Интерфейс

Ниже приведены клиентские API-интерфейсы RPC, поддерживаемые узлом реплики в JsonRpcAccountsService.

Следующие API не включены:

Пункты действий

  1. Создайте структуру реплики и исполняемый файл
  2. Интегрируйте код восстановления моментального снимка для начальной загрузки AccountsDb.
  3. Разработайте код интерфейса ReplicaSlotConfirmationRequestor и ReplicaSlotConfirmationServer.
  4. Разработайте подробные реализации ReplicaSlotConfirmationRequestor и ReplicaSlotConfirmationServer: управление жизненным циклом ReplEligibleSlotSet: добавление к нему новых корней и удаление корней. И интерфейсы, управляющие интерфейсом ReplWorkingSlotSet: добавление и удаление. Разработать компонент, синтезирующий информацию из BankForks, BlockCommitmentCache и OptimistcallyConfirmedBank на стороне сервера и поддерживающий информацию на стороне клиента.
  5. Разработайте код интерфейса для ReplicaAccountsRequestor и ReplicaAccountsServer.
  6. Разработайте подробную реализацию для ReplicaAccountsRequestor и ReplicaAccountsServer и разработайте сериализатор и десериализатор хранилища учетных записей репликации.
  7. Разработать код интерфейса JsonRpcAccountsService
  8. Подробная реализация JsonRpcAccountsService, код рефакторинга для совместного использования с частью JsonRpcService.
  9. Интеграция с AccountsBackgroundService в реплике для сжатия, очистки и моментальных снимков.
  10. Метрики и тестирование производительности