diff --git a/docs/clustering.md b/docs/clustering.md index 1c0c4a71db95b6f0f144ccb4d77ea082846c1be5..526cdb9dd94e405efbe3adf3b9738f7f980c4804 100644 --- a/docs/clustering.md +++ b/docs/clustering.md @@ -19,7 +19,7 @@ picodata run --instance-id iN --listen iN --peer i1 инÑтанÑов — одного обычно доÑтаточно, но Ð´Ð»Ñ Ð¿Ð¾Ð´Ñтраховки можно взÑÑ‚ÑŒ три. Именно на их оÑнове будет произведена Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ñтера и поиÑк вÑех работающих инÑтанÑов Ð´Ð»Ñ Ð¸Ñ… Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð² ÑоÑтав клаÑтера -(discovery). +(discovery). ПодробноÑти алгоритма discovery приведены в отдельном [документе](discovery.md). Ð’ контекÑте Ñборки клаÑтера важно лишь @@ -62,18 +62,19 @@ picodata run --instance-id iN --listen iN --peer i1 ### fn start_discover() -Дочерний процеÑÑ Ð½Ð°Ñ‡Ð¸Ð½Ð°ÐµÑ‚ Ñвое ÑущеÑтвование Ñ Ð·Ð°Ð¿ÑƒÑка Ð¼Ð¾Ð´ÑƒÐ»Ñ -`box.cfg()` и вызова функции `start_discover()`. Возможно, что при Ñтом -из БД будет ÑÑно, что bootstrap данного инÑтанÑа уже был произведен -ранее и что Raft уже знает о вхождении Ñтого инÑтанÑа в клаÑтер — в -таком Ñлучае никакого discovery не будет, инÑÑ‚Ð°Ð½Ñ Ñразу перейдет к Ñтапу -`postjoin()`. Ð’ противном Ñлучае, еÑли меÑто инÑтанÑа в клаÑтере еще не -извеÑтно, алгоритм discovery определÑет значение флага -`i_am_bootstrap_leader` и Ð°Ð´Ñ€ÐµÑ Ð»Ð¸Ð´ÐµÑ€Ð° Raft-группы. Далее инÑÑ‚Ð°Ð½Ñ -ÑбраÑывает Ñвое ÑоÑтоÑние (Ñтап rebootstrap), чтобы повторно провеÑти -инициализацию `box.cfg()`, теперь уже Ñ Ð¸Ð·Ð²ÐµÑтными параметрами. Сам -лидер (единÑтвенный Ñ `i_am_bootstrap_leader == true`) выполнÑет функцию -`start_boot()`. ОÑтальные инÑтанÑÑ‹ переходÑÑ‚ к функции `start_join()`. +Дочерний процеÑÑ Ð½Ð°Ñ‡Ð¸Ð½Ð°ÐµÑ‚ Ñвое ÑущеÑтвование Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ +[`init_common()`](#fn-init_common), в рамках которой в Ñ‚.ч. +инициализируетÑÑ Ð¼Ð¾Ð´ÑƒÐ»ÑŒ `box`. Возможно, что при Ñтом из БД будет ÑÑно, +что bootstrap данного инÑтанÑа уже был произведен ранее и что Raft уже +знает о вхождении Ñтого инÑтанÑа в клаÑтер — в таком Ñлучае никакого +discovery не будет, инÑÑ‚Ð°Ð½Ñ Ñразу перейдет к Ñтапу `postjoin()`. Ð’ +противном Ñлучае, еÑли меÑто инÑтанÑа в клаÑтере еще не извеÑтно, +алгоритм discovery определÑет значение флага `i_am_bootstrap_leader` и +Ð°Ð´Ñ€ÐµÑ Ð»Ð¸Ð´ÐµÑ€Ð° Raft-группы. Далее инÑÑ‚Ð°Ð½Ñ ÑбраÑывает Ñвое ÑоÑтоÑние (Ñтап +rebootstrap), чтобы повторно провеÑти инициализацию `box.cfg()`, теперь +уже Ñ Ð¸Ð·Ð²ÐµÑтными параметрами. Сам лидер (единÑтвенный Ñ +`i_am_bootstrap_leader == true`) выполнÑет функцию `start_boot()`. +ОÑтальные инÑтанÑÑ‹ переходÑÑ‚ к функции `start_join()`. ### fn start_boot() @@ -90,7 +91,7 @@ picodata run --instance-id iN --listen iN --peer i1 Вызову функции `start_join()` вÑегда предшеÑтвует rebootstrap (удаление БД и перезапуÑк процеÑÑа), поÑтому на данном Ñтапе в БД нет ни Ð¼Ð¾Ð´ÑƒÐ»Ñ -box, ни проÑтранÑтва хранениÑ. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ `start_join()` имеет проÑтое +`box`, ни проÑтранÑтва хранениÑ. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ `start_join()` имеет проÑтое уÑтройÑтво: ИнÑтанÑ-клиент отправлÑет Ð·Ð°Ð¿Ñ€Ð¾Ñ `raft_join` лидеру Raft-группы (он @@ -99,14 +100,12 @@ box, ни проÑтранÑтва хранениÑ. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ `start_join( - Идентификатор `raft_id` и данные таблицы `raft_group` — Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ Raft-узла; - Идентификаторы `instance_uuid`, `replicaset_uuid` и параметры - `replication`, `read_only` Ð´Ð»Ñ `box.cfg`. + `replication`, `read_only` — Ð´Ð»Ñ Ð¿ÐµÑ€Ð²Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ вызова `box.cfg()`. -Получив вÑе наÑтройки, инÑÑ‚Ð°Ð½Ñ Ð¸Ñпользует их в `box.cfg()`, и затем -Ñоздает в БД группу `raft_group` Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ð¼Ð¸ адреÑами других -инÑтанÑов. Без Ñтого инÑÑ‚Ð°Ð½Ñ Ð½Ðµ Ñможет отвечать на ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ других -членов Raft-группы. Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы запиÑи в `raft_group` не были -заменены на менее актуальные из журнала Raft, ÐºÐ°Ð¶Ð´Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ маркируетÑÑ -значением `commit_index`. +Получив вÑе наÑтройки, инÑÑ‚Ð°Ð½Ñ Ð¸Ñпользует их в `box.cfg()` (Ñм. +[`init_common()`](#fn-init_common)), и затем Ñоздает в БД группу +`raft_group` Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ð¼Ð¸ адреÑами других инÑтанÑов. Без Ñтого инÑÑ‚Ð°Ð½Ñ +не Ñможет отвечать на ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ других членов Raft-группы. По завершении Ñтих манипулÑций инÑÑ‚Ð°Ð½Ñ Ñ‚Ð°ÐºÐ¶Ðµ переходит к Ñтапу `postjoin()`. @@ -120,8 +119,7 @@ box, ни проÑтранÑтва хранениÑ. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ `start_join( Raft-группой. Ð’ Ñлучае, еÑли других кандидатов нет, инÑÑ‚Ð°Ð½Ñ Ñ‚ÑƒÑ‚ же избирает ÑÐµÐ±Ñ Ð»Ð¸Ð´ÐµÑ€Ð¾Ð¼ группы. - -Ð’ Ñтом меÑте также уÑтанавливаетÑÑ `on_shutdown` callback, который +Ð’ Ñтом меÑте также уÑтанавливаетÑÑ `on_shutdown` триггер, который обеÑпечит [корректное завершение работы инÑтанÑа](#Graceful-shutdown). Следующим шагом инÑÑ‚Ð°Ð½Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰Ð°ÐµÑ‚ клаÑтер о том, что он готов проходить наÑтройку необходимых подÑиÑтем (репликации, шардинга, и Ñ‚.д.). Ð”Ð»Ñ @@ -133,6 +131,30 @@ governor](#Topology-governor), также называемый `governor_loop`. Как только запиÑÑŒ Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ‹Ð¼ грейдом будет зафикÑирована в Raft, узел готов к иÑпользованию. +### fn init_common() + +Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ `init_common` обобщает дейÑтвиÑ, необходимые Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ +инÑтанÑа во вÑех трех вышеопиÑанных ÑценариÑÑ… — `start_discover`, +`start_boot`, `start_join`. + +Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¸Ð½ÑтанÑа ÑводитÑÑ Ðº Ñледующим шагам: + +- Ñоздание `data_dir`, +- первичный вызов `box.cfg`, +- Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ `package.preload.vshard`, +- Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð¼Ð¾Ðº (`box.schema.func.create`), +- Ñоздание ÑиÑтемных ÑпейÑов (`_picodata_raft_log` и Ñ‚.д). + +Параметры первичного вызова `box.cfg` завиÑÑÑ‚ от конкретного ÑценариÑ: + +| param | `start_discover` | `start_boot` | `start_join` | +|-------------|------------------|--------------|-------------------------------| +| listen | None | None | _from args_ | +| read_only | false | false | from `rpc::join` response | +| uuids | _random_ | _given_ | from `rpc::join` response | +| replication | None | None | from `rpc::join` response | +| data_dir | _from args_ | ... | ... | +| log_level | _from args_ | ... | ... | ## Обработка запроÑов @@ -229,7 +251,7 @@ struct Instance { `Applied`. Важно помнить, что обновление ÑтатуÑа и Ñама Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ выполнÑÑ‚ÑŒÑÑ Ð½Ðµ атомарно (еÑли в `Op::on_commit()` проиÑходит передача ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¼Ñƒ потоку — yield). Ð’ таком Ñлучае, Ñледует - позаботитьÑÑ Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ об идемпотентноÑти операции. + позаботитьÑÑ Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ об идемпотентноÑти операции. Схема ниже иллюÑтрирует Ñту информацию. diff --git a/src/main.rs b/src/main.rs index d2927466ce2948655e26670220e6ad431ac4f94f..b4e1e7267639a554040441c7dadd392d5bd10e4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -772,6 +772,14 @@ fn main_run(args: args::Run) -> ! { } } +/// Performs tarantool initialization calling `box.cfg` for the first time. +/// +/// This function is called from: +/// +/// - `start_discover` +/// - `start_boot` +/// - `start_join` +/// fn init_common(args: &args::Run, cfg: &tarantool::Cfg) -> (Clusterwide, RaftSpaceAccess) { std::fs::create_dir_all(&args.data_dir).unwrap(); tarantool::set_cfg(cfg);