From c63ef1c6e32226438b3398fec50bfba288fabb4a Mon Sep 17 00:00:00 2001 From: "a.tolstoy" <a.tolstoy@picodata.io> Date: Wed, 1 Nov 2023 16:53:06 +0300 Subject: [PATCH] clustering.md: fix lists, links, formatting --- docs/architecture/clustering.md | 104 ++++++++++++++++---------------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/docs/architecture/clustering.md b/docs/architecture/clustering.md index 1786d6f9..c8554388 100644 --- a/docs/architecture/clustering.md +++ b/docs/architecture/clustering.md @@ -25,12 +25,12 @@ picodata run --instance-id iN --listen iN --peer i1 [документе](discovery.md). Ð’ контекÑте Ñборки клаÑтера важно лишь понимать, что Ñтот алгоритм позволÑет не более чем одному инÑтанÑу (peer'у) Ñоздать raft-группу, -Ñ‚.е. Ñтать инÑтанÑом Ñ raft_id=1. ЕÑли таких инÑтанÑов будет неÑколько, +Ñ‚.е. Ñтать инÑтанÑом Ñ `raft_id=1`. ЕÑли таких инÑтанÑов будет неÑколько, то и raft-групп, а Ñледовательно и клаÑтеров Picodata получитÑÑ Ð½ÐµÑколько. -Топологией raft-группы управлÑет алгоритм Raft, реализованный в виде -крейта `raft-rs`. +Топологией raft-группы управлÑет алгоритм Raft, реализованный в виде крейта +[raft-rs](https://doc.rust-lang.org/rust-by-example/crates.html){:target="_blank"}. ## Ðтапы инициализации клаÑтера {: #cluster-bootstrap-stages } Ðа Ñхеме ниже показаны Ñтапы жизненного цикла инÑтанÑа в контекÑте его @@ -64,11 +64,11 @@ picodata run --instance-id iN --listen iN --peer i1 Выполнение дочернего процеÑÑа начинаетÑÑ Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° функции [`start_discover()`](#fn-start_discover) и далее Ñледует алгоритму. При необходимоÑти дочерний процеÑÑ Ð¼Ð¾Ð¶ÐµÑ‚ попроÑить Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»Ñ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ вÑе -файлы БД (Ñм. раздел ["РебутÑтрап"](#РебутÑтрап)). Ðто иÑпользуетÑÑ Ð´Ð»Ñ +файлы БД (Ñм. раздел [РебутÑтрап](#rebootstrap)). Ðто иÑпользуетÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð¹ инициализации инÑтанÑа Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ñ‹Ð¼ `replicaset_uuid` вмеÑто рандомного. -### РебутÑтрап {: #revootsrap } +### РебутÑтрап {: #rebootstrap } Ð’ СУБД Tarantool имеютÑÑ Ð´Ð²Ðµ оÑобенноÑти, из-за которых процеÑÑ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ выглÑдит Ñледующим образом: @@ -79,11 +79,11 @@ picodata run --instance-id iN --listen iN --peer i1 2. Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñервера iproto, реализующего бинарный Ñетевой протокол Tarantool, выполнÑетÑÑ Ñ‚Ð¾Ð¹ же функцией `box.cfg()`. -Ð’ ÑовокупноÑти Ñти две оÑобенноÑти Ñоздают проблему курицы и Ñйца: +Ð’ ÑовокупноÑти Ñти две оÑобенноÑти Ñоздают проблему "курицы и Ñйца": -- ИнÑÑ‚Ð°Ð½Ñ Ð½Ðµ может общатьÑÑ Ð¿Ð¾ Ñети, пока не узнает принадлежноÑть - репликаÑету. -- ПринадлежноÑть репликаÑету невозможно узнать без Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñети. +- инÑÑ‚Ð°Ð½Ñ Ð½Ðµ может общатьÑÑ Ð¿Ð¾ Ñети, пока не узнает принадлежноÑть + репликаÑету; +- принадлежноÑть репликаÑету невозможно узнать без Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñети. Чтобы Ñту проблему решить, Picodata инициализируетÑÑ Ñо Ñлучайно Ñгенерированными идентификаторами, а позже перезапуÑкает процеÑÑ, @@ -100,7 +100,7 @@ discovery не будет, инÑÑ‚Ð°Ð½Ñ Ñразу перейдет к Ñта противном Ñлучае, еÑли меÑто инÑтанÑа в клаÑтере еще не извеÑтно, алгоритм discovery определÑет значение флага `i_am_bootstrap_leader` и Ð°Ð´Ñ€ÐµÑ Ð»Ð¸Ð´ÐµÑ€Ð° raft-группы. Далее инÑÑ‚Ð°Ð½Ñ ÑбраÑывает Ñвое ÑоÑтоÑние (Ñм. -["РебутÑтрап"](#РебутÑтрап)), чтобы повторно провеÑти инициализацию +[РебутÑтрап](#rebootstrap)), чтобы повторно провеÑти инициализацию `box.cfg()`, теперь уже Ñ Ð¸Ð·Ð²ÐµÑтными параметрами. Сам лидер (единÑтвенный Ñ `i_am_bootstrap_leader == true`) выполнÑет функцию `start_boot()`. ОÑтальные инÑтанÑÑ‹ переходÑÑ‚ к функции `start_join()`. @@ -119,7 +119,7 @@ discovery не будет, инÑÑ‚Ð°Ð½Ñ Ñразу перейдет к Ñта ### fn start_join() Вызову функции `start_join()` вÑегда предшеÑтвует -[ребутÑтрап](#РебутÑтрап) (удаление вÑех данных и перезапуÑк процеÑÑа), +[ребутÑтрап](#rebootstrap) (удаление вÑех данных и перезапуÑк процеÑÑа), поÑтому на данном Ñтапе в БД нет ни Ð¼Ð¾Ð´ÑƒÐ»Ñ `box`, ни проÑтранÑтва хранениÑ. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ `start_join()` имеет проÑтое уÑтройÑтво: @@ -128,7 +128,8 @@ discovery не будет, инÑÑ‚Ð°Ð½Ñ Ñразу перейдет к Ñта Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ информацию: Ð”Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ raft-узла: -- идентификатор `raft_id`, + +- идентификатор `raft_id`; - данные таблицы `_picodata_peer_address`. Ð”Ð»Ñ Ð¿ÐµÑ€Ð²Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ вызова `box.cfg()`: @@ -152,24 +153,20 @@ raft-группы. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ `postjoin()` выполнÑет Ñледующие дейÑтвиÑ: -- Инициализирует HTTP-Ñервер в ÑоответÑтвии Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð¼ `--http-listen`. - -- ЗапуÑкает Lua-Ñкрипт, указанный в аргументе `--script`. - -- Инициализирует узел Raft, который начинает взаимодейÑтвовать Ñ - raft-группой. - -- Ð’ Ñлучае, еÑли других кандидатов нет, инÑÑ‚Ð°Ð½Ñ Ñ‚ÑƒÑ‚ же - избирает ÑÐµÐ±Ñ Ð»Ð¸Ð´ÐµÑ€Ð¾Ð¼ группы. - -- УÑтанавливает триггер `on_shutdown`, который обеÑпечит - [корректное завершение работы инÑтанÑа](#Graceful-shutdown). +- инициализирует HTTP-Ñервер в ÑоответÑтвии Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð¼ `--http-listen`. +- запуÑкает Lua-Ñкрипт, указанный в аргументе `--script`; +- инициализирует узел Raft, который начинает взаимодейÑтвовать Ñ + raft-группой; +- в Ñлучае, еÑли других кандидатов нет, инÑÑ‚Ð°Ð½Ñ Ñ‚ÑƒÑ‚ же + избирает ÑÐµÐ±Ñ Ð»Ð¸Ð´ÐµÑ€Ð¾Ð¼ группы; +- уÑтанавливает триггер `on_shutdown`, который обеÑпечит + [корректное завершение работы инÑтанÑа](#graceful-shutdown). ПоÑледним шагом инÑÑ‚Ð°Ð½Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰Ð°ÐµÑ‚ клаÑтер о том, что он готов проходить наÑтройку необходимых подÑиÑтем (репликации, шардинга, и Ñ‚.д.). Ð”Ð»Ñ Ñтого лидеру отправлÑетÑÑ Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° обновление `target_grade` текущего инÑтанÑа до ÑƒÑ€Ð¾Ð²Ð½Ñ `Online`, поÑле чего за дальнейшие дейÑÑ‚Ð²Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ -отвечать Ñпециальный поток ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ [topology governor](#Topology-governor). +отвечать Ñпециальный поток ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ [topology governor](#topology-governor). Как только запиÑÑŒ Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ‹Ð¼ грейдом будет зафикÑирована в Raft, узел готов к иÑпользованию. @@ -180,12 +177,12 @@ raft-группы. инÑтанÑа во вÑех трех вышеопиÑанных ÑценариÑÑ… — `start_discover`, `start_boot`, `start_join`. -Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¸Ð½ÑтанÑа ÑводитÑÑ Ðº Ñледующим шагам: +Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¸Ð½ÑтанÑа подразумевает Ñледующие шаги: -- Ñоздание `data_dir`, -- первичный вызов `box.cfg`, -- Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ `package.preload.vshard`, -- Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð¼Ñ‹Ñ… процедур (`box.schema.func.create`), +- Ñоздание `data_dir`; +- первичный вызов `box.cfg`; +- Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ `package.preload.vshard`; +- Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð¼Ñ‹Ñ… процедур (`box.schema.func.create`); - Ñоздание ÑиÑтемных таблиц (`_picodata_raft_log` и Ñ‚.д). Параметры первичного вызова `box.cfg` завиÑÑÑ‚ от конкретного ÑценариÑ: @@ -252,17 +249,17 @@ struct Instance { Цель такого запроÑа ÑводитÑÑ Ðº добавлению нового инÑтанÑа в raft-группу. Ð”Ð»Ñ Ñтого алгоритма Ñправедливы Ñледующие тезиÑÑ‹: -- Ð—Ð°Ð¿Ñ€Ð¾Ñ `rpc::join` вÑегда делает инÑÑ‚Ð°Ð½Ñ Ð±ÐµÐ· Ñнапшотов. -- Ð’ процеÑÑе обработки запроÑа в raft-журнал добавлÑетÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ +- Ð·Ð°Ð¿Ñ€Ð¾Ñ `rpc::join` вÑегда делает инÑÑ‚Ð°Ð½Ñ Ð±ÐµÐ· Ñнапшотов; +- в процеÑÑе обработки запроÑа в raft-журнал добавлÑетÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ `op::PersistPeer { peer }`, при Ñтом `current_grade: Offline`, `target_grade: Offline` (подробнее о них в разделе [topology - governor](#Topology-governor)). -- Ð’ ответ выдаетÑÑ Ð²Ñегда новый `raft_id`, никому другому ранее не - принадлежавший. -- Помимо идентификаторов нового инÑтанÑа, ответ Ñодержит ÑпиÑок + governor](#topology-governor)); +- в ответ выдаетÑÑ Ð²Ñегда новый `raft_id`, никому другому ранее не + принадлежавший; +- помимо идентификаторов нового инÑтанÑа, ответ Ñодержит ÑпиÑок голоÑующих членов raft-группы. Они необходимы новому инÑтанÑу Ð´Ð»Ñ - того чтобы отвечать на запроÑÑ‹ от raft-лидера. -- Также ответ Ñодержит параметр `box_replication`, который требуетÑÑ Ð´Ð»Ñ + того чтобы отвечать на запроÑÑ‹ от raft-лидера; +- также ответ Ñодержит параметр `box_replication`, который требуетÑÑ Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð¹ наÑтройки репликации. ## Graceful shutdown @@ -270,9 +267,9 @@ struct Instance { Чтобы выключение прошло штатно и не имело негативных поÑледÑтвий, необходимо Ñледить за Ñоблюдением Ñледующих уÑловий: -- ИнÑÑ‚Ð°Ð½Ñ Ð½Ðµ должен оÑтаватьÑÑ Ð³Ð¾Ð»Ð¾Ñующим, пока еÑть другие кандидаты в - ÑоÑтоÑнии `Online`. -- ИнÑÑ‚Ð°Ð½Ñ Ð½Ðµ должен оÑтаватьÑÑ Ð»Ð¸Ð´ÐµÑ€Ð¾Ð¼. +- инÑÑ‚Ð°Ð½Ñ Ð½Ðµ должен оÑтаватьÑÑ Ð³Ð¾Ð»Ð¾Ñующим, пока еÑть другие кандидаты в + ÑоÑтоÑнии `Online`; +- инÑÑ‚Ð°Ð½Ñ Ð½Ðµ должен оÑтаватьÑÑ Ð»Ð¸Ð´ÐµÑ€Ð¾Ð¼. Чтобы Ñтого добитьÑÑ, каждый инÑÑ‚Ð°Ð½Ñ Ð¿Ñ€Ð¸ Ñрабатывании триггера `on_shutdown` отправлÑет лидеру Ð·Ð°Ð¿Ñ€Ð¾Ñ `UpdatePeerRequest { @@ -316,7 +313,6 @@ Cartridge) Picodata не иÑпользует понÑтие "ÑоÑтоÑÐ½Ð¸Ñ ÐºÐ°ÐºÐ¾Ð¹-то период времени, поÑле чего их необходимо Ñнова привеÑти в актуальное ÑоÑтоÑние. - Ðа оÑнове ÑовокупноÑти грейдов и их инкарнаций `governor_loop` на каждой итерации беÑконечного цикла генерирует активноÑти (activity) и пытаетÑÑ Ð¸Ñ… организовать. Пока не организует, никаких других изменений в текущих @@ -324,12 +320,13 @@ Cartridge) Picodata не иÑпользует понÑтие "ÑоÑтоÑÐ½Ð¸Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐ°Ñ‚ÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹, то на Ñледующей итерации они будут перевычиÑлены Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ новых целей. -Инкарнации грейдов вычиÑлÑÑŽÑ‚ÑÑ Ð¿Ð¾ Ñледующему принципу. -- Каждый раз когда `target_grade` инÑтанÑа получает значение `Online`, - его Ð¸Ð½ÐºÐ°Ñ€Ð½Ð°Ñ†Ð¸Ñ ÑƒÐ²ÐµÐ»Ð¸Ñ‡Ð¸Ð²Ð°ÐµÑ‚ÑÑ Ð½Ð° 1. -- Ð’Ñе оÑтальные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð³Ñ€ÐµÐ¹Ð´Ð¾Ð² копируют инкарнацию Ñ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð¾Ð¿Ð¾Ð»Ð¾Ð¶Ð½Ð¾Ð³Ð¾ - грейда, то еÑть при изменении `target_grade` Ð¸Ð½ÐºÐ°Ñ€Ð½Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¿Ð¸Ñ€ÑƒÐµÑ‚ÑÑ Ñ - `current_grade`, при изменении `current_grade` — Ñ `target_grade`. +Инкарнации грейдов вычиÑлÑÑŽÑ‚ÑÑ Ð¿Ð¾ Ñледующему принципу: + +- каждый раз когда `target_grade` инÑтанÑа получает значение `Online`, + его Ð¸Ð½ÐºÐ°Ñ€Ð½Ð°Ñ†Ð¸Ñ ÑƒÐ²ÐµÐ»Ð¸Ñ‡Ð¸Ð²Ð°ÐµÑ‚ÑÑ Ð½Ð° 1; +- вÑе оÑтальные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð³Ñ€ÐµÐ¹Ð´Ð¾Ð² копируют инкарнацию Ñ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð¾Ð¿Ð¾Ð»Ð¾Ð¶Ð½Ð¾Ð³Ð¾ + грейда, то еÑть при изменении `target_grade` Ð¸Ð½ÐºÐ°Ñ€Ð½Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¿Ð¸Ñ€ÑƒÐµÑ‚ÑÑ Ñ + `current_grade`, при изменении `current_grade` — Ñ `target_grade`. Дальше перечиÑлены активноÑти, которыми занимаетÑÑ `governor_loop`, в том же порÑдке, в котором он к ним приÑтупает. @@ -347,13 +344,14 @@ Cartridge) Picodata не иÑпользует понÑтие "ÑоÑтоÑÐ½Ð¸Ñ ÐŸÑ€Ð°Ð²Ð¸Ð»Ð° выбора новой конфигурации опиÑаны в `picodata::governor::cc::raft_conf_change` и заключаютÑÑ Ð² Ñледующем: -- Любые инÑтанÑÑ‹, переходÑщие в грейд `Expelled`, удалÑÑŽÑ‚ÑÑ Ð¸Ð· + +- любые инÑтанÑÑ‹, переходÑщие в грейд `Expelled`, удалÑÑŽÑ‚ÑÑ Ð¸Ð· raft-группы; -- ГолоÑующие инÑтанÑÑ‹, переходÑщие в грейд `Offline`, переÑтают быть +- голоÑующие инÑтанÑÑ‹, переходÑщие в грейд `Offline`, переÑтают быть голоÑующими (ÑтановÑÑ‚ÑÑ `learners`) и Ð´Ð»Ñ Ð½Ð¸Ñ… находитÑÑ Ð·Ð°Ð¼ÐµÐ½Ð°; -- Среди Ñвежедобавленных инÑтанÑов Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ грейдом `Online` - подбираетÑÑ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð¾Ðµ количеÑтво голоÑующих инÑтанÑов (`voters`), - оÑтальные добавлÑÑŽÑ‚ÑÑ ÐºÐ°Ðº `learners`; +- Ñреди Ñвежедобавленных инÑтанÑов Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ грейдом `Online` + подбираетÑÑ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð¾Ðµ количеÑтво голоÑующих инÑтанÑов (`voters`), + оÑтальные добавлÑÑŽÑ‚ÑÑ ÐºÐ°Ðº `learners`. <!-- [TODO](#ПредÑтоит Ñделать) Ðовые воутеры должны выбиратьÑÑ Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ failure domain'ов. --> -- GitLab