-
Notifications
You must be signed in to change notification settings - Fork 21
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
base: main
Are you sure you want to change the base?
Conversation
337fead
to
3b25a22
Compare
d66de58
to
2fb319a
Compare
|
||
There wiil be 3 new entities: | ||
1) `IncompleteMirrorRWModeController` | ||
2) `AgentAvailabilityWaiter` |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
вот это стоит раскрыть подробнее - например, написать, что мы не будем тут поддерживать персистентный список номеров блоков, не записанных в какие-то из реплик (мы же недописанные блоки только в памяти будем держать?)
также что конкретно мы будем ресинкать при рестарте вольюма - весь вольюм или же девайсы с агентов, которые у нас были признаны временно недоступными?
я не понимаю, почему ты тут хочешь мапу использовать
кажется, прямолинейнее держать deque диапазонов блоков, которые надо отреплицировать
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
мы же недописанные блоки только в памяти будем держать?
Да.
также что конкретно мы будем ресинкать при рестарте вольюма - весь вольюм или же девайсы с агентов, которые у нас были признаны временно недоступными?
Только остающих агентов.
я не понимаю, почему ты тут хочешь мапу использовать
кажется, прямолинейнее держать deque диапазонов блоков, которые надо отреплицировать
Мапа потому что, во-первых, с ней работает TNonreplicatedPartitionMigrationCommonActor
, а во-вторых, мапа кажется логичнее, т.к. допускаю что многие клиенты могут быстро писать в один и тот же блок.
2fb319a
to
3d54eb7
Compare
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не до конца понял, что конкретно ты имеешь в виду, но вообще если актуализировать реплику, куда мы по итогам этой фичи что-то недописали, просто через resync, возможна следующая проблема:
- принимаем решение, что реплика r1 временно недоступна, и перестаем слать в нее записи
- приходит запись, отправляем ее в r2 и r3, получаем от них S_OK, подтверждаем запись клиенту
- r3 ломается, девайсы в ней заменяются, volume рестартует
- r1 становится снова доступной
- volume рестартует, запускает resync, resync накатывает значение из r1 в реплики r2 и r3, но значение в r1 устарело, т.к. в пункте 2 мы запись в r1 не отправляли
В общем, на самом деле после рестарта volume в случае, если у нас какая-то реплика была временно недоступна до рестарта, мы должны запускать не совсем resync, а процесс, который ближе к репликации на самом деле. Нам надо не одну какую-то версию во все реплики накатить, а накатить в реплику r1 версию из одной из двух других реплик (в данном случае - накатить версию из r2, потому что в r3 теперь fresh-девайсы). Отличие от репликации fresh-девайсов в том, что мы ожидаем, что подавляющее большинство блоков не надо будет копировать, т.к. за единицы секунд мы вряд ли успеем накопить много блоков, не доехавших до r1. Но по смыслу это как будто все-таки репликация.
То есть смысл данной фичи в следующем. Мы хотим быстрее обнаруживать поломки девайсов и агентов. Для этого мы вводим второй (уменьшенный) таймаут, по истечении которого на самом деле признаем реплику (или ее часть) недоступной на стороне вольюма и перестаем в нее зеркалировать write-запросы. Но накапливаем в памяти историю недозаписанных блоков - это на случай, если реплика вдруг быстро оживет (если проблема на самом деле не в сторадж-ноде (девайс / агент), а в сетевом флапе). И если реплика быстро оживает, мы синкаем в нее не все блоки, а только те, которые мы в реплику недописали. Но в случае рестарта вольюма мы теряем информацию о том, что мы недописали, и вынуждены вести себя так, как будто нам надо эту реплику полностью переналить из других реплик (то есть говорим про репликацию по типу той, которая делается для fresh-девайсов).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не до конца понял, что конкретно ты имеешь в виду, но вообще если актуализировать реплику, куда мы по итогам этой фичи что-то недописали, просто через resync, возможна следующая проблема:
Я имею ввиду ситуацию:
- Отвалилась r1
- Клиент хочет записать блок
- Запись отправляется в r2, но не успевает в r3, т.к. сервис рестатанул.
Теперь если запустить обычный resync, то во всех трёх репликах будут разные блоки и resync просто зависнет.
Фиксить я это буду скорее всего чуть переделав алгоритм resync, который не будет доверять данным из реплики, которая отставала.
Но в случае рестарта вольюма мы теряем информацию о том, что мы недописали, и вынуждены вести себя так, как будто нам надо эту реплику полностью переналить из других реплик (то есть говорим про репликацию по типу той, которая делается для fresh-девайсов).
Запускать полноценную миграцию мне меньше хочется, т.к. resync всё же быстрее, учитывая что не так много блоков будет записано.
There was a problem hiding this comment.
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. Репликация может тоже проверять чексуммы сначала. Это для репликации и миграции самих по себе будет полезно, даже без этой фичи, т.к. часть данных - это нули, которые нет смысла реплицировать.
Related to #3
https://github.com/ydb-platform/nbs/blob/users/komarevtsev-d/issue-3/doc-proposal/0/doc/blockstore/storage/dynamic_io_mirroring_proposal.md