Балансировка нагрузки включена по умолчанию для любой распределённой таблицы, которая использует зеркалирование. По умолчанию запросы распределяются случайным образом между зеркалами. Вы можете изменить это поведение, используя ha_strategy.
ha_strategy = {random|nodeads|noerrors|roundrobin}
Стратегия выбора зеркала для балансировки нагрузки является необязательной и по умолчанию установлена в random.
Стратегия, используемая для выбора зеркала, или, другими словами, выбора конкретного агентского зеркала в распределённой таблице, контролируется этой директивой. По сути, эта директива управляет тем, как мастер выполняет балансировку нагрузки между настроенными агентскими узлами зеркал. Реализованы следующие стратегии:
Режим балансировки по умолчанию — простое линейное случайное распределение между зеркалами. Это означает, что каждому зеркалу назначаются равные вероятности выбора. Это похоже на круговой обход (round-robin, RR), но не накладывает строгий порядок выбора.
- Example
ha_strategy = randomПростая стратегия случайного выбора по умолчанию не учитывает состояние зеркал, уровень ошибок и, что самое важное, фактические задержки отклика. Чтобы справиться с неоднородными кластерами и временными пиками нагрузки на агентские узлы, существует группа стратегий балансировки, которые динамически корректируют вероятности на основе фактических задержек запросов, наблюдаемых мастером.
Адаптивные стратегии, основанные на вероятностях, взвешенных по задержкам, работают следующим образом:
- Статистика задержек накапливается блоками по ha_period_karma секунд.
- Вероятности, взвешенные по задержкам, пересчитываются один раз за период karma.
- Флаг "живой или мёртвый" корректируется один раз за запрос, включая ping-запросы.
Изначально вероятности равны. На каждом шаге они масштабируются обратно пропорционально задержкам, наблюдаемым за последний период karma, а затем нормализуются. Например, если в первые 60 секунд после запуска мастера 4 зеркала имели задержки 10 мс, 5 мс, 30 мс и 3 мс соответственно, первый шаг корректировки будет следующим:
- Начальные проценты: 0.25, 0.25, 0.25, 0.25.
- Наблюдаемые задержки: 10 мс, 5 мс, 30 мс, 3 мс.
- Обратные задержки: 0.1, 0.2, 0.0333, 0.333.
- Масштабированные проценты: 0.025, 0.05, 0.008333, 0.0833.
- Нормализованные проценты: 0.15, 0.30, 0.05, 0.50.
Это означает, что первое зеркало будет выбрано с вероятностью 15% в течение следующего периода karma, второе — с вероятностью 30%, третье (самое медленное с 30 мс) — только с 5%, а четвёртое и самое быстрое (3 мс) — с 50%. После этого периода второй шаг корректировки снова обновит эти вероятности и так далее.
Идея в том, что как только наблюдаемые задержки стабилизируются, вероятности, взвешенные по задержкам, также стабилизируются. Все эти итерации корректировки предназначены для сходимости к точке, где средние задержки примерно равны для всех зеркал.
Вероятности, взвешенные по задержкам, но мёртвые зеркала исключаются из выбора. "Мёртвым" зеркалом считается зеркало, которое вызвало несколько последовательных серьёзных ошибок (например, сбой сети или отсутствие ответа и т. п.).
- Example
ha_strategy = nodeadsВероятности, взвешенные по задержкам, но зеркала с худшим соотношением ошибок и успешных ответов исключаются из выбора.
- Example
ha_strategy = noerrorsПростой выбор по круговому обходу, то есть выбор первого зеркала в списке, затем второго, затем третьего и так далее, а после достижения последнего зеркала процесс повторяется. В отличие от рандомизированных стратегий, RR накладывает строгий порядок запросов (1, 2, 3, ..., N-1, N, 1, 2, 3, ... и так далее) и гарантирует, что два последовательных запроса не будут отправлены одному и тому же зеркалу.
- Example
ha_strategy = roundrobinha_period_karma = 2m
ha_period_karma определяет размер окна статистики агентских зеркал в секундах (или с суффиксом времени). Опционально, по умолчанию 60.
Для распределённой таблицы с агентскими зеркалами сервер отслеживает несколько различных счётчиков для каждого зеркала. Эти счётчики затем используются для отказоустойчивости и балансировки. (Сервер выбирает лучшее зеркало на основе счётчиков.) Счётчики накапливаются блоками по ha_period_karma секунд.
После начала нового блока мастер может использовать накопленные значения из предыдущего блока, пока новый блок не заполнится наполовину. Таким образом, любая предыдущая история перестаёт влиять на выбор зеркала максимум через 1.5 раза ha_period_karma секунд.
Хотя для выбора зеркала используется максимум 2 блока, до 15 последних блоков фактически сохраняются для целей инструментирования. Их можно просмотреть с помощью оператора SHOW AGENT STATUS.
ha_ping_interval = 3s
Директива ha_ping_interval определяет интервал между ping-запросами, отправляемыми агентским зеркалам, в миллисекундах (или с суффиксом времени). Этот параметр опционален, значение по умолчанию — 1000.
Для распределённой таблицы с агентскими зеркалами сервер отправляет всем зеркалам команду ping в периоды простоя, чтобы отслеживать их текущее состояние (живы они или мертвы, время сетевого отклика и т. п.). Интервал между ping-запросами определяется настройкой ha_ping_interval.
Если вы хотите отключить ping-запросы, установите ha_ping_interval в 0.
С Manticore транзакции записи (такие как INSERT, REPLACE, DELETE, TRUNCATE, UPDATE, COMMIT) могут реплицироваться на другие узлы кластера до полного применения транзакции на текущем узле. В настоящее время репликация поддерживается для таблиц percolate, rt и distributed в Linux и macOS.
Нативные бинарные файлы для Windows для Manticore не поддерживают репликацию. Мы рекомендуем устанавливать Manticore через WSL (Подсистема Windows для Linux).
На macOS репликация имеет ограниченную поддержку и рекомендуется только для целей разработки.
Репликация Manticore основана на библиотеке Galera и обладает несколькими впечатляющими функциями:
- Истинный multi-master: чтение и запись на любой узел в любое время.
- Практически синхронная репликация — отсутствие задержек у слейвов и отсутствие потери данных после сбоя узла.
- Горячее резервирование: отсутствие простоев при переключении (так как переключения нет).
- Плотная связность: все узлы имеют одинаковое состояние, и не допускается расхождение данных между узлами.
- Автоматическое добавление узлов: нет необходимости вручную создавать резервные копии базы данных и восстанавливать их на новом узле.
- Простота использования и развертывания.
- Обнаружение и автоматическое исключение ненадежных узлов.
- Репликация на основе сертификации.
Для настройки репликации в Manticore Search:
- Опция data_dir должна быть установлена в разделе "searchd" конфигурационного файла. Репликация не поддерживается в plain режиме.
- Должна быть указана директива listen, содержащая IP-адрес, доступный другим узлам, или node_address с доступным IP-адресом.
- По желанию, вы можете задать уникальные значения для server_id на каждом узле кластера. Если значение не задано, узел попытается использовать MAC-адрес или случайное число для генерации
server_id.
Если не задана директива replication listen, Manticore использует первые два свободных порта из диапазона 200 портов после порта прослушивания протокола по умолчанию для каждого созданного кластера. Для ручной настройки портов репликации необходимо определить диапазон портов в директиве listen (типа replication), и пары адрес/диапазон портов не должны пересекаться между разными узлами на одном сервере. В качестве правила, диапазон портов должен содержать как минимум два порта на кластер. При определении слушателя репликации с диапазоном портов (например, listen = 192.168.0.1:9320-9328:replication), Manticore не начинает сразу прослушивать эти порты. Вместо этого он будет брать случайные свободные порты из указанного диапазона только при начале использования репликации.
Кластер репликации — это группа узлов, в которой реплицируется транзакция записи. Репликация настраивается на уровне таблицы, то есть одна таблица может принадлежать только одному кластеру. Нет ограничений на количество таблиц в кластере. Все транзакции, такие как INSERT, REPLACE, DELETE, TRUNCATE для любой таблицы percolate или real-time, принадлежащей кластеру, реплицируются на все остальные узлы этого кластера. Distributed таблицы также могут участвовать в процессе репликации. Репликация является multi-master, поэтому запись на любой узел или несколько узлов одновременно работает одинаково хорошо.
Для создания кластера обычно используется команда create cluster с CREATE CLUSTER <cluster name>, а для присоединения к кластеру — команда join cluster с JOIN CLUSTER <cluster name> at 'host:port'. Однако в некоторых редких случаях может потребоваться тонкая настройка поведения CREATE/JOIN CLUSTER. Доступные опции:
Эта опция задает имя кластера. Оно должно быть уникальным среди всех кластеров в системе.
Примечание: Максимальная допустимая длина имени хоста для команды
JOINсоставляет 253 символа. Если этот лимит превышен, searchd выдаст ошибку.
Опция path задает каталог данных для write-set cache replication и входящих таблиц с других узлов. Это значение должно быть уникальным среди всех кластеров в системе и указываться как относительный путь к каталогу data_dir. По умолчанию оно равно значению data_dir.
Опция nodes — это список пар адрес:порт для всех узлов кластера, разделенных запятыми. Этот список должен быть получен через API интерфейс узла и может включать адрес текущего узла. Используется для присоединения узла к кластеру и повторного присоединения после перезапуска.
Опция options позволяет передавать дополнительные параметры напрямую плагину репликации Galera, как описано в Galera Documentation Parameters
При работе с кластером репликации все операторы записи, такие как INSERT, REPLACE, DELETE, TRUNCATE, UPDATE, которые изменяют содержимое таблицы кластера, должны использовать выражение cluster_name:table_name вместо имени таблицы. Это гарантирует, что изменения будут распространены на все реплики в кластере. Если не использовать правильное выражение, будет вызвана ошибка.
В JSON-интерфейсе свойство cluster должно быть установлено вместе с именем table для всех операторов записи в таблицу кластера. Если свойство cluster не установлено, возникнет ошибка.
Auto ID для таблицы в кластере должен быть действительным, если правильно настроен server_id.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
INSERT INTO posts:weekly_index VALUES ( 'iphone case' )
TRUNCATE RTINDEX click_query:weekly_index
UPDATE INTO posts:rt_tags SET tags=(101, 302, 304) WHERE MATCH ('use') AND id IN (1,101,201)
DELETE FROM clicks:rt WHERE MATCH ('dumy') AND gid>206POST /insert -d '
{
"cluster":"posts",
"table":"weekly_index",
"doc":
{
"title" : "iphone case",
"price" : 19.85
}
}'
POST /delete -d '
{
"cluster":"posts",
"table": "weekly_index",
"id":1
}'$index->addDocuments([
1, ['title' => 'iphone case', 'price' => 19.85]
]);
$index->deleteDocument(1);indexApi.insert({"cluster":"posts","table":"weekly_index","doc":{"title":"iphone case","price":19.85}})
indexApi.delete({"cluster":"posts","table":"weekly_index","id":1})await indexApi.insert({"cluster":"posts","table":"weekly_index","doc":{"title":"iphone case","price":19.85}})
await indexApi.delete({"cluster":"posts","table":"weekly_index","id":1})res = await indexApi.insert({"cluster":"posts","table":"weekly_index","doc":{"title":"iphone case","price":19.85}});
res = await indexApi.delete({"cluster":"posts","table":"weekly_index","id":1});InsertDocumentRequest newdoc = new InsertDocumentRequest();
HashMap<String,Object> doc = new HashMap<String,Object>(){{
put("title","Crossbody Bag with Tassel");
put("price",19.85);
}};
newdoc.index("weekly_index").cluster("posts").id(1L).setDoc(doc);
sqlresult = indexApi.insert(newdoc);
DeleteDocumentRequest deleteRequest = new DeleteDocumentRequest();
deleteRequest.index("weekly_index").cluster("posts").setId(1L);
indexApi.delete(deleteRequest);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("title", "Crossbody Bag with Tassel");
doc.Add("price", 19.85);
InsertDocumentRequest newdoc = new InsertDocumentRequest(table: "weekly_index", cluster:posts, id: 1, doc: doc);
var sqlresult = indexApi.Insert(newdoc);
DeleteDocumentRequest deleteDocumentRequest = new DeleteDocumentRequest(table: "weekly_index", cluster: "posts", id: 1);
indexApi.Delete(deleteDocumentRequest);let mut doc = HashMap::new();
doc.insert("title".to_string(), serde_json::json!("Crossbody Bag with Tassel"));
doc.insert("price".to_string(), serde_json::json!(19.85));
let insert_req = InsertDocumentRequest {
table: serde_json::json!("weekly_index"),
doc: serde_json::json!(doc),
cluster: serde_json::json!("posts"),
id: serde_json::json!(1),
};
let insert_res = index_api.insert(insert_req).await;
let delete_req = DeleteDocumentRequest {
table: serde_json::json!("weekly_index"),
cluster: serde_json::json!("posts"),
id: serde_json::json!(1),
};
index_api.delete(delete_req).await;Операторы чтения, такие как SELECT, CALL PQ, DESCRIBE, могут использовать либо обычные имена таблиц без префикса с именем кластера, либо формат cluster_name:table_name. Если используется второй вариант, компонент cluster_name игнорируется.
При использовании HTTP-эндпоинта json/search свойство cluster можно указать при желании, но его также можно опустить.
- SQL
- JSON
SELECT * FROM weekly_index
CALL PQ('posts:weekly_index', 'document is here')POST /search -d '
{
"cluster":"posts",
"table":"weekly_index",
"query":{"match":{"title":"keyword"}}
}'
POST /search -d '
{
"table":"weekly_index",
"query":{"match":{"title":"keyword"}}
}'Опции плагина репликации можно настроить с помощью оператора SET.
Список доступных опций можно найти в Galera Documentation Parameters.
- SQL
- JSON
SET CLUSTER click_query GLOBAL 'pc.bootstrap' = 1POST /cli -d "
SET CLUSTER click_query GLOBAL 'pc.bootstrap' = 1
"Возможно, что реплицируемые узлы расходятся друг с другом, что приводит к состоянию, когда все узлы помечены как non-primary. Это может произойти из-за сетевого разрыва между узлами, сбоя кластера или если плагин репликации сталкивается с исключением при определении primary component. В таком случае необходимо выбрать узел и повысить его до роли primary component.
Чтобы определить узел, который нужно повысить, следует сравнить значение переменной статуса кластера last_committed на всех узлах. Если все серверы в данный момент работают, перезапуск кластера не требуется. Вместо этого можно просто повысить узел с наибольшим значением last_committed до primary component с помощью оператора SET (как показано в примере).
Остальные узлы затем переподключатся к primary component и синхронизируют свои данные на основе этого узла.
- SQL
- JSON
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1POST /cli -d "
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1
"Для использования репликации необходимо определить один listen порт для протокола SphinxAPI и один listen для адреса репликации и диапазона портов в конфигурационном файле. Также укажите папку data_dir для приема входящих таблиц.
- ini
searchd {
listen = 9312
listen = 192.168.1.101:9360-9370:replication
data_dir = /var/lib/manticore/
...
}Для репликации таблиц необходимо создать кластер на сервере, где находятся локальные таблицы для репликации.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
CREATE CLUSTER postsPOST /cli -d "
CREATE CLUSTER posts
"$params = [
'cluster' => 'posts'
]
];
$response = $client->cluster()->create($params);utilsApi.sql('CREATE CLUSTER posts')await utilsApi.sql('CREATE CLUSTER posts')res = await utilsApi.sql('CREATE CLUSTER posts');utilsApi.sql("CREATE CLUSTER posts");utilsApi.Sql("CREATE CLUSTER posts");utils_api.sql("CREATE CLUSTER posts", Some(true)).await;Добавьте эти локальные таблицы в кластер
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
ALTER CLUSTER posts ADD pq_title
ALTER CLUSTER posts ADD pq_clicksPOST /cli -d "
ALTER CLUSTER posts ADD pq_title
"
POST /cli -d "
ALTER CLUSTER posts ADD pq_clicks
"$params = [
'cluster' => 'posts',
'body' => [
'operation' => 'add',
'table' => 'pq_title'
]
];
$response = $client->cluster()->alter($params);
$params = [
'cluster' => 'posts',
'body' => [
'operation' => 'add',
'table' => 'pq_clicks'
]
];
$response = $client->cluster()->alter($params);utilsApi.sql('ALTER CLUSTER posts ADD pq_title')
utilsApi.sql('ALTER CLUSTER posts ADD pq_clicks')await utilsApi.sql('ALTER CLUSTER posts ADD pq_title')
await utilsApi.sql('ALTER CLUSTER posts ADD pq_clicks')res = await utilsApi.sql('ALTER CLUSTER posts ADD pq_title');
res = await utilsApi.sql('ALTER CLUSTER posts ADD pq_clicks');utilsApi.sql("ALTER CLUSTER posts ADD pq_title");
utilsApi.sql("ALTER CLUSTER posts ADD pq_clicks");utilsApi.Sql("ALTER CLUSTER posts ADD pq_title");
utilsApi.Sql("ALTER CLUSTER posts ADD pq_clicks");utils_api.sql("ALTER CLUSTER posts ADD pq_title", Some(true)).await;
utils_api.sql("ALTER CLUSTER posts ADD pq_clicks", Some(true)).await;Все остальные узлы, которые хотят получить реплику таблиц кластера, должны присоединиться к кластеру следующим образом:
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
JOIN CLUSTER posts AT '192.168.1.101:9312'POST /cli -d "
JOIN CLUSTER posts AT '192.168.1.101:9312'
"$params = [
'cluster' => 'posts',
'body' => [
'192.168.1.101:9312'
]
];
$response = $client->cluster->join($params);utilsApi.sql('JOIN CLUSTER posts AT \'192.168.1.101:9312\'')await utilsApi.sql('JOIN CLUSTER posts AT \'192.168.1.101:9312\'')res = await utilsApi.sql('JOIN CLUSTER posts AT \'192.168.1.101:9312\'');utilsApi.sql("JOIN CLUSTER posts AT '192.168.1.101:9312'");utilsApi.Sql("JOIN CLUSTER posts AT '192.168.1.101:9312'");utils_api.sql("JOIN CLUSTER posts AT '192.168.1.101:9312'", Some(true)).await;При выполнении запросов добавляйте к имени таблицы префикс с именем кластера posts: или используйте свойство cluster в объекте HTTP-запроса.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
INSERT INTO posts:pq_title VALUES ( 3, 'test me' )POST /insert -d '
{
"cluster":"posts",
"table":"pq_title",
"id": 3
"doc":
{
"title" : "test me"
}
}'$index->addDocuments([
3, ['title' => 'test me']
]);indexApi.insert({"cluster":"posts","table":"pq_title","id":3"doc":{"title":"test me"}})await indexApi.insert({"cluster":"posts","table":"pq_title","id":3"doc":{"title":"test me"}})res = await indexApi.insert({"cluster":"posts","table":"pq_title","id":3"doc":{"title":"test me"}});InsertDocumentRequest newdoc = new InsertDocumentRequest();
HashMap<String,Object> doc = new HashMap<String,Object>(){{
put("title","test me");
}};
newdoc.index("pq_title").cluster("posts").id(3L).setDoc(doc);
sqlresult = indexApi.insert(newdoc);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("title", "test me");
InsertDocumentRequest newdoc = new InsertDocumentRequest(index: "pq_title", cluster: "posts", id: 3, doc: doc);
var sqlresult = indexApi.Insert(newdoc);let mut doc = HashMap::new();
doc.insert("title".to_string(), serde_json::json!("test me"));
let insert_req = InsertDocumentRequest {
table: serde_json::json!("pq_title"),
doc: serde_json::json!(doc),
cluster: serde_json::json!("posts"),
id: serde_json::json!(3),
};
let insert_res = index_api.insert(insert_req).await;All queries that modify tables in the cluster are now replicated to all nodes in the cluster.
Для создания кластера репликации необходимо как минимум задать его имя.
Если вы создаёте один кластер или первый кластер, вы можете опустить опцию path. В этом случае в качестве пути кластера будет использована опция data_dir. Однако для всех последующих кластеров необходимо указать опцию [path], и путь должен быть доступен. Также может быть задана опция nodes для перечисления всех узлов в кластере.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
CREATE CLUSTER posts
CREATE CLUSTER click_query '/var/data/click_query/' as path
CREATE CLUSTER click_query '/var/data/click_query/' as path, 'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312' as nodesPOST /cli -d "
CREATE CLUSTER posts
"
POST /cli -d "
CREATE CLUSTER click_query '/var/data/click_query/' as path
"
POST /cli -d "
CREATE CLUSTER click_query '/var/data/click_query/' as path, 'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312' as nodes
"$params = [
'cluster' => 'posts',
]
];
$response = $client->cluster()->create($params);
$params = [
'cluster' => 'click_query',
'body' => [
'path' => '/var/data/click_query/'
]
]
];
$response = $client->cluster()->create($params);
$params = [
'cluster' => 'click_query',
'body' => [
'path' => '/var/data/click_query/',
'nodes' => 'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312'
]
]
];
$response = $client->cluster()->create($params);utilsApi.sql('CREATE CLUSTER posts')
utilsApi.sql('CREATE CLUSTER click_query \'/var/data/click_query/\' as path')
utilsApi.sql('CREATE CLUSTER click_query \'/var/data/click_query/\' as path, \'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312\' as nodes')await utilsApi.sql('CREATE CLUSTER posts')
await utilsApi.sql('CREATE CLUSTER click_query \'/var/data/click_query/\' as path')
await utilsApi.sql('CREATE CLUSTER click_query \'/var/data/click_query/\' as path, \'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312\' as nodes')res = await utilsApi.sql('CREATE CLUSTER posts');
res = await utilsApi.sql('CREATE CLUSTER click_query \'/var/data/click_query/\' as path');
res = await utilsApi.sql('CREATE CLUSTER click_query \'/var/data/click_query/\' as path, \'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312\' as nodes');utilsApi.sql("CREATE CLUSTER posts");
utilsApi.sql("CREATE CLUSTER click_query '/var/data/click_query/' as path");
utilsApi.sql("CREATE CLUSTER click_query '/var/data/click_query/' as path, 'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312' as nodes");utilsApi.Sql("CREATE CLUSTER posts");
utilsApi.Sql("CREATE CLUSTER click_query '/var/data/click_query/' as path");
utilsApi.Sql("CREATE CLUSTER click_query '/var/data/click_query/' as path, 'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312' as nodes");utils_api.sql("CREATE CLUSTER posts", Some(true)).await;
utils_api.sql("CREATE CLUSTER click_query '/var/data/click_query/' as path", Some(true)).await;
utils_api.sql("CREATE CLUSTER click_query '/var/data/click_query/' as path, 'clicks_mirror1:9312,clicks_mirror2:9312,clicks_mirror3:9312' as nodes", Some(true)).await;Если при создании кластера опция nodes не указана, первым узлом, присоединившимся к кластеру, будет сохранена опция nodes.
Чтобы присоединиться к существующему кластеру, необходимо указать как минимум:
- имя кластера
host:portдругого узла в кластере, к которому вы присоединяетесь
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
JOIN CLUSTER posts AT '10.12.1.35:9312'POST /cli -d "
JOIN CLUSTER posts AT '10.12.1.35:9312'
"$params = [
'cluster' => 'posts',
'body' => [
'10.12.1.35:9312'
]
];
$response = $client->cluster->join($params);utilsApi.sql('JOIN CLUSTER posts AT \'10.12.1.35:9312\'')await utilsApi.sql('JOIN CLUSTER posts AT \'10.12.1.35:9312\'')res = await utilsApi.sql('JOIN CLUSTER posts AT \'10.12.1.35:9312\'');utilsApi.sql("JOIN CLUSTER posts AT '10.12.1.35:9312'");utilsApi.Sql("JOIN CLUSTER posts AT '10.12.1.35:9312'");utils_api.sql("JOIN CLUSTER posts AT '10.12.1.35:9312'", Some(true)).await;{u'error': u'', u'total': 0, u'warning': u''}{u'error': u'', u'total': 0, u'warning': u''}{"total":0,"error":"","warning":""}В большинстве случаев вышеуказанного достаточно, если существует один кластер репликации. Однако, если вы создаёте несколько кластеров репликации, необходимо также задать путь и убедиться, что директория доступна.
- SQL
JOIN CLUSTER c2 at '127.0.0.1:10201' 'c2' as pathУзел присоединяется к кластеру, получая данные от указанного узла и, в случае успеха, обновляет списки узлов на всех остальных узлах кластера так же, как если бы это было сделано вручную через ALTER CLUSTER ... UPDATE nodes. Этот список используется для повторного присоединения узлов к кластеру при перезапуске.
Существует два списка узлов:
1.cluster_<name>_nodes_set: используется для повторного присоединения узлов к кластеру при перезапуске. Он обновляется на всех узлах так же, как это делает ALTER CLUSTER ... UPDATE nodes. Команда JOIN CLUSTER выполняет это обновление автоматически. Статус кластера отображает этот список как cluster_<name>_nodes_set.
2. cluster_<name>_nodes_view: этот список содержит все активные узлы, используемые для репликации, и не требует ручного управления. ALTER CLUSTER ... UPDATE nodes фактически копирует этот список узлов в список узлов, используемых для повторного присоединения при перезапуске. Статус кластера отображает этот список как cluster_<name>_nodes_view.
Когда узлы расположены в разных сетевых сегментах или дата-центрах, опция nodes может быть задана явно. Это минимизирует трафик между узлами и использует шлюзовые узлы для межсоединения между дата-центрами. Следующий код присоединяется к существующему кластеру с использованием опции nodes.
Примечание: список кластера
cluster_<name>_nodes_setне обновляется автоматически при использовании этого синтаксиса. Для его обновления используйте ALTER CLUSTER ... UPDATE nodes.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
JOIN CLUSTER click_query 'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312' as nodesPOST /cli -d "
JOIN CLUSTER click_query 'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312' as nodes
"$params = [
'cluster' => 'posts',
'body' => [
'nodes' => 'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312'
]
];
$response = $client->cluster->join($params);utilsApi.sql('JOIN CLUSTER click_query \'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312\' as nodes')await utilsApi.sql('JOIN CLUSTER click_query \'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312\' as nodes')res = await utilsApi.sql('JOIN CLUSTER click_query \'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312\' as nodes');utilsApi.sql("JOIN CLUSTER click_query 'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312' as nodes");utilsApi.Sql("JOIN CLUSTER click_query 'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312' as nodes");utils_api.sql("JOIN CLUSTER click_query 'clicks_mirror1:9312;clicks_mirror2:9312;clicks_mirror3:9312' as nodes", Some(true)).await;{u'error': u'', u'total': 0, u'warning': u''}{u'error': u'', u'total': 0, u'warning': u''}{"total":0,"error":"","warning":""}Команда JOIN CLUSTER работает синхронно и завершается, как только узел получает все данные от других узлов кластера и синхронизируется с ними.
Операция JOIN CLUSTER может завершиться с ошибкой, указывающей на дублирование server_id. Это происходит, когда присоединяющийся узел имеет такой же server_id, как и существующий узел в кластере. Чтобы решить эту проблему, убедитесь, что каждый узел в кластере репликации имеет уникальный server_id. Вы можете изменить значение по умолчанию server_id в разделе "searchd" вашего конфигурационного файла на уникальное значение перед попыткой присоединения к кластеру.