Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic IO mirroring in mirror disks proposal #1910

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

komarevtsev-d
Copy link
Collaborator

@komarevtsev-d komarevtsev-d commented Aug 30, 2024

drbasic
drbasic previously approved these changes Aug 31, 2024

There wiil be 3 new entities:
1) `IncompleteMirrorRWModeController`
2) `AgentAvailabilityWaiter`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

что-то мне словарь для слова waiter предлагает только вариант "официант"
думаю, лучше назвать как-то типа AgentAvailabilityMonitor


`SmartMigrationActor` is an actor that migrates dirty block map (collected by `IncompleteMirrorRWModeController`) from 2 available agents to the lagging one. It inherits from `TNonreplicatedPartitionMigrationCommonActor` since it already has most of the necessary functionality:
- Copies from one actor to the other
- Does copying by blocks map
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

вот это стоит раскрыть подробнее - например, написать, что мы не будем тут поддерживать персистентный список номеров блоков, не записанных в какие-то из реплик (мы же недописанные блоки только в памяти будем держать?)

также что конкретно мы будем ресинкать при рестарте вольюма - весь вольюм или же девайсы с агентов, которые у нас были признаны временно недоступными?

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

мы же недописанные блоки только в памяти будем держать?

Да.

также что конкретно мы будем ресинкать при рестарте вольюма - весь вольюм или же девайсы с агентов, которые у нас были признаны временно недоступными?

Только остающих агентов.

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

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

@komarevtsev-d komarevtsev-d force-pushed the users/komarevtsev-d/issue-3/doc-proposal/0 branch from 2fb319a to 3d54eb7 Compare September 10, 2024 08:40
There can be 0-1 instances of `IncompleteMirrorRWModeController` per `NonreplicatedPartition`. The presence of the `IncompleteMirrorRWModeController` indicates that the replica has agents that lag behind. `IncompleteMirrorRWModeController` manages the lifetimes of `AgentAvailabilityMonitor` and `SmartMigrationActor` entities.

Since the dirty block map will not be stored persistently, we must handle lagging replica on restart of a partition, volume, or a whole service. In this case, the basic resync is started, but with a small difference that only devices of lagging agents will be processed.
There is one caveat, though: mirror-3 disks can now store different data in the same block across all three replicas. The lagging replica - the oldest data and the other two can differ because a write blocks request was sent to only one replica before the restart. That is not a problem because write confirmation was not sent to a client, but it is something that the current resync algorithm is not ready for.
Copy link
Collaborator

@qkrorlqr qkrorlqr Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не до конца понял, что конкретно ты имеешь в виду, но вообще если актуализировать реплику, куда мы по итогам этой фичи что-то недописали, просто через resync, возможна следующая проблема:

  1. принимаем решение, что реплика r1 временно недоступна, и перестаем слать в нее записи
  2. приходит запись, отправляем ее в r2 и r3, получаем от них S_OK, подтверждаем запись клиенту
  3. r3 ломается, девайсы в ней заменяются, volume рестартует
  4. r1 становится снова доступной
  5. volume рестартует, запускает resync, resync накатывает значение из r1 в реплики r2 и r3, но значение в r1 устарело, т.к. в пункте 2 мы запись в r1 не отправляли

В общем, на самом деле после рестарта volume в случае, если у нас какая-то реплика была временно недоступна до рестарта, мы должны запускать не совсем resync, а процесс, который ближе к репликации на самом деле. Нам надо не одну какую-то версию во все реплики накатить, а накатить в реплику r1 версию из одной из двух других реплик (в данном случае - накатить версию из r2, потому что в r3 теперь fresh-девайсы). Отличие от репликации fresh-девайсов в том, что мы ожидаем, что подавляющее большинство блоков не надо будет копировать, т.к. за единицы секунд мы вряд ли успеем накопить много блоков, не доехавших до r1. Но по смыслу это как будто все-таки репликация.

То есть смысл данной фичи в следующем. Мы хотим быстрее обнаруживать поломки девайсов и агентов. Для этого мы вводим второй (уменьшенный) таймаут, по истечении которого на самом деле признаем реплику (или ее часть) недоступной на стороне вольюма и перестаем в нее зеркалировать write-запросы. Но накапливаем в памяти историю недозаписанных блоков - это на случай, если реплика вдруг быстро оживет (если проблема на самом деле не в сторадж-ноде (девайс / агент), а в сетевом флапе). И если реплика быстро оживает, мы синкаем в нее не все блоки, а только те, которые мы в реплику недописали. Но в случае рестарта вольюма мы теряем информацию о том, что мы недописали, и вынуждены вести себя так, как будто нам надо эту реплику полностью переналить из других реплик (то есть говорим про репликацию по типу той, которая делается для fresh-девайсов).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не до конца понял, что конкретно ты имеешь в виду, но вообще если актуализировать реплику, куда мы по итогам этой фичи что-то недописали, просто через resync, возможна следующая проблема:

Я имею ввиду ситуацию:

  1. Отвалилась r1
  2. Клиент хочет записать блок
  3. Запись отправляется в r2, но не успевает в r3, т.к. сервис рестатанул.

Теперь если запустить обычный resync, то во всех трёх репликах будут разные блоки и resync просто зависнет.
Фиксить я это буду скорее всего чуть переделав алгоритм resync, который не будет доверять данным из реплики, которая отставала.

Но в случае рестарта вольюма мы теряем информацию о том, что мы недописали, и вынуждены вести себя так, как будто нам надо эту реплику полностью переналить из других реплик (то есть говорим про репликацию по типу той, которая делается для fresh-девайсов).

Запускать полноценную миграцию мне меньше хочется, т.к. resync всё же быстрее, учитывая что не так много блоков будет записано.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Теперь если запустить обычный resync, то во всех трёх репликах будут разные блоки и resync просто зависнет.

Почему зависнет?

void TResyncRangeActor::CompareChecksums(const TActorContext& ctx)
- просто выберет первую попавшуюся

Запускать полноценную миграцию мне меньше хочется, т.к. resync всё же быстрее, учитывая что не так много блоков будет записано.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants