В кластере с многомастеровой репликацией необходимо установить отправную точку, прежде чем другие узлы смогут присоединиться и сформировать кластер. Это называется загрузкой кластера (bootstrap) и включает запуск одного узла в качестве primary component. Перезапуск одного узла или повторное подключение после отключения можно выполнять как обычно.
В случае полного отключения кластера первый должен быть запущен сервер, который был остановлен последним, с параметром командной строки --new-cluster или путем запуска manticore_new_cluster через systemd. Чтобы гарантировать, что сервер может служить отправной точкой, файл grastate.dat, расположенный в папке кластера, должен содержать значение 1 для опции safe_to_bootstrap. Обе условия, --new-cluster и safe_to_bootstrap=1, должны быть выполнены. Если любой другой узел будет запущен без этих параметров, возникнет ошибка. Для обхода этой защиты и принудительного запуска кластера с другого сервера можно использовать параметр командной строки --new-cluster-force. Альтернативно можно запустить manticore_new_cluster --force через systemd.
В случае жесткого сбоя или некорректного завершения работы всех серверов в кластере следует определить наиболее продвинутый узел с наибольшим значением seqno в файле grastate.dat, расположенном в папке кластера, и запустить его с ключом командной строки --new-cluster-force.
В случае, если демон поиска Manticore останавливается и в кластере не остается узлов для обработки запросов, необходимо выполнить восстановление. Из-за мульти-мастерной природы библиотеки Galera, используемой для репликации, кластер репликации Manticore представляет собой единый логический объект, который поддерживает согласованность своих узлов и данных, а также состояние всего кластера. Это позволяет безопасно проводить записи на нескольких узлах одновременно и обеспечивает целостность кластера.
Однако это также создает некоторые сложности. Рассмотрим несколько сценариев, используя кластер из узлов A, B и C, чтобы понять, что нужно делать, когда некоторые или все узлы становятся недоступными.
Когда узел A останавливается, другие узлы получают сообщение о «нормальном завершении работы». Размер кластера уменьшается, и происходит перерасчет кворума.
При запуске узел A присоединяется к кластеру и не будет обслуживать операции записи, пока полностью не синхронизируется с кластером. Если кэш набора транзакций на узлах-доноров B или C (который можно контролировать параметром Galera кластера gcache.size) по-прежнему содержит все транзакции, пропущенные узлом A, узел A получит быстрый инкрементальный перенос состояния (IST), то есть передачу только пропущенных транзакций. В противном случае произойдет перенос состояния снимка (SST), который включает передачу файлов таблиц.
В случае остановки узлов A и B размер кластера сокращается до одного, узел C формирует основную компоненту и обрабатывает операции записи.
Затем узлы A и B могут быть запущены как обычно и присоединятся к кластеру после старта. Узел C выступает в качестве донора, предоставляя перенос состояния узлам A и B.
Все узлы остановлены, кластер выключен.
Проблема теперь заключается в том, как инициализировать кластер. Важно, чтобы при корректном завершении работы searchd узлы записывали номер последней выполненной транзакции в директорию кластера в файл grastate.dat вместе с флагом safe_to_bootstrap. Узел, который был остановлен последним, будет иметь опцию safe_to_bootstrap: 1 и самый продвинутый номер seqno.
Важным является, чтобы этот узел запускался первым для формирования кластера. Для инициализации кластера сервер на этом узле должен быть запущен с флагом --new-cluster. В Linux также можно запустить manticore_new_cluster, который стартует Manticore в режиме --new-cluster через systemd.
Если сначала запускается другой узел, который инициализирует кластер, то наиболее продвинутый узел присоединится к этому кластеру, выполнит полную SST и получит файлы таблиц, в которых некоторые транзакции отсутствуют по сравнению с теми файлами таблиц, которые он имел ранее. Поэтому важно запускать в первую очередь узел, который был остановлен последним, и у которого в файле grastate.dat установлен флаг safe_to_bootstrap: 1.
В случае сбоя или сетевого отказа, из-за которого узел A исчезает из кластера, узлы B и C попытаются переподключиться к узлу A. При неудаче они удалят узел A из кластера. С двумя из трех узлов, которые продолжают работу, кластер сохраняет кворум и продолжает функционировать нормально.
При перезапуске узел A автоматически присоединится к кластеру, как описано в Случае 1.
Узлы A и B вышли из строя. Узел C не может самостоятельно сформировать кворум, поскольку 1 узел меньше половины от общего числа узлов (3). В результате кластер на узле C переходит в состояние non-primary и отклоняет операции записи с сообщением об ошибке.
Тем временем узел C ожидает подключения других узлов и также пытается к ним подключиться. Если это произойдет, восстанавливается сеть, и узлы A и B снова в сети, кластер автоматически восстановится. Если узлы A и B просто временно отключены от узла C, но могут общаться друг с другом, они продолжат работу в нормальном режиме, так как они продолжают образовывать кворум.
Однако если оба узла A и B вышли из строя или перезапустились из-за отключения питания, кому-то нужно активировать основную компоненту на узле C с помощью следующей команды:
- SQL
- JSON
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1POST /cli -d "
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1
"Важным является то, что перед выполнением этой команды нужно убедиться, что другие узлы действительно недоступны. Иначе может произойти сценарий разделения мозга (split-brain), и сформируются отдельные кластеры.
Все узлы вышли из строя. В этой ситуации файл grastate.dat в директории кластера не был обновлен и не содержит корректный номер последовательности seqno.
Если это случается, необходимо найти узел с самыми свежими данными и запустить сервер на нем с использованием ключа командной строки --new-cluster-force. Все остальные узлы будут запущены как обычно, как описано в Случае 3).
В Linux также можно использовать команду manticore_new_cluster --force, которая запустит Manticore в режиме --new-cluster-force через systemd.
Разделение мозга может привести к переходу кластера в состояние без первичной реплики. Например, рассмотрим кластер, состоящий из четного числа узлов (четыре), таких как две пары узлов, расположенных в разных центрах обработки данных. Если сбой сети прерывает соединение между центрами обработки данных, происходит разделение мозга, поскольку каждая группа узлов удерживает ровно половину кворума. В результате обе группы перестают обрабатывать транзакции записи, поскольку модель репликации Galera отдает приоритет согласованности данных, и кластер не может принимать транзакции записи без кворума. Однако узлы в обеих группах пытаются переподключиться к узлам из другой группы, чтобы восстановить кластер.
Если кто-то хочет восстановить кластер до восстановления сети, следует предпринять те же шаги, что описаны в Случае 5, но только в одной группе узлов.
После выполнения оператора группа с узлом, на котором он был выполнен, снова сможет обрабатывать транзакции записи.
- SQL
- JSON
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1POST /cli -d "
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1
"Однако важно отметить, что если оператор будет выполнен в обеих группах, это приведет к образованию двух отдельных кластеров, и последующее восстановление сети не приведет к повторному объединению групп.
Со стандартной конфигурацией, Manticore ожидает ваши подключения на:
- порт 9306 для клиентов MySQL
- порт 9308 для HTTP/HTTPS подключений
- порт 9312 для HTTP/HTTPS, а также подключений от других узлов Manticore и клиентов, основанных на бинарном API Manticore
- SQL
- HTTP
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
- docker
mysql -h0 -P9306HTTP — это безсессионный протокол, поэтому не требует специальной фазы подключения:
curl -s "http://localhost:9308/search"require_once __DIR__ . '/vendor/autoload.php';
$config = ['host'=>'127.0.0.1','port'=>9308];
$client = new \Manticoresearch\Client($config);import manticoresearch
config = manticoresearch.Configuration(
host = "http://127.0.0.1:9308"
)
client = manticoresearch.ApiClient(config)
indexApi = manticoresearch.IndexApi(client)
searchApi = manticoresearch.searchApi(client)
utilsApi = manticoresearch.UtilsApi(client)import manticoresearch
config = manticoresearch.Configuration(
host = "http://127.0.0.1:9308"
)
async with manticoresearch.ApiClient(config) as client:
indexApi = manticoresearch.IndexApi(client)
searchApi = manticoresearch.searchApi(client)
utilsApi = manticoresearch.UtilsApi(client)var Manticoresearch = require('manticoresearch');
var client= new Manticoresearch.ApiClient()
client.basePath="http://127.0.0.1:9308";
indexApi = new Manticoresearch.IndexApi(client);
searchApi = new Manticoresearch.SearchApi(client);
utilsApi = new Manticoresearch.UtilsApi(client);import com.manticoresearch.client.ApiClient;
import com.manticoresearch.client.ApiException;
import com.manticoresearch.client.Configuration;
import com.manticoresearch.client.model.*;
import com.manticoresearch.client.api.IndexApi;
import com.manticoresearch.client.api.UtilsApi;
import com.manticoresearch.client.api.SearchApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("http://127.0.0.1:9308");
IndexApi indexApi = new IndexApi(client);
SearchApi searchApi = new UtilsApi(client);
UtilsApi utilsApi = new UtilsApi(client);using ManticoreSearch.Client;
using ManticoreSearch.Api;
using ManticoreSearch.Model;
string basePath = "http://127.0.0.1:9308";
IndexApi indexApi = new IndexApi(basePath);
SearchApi searchApi = new UtilsApi(basePath);
UtilsApi utilsApi = new UtilsApi(basePath);use std::sync::Arc;
use manticoresearch::{
apis::{
{configuration::Configuration,IndexApi,IndexApiClient,SearchApi,SearchApiClient,UtilsApi,UtilsApiClient}
},
};
async fn maticore_connect {
let configuration = Configuration {
base_path: "http://127.0.0.1:9308".to_owned(),
..Default::default(),
};
let api_config = Arc::new(configuration);
let utils_api = UtilsApiClient::new(api_config.clone());
let index_api = IndexApiClient::new(api_config.clone());
let search_api = SearchApiClient::new(api_config.clone());Запустите контейнер Manticore и используйте встроенный клиент MySQL для подключения к узлу.
docker run --name manticore -d manticoresearch/manticore && docker exec -it manticore mysqlManticore Search реализует SQL-интерфейс с использованием протокола MySQL, что позволяет использовать любую библиотеку или коннектор MySQL, а также многие MySQL-клиенты для подключения к Manticore Search и работы с ним так, как если бы это был сервер MySQL, а не Manticore.
Однако диалект SQL отличается и реализует только подмножество SQL-команд или функций, доступных в MySQL. Кроме того, существуют команды и функции, специфичные для Manticore Search, такие как клауза MATCH() для полнотекстового поиска.
Manticore Search не поддерживает подготовленные выражения на стороне сервера, но можно использовать подготовленные выражения на стороне клиента. Важно отметить, что Manticore реализует тип данных с множественными значениями (MVA), который не имеет эквивалента в MySQL или библиотеках, реализующих подготовленные выражения. В таких случаях значения MVA должны быть сформированы в сыром запросе.
Некоторые клиенты/коннекторы MySQL требуют значения для пользователя/пароля и/или имени базы данных. Поскольку в Manticore Search нет понятия баз данных и не реализован контроль доступа пользователей, эти значения могут быть заданы произвольно, так как Manticore просто их игнорирует.
Порт по умолчанию для SQL-интерфейса — 9306, и он включен по умолчанию.
Вы можете настроить порт MySQL в разделе searchd конфигурационного файла, используя директиву listen следующим образом:
searchd {
...
listen = 127.0.0.1:9306:mysql
...
}
Имейте в виду, что в Manticore нет аутентификации пользователей, поэтому убедитесь, что порт MySQL недоступен никому за пределами вашей сети.
Для выполнения "VIP" подключений можно использовать отдельный порт MySQL. При подключении к этому порту пул потоков обходится, и всегда создается новый выделенный поток. Это полезно в случае серьезной перегрузки, когда сервер либо зависает, либо препятствует подключению через обычный порт.
searchd {
...
listen = 127.0.0.1:9306:mysql
listen = 127.0.0.1:9307:mysql_vip
...
}
Самый простой способ подключения к Manticore — использование стандартного MySQL клиента:
mysql -P9306 -h0
Протокол MySQL поддерживает шифрование SSL. Безопасные подключения можно установить на том же порту mysql.
Сжатие можно использовать при подключениях MySQL, и оно доступно клиентам по умолчанию. Клиенту просто нужно указать, что соединение должно использовать сжатие.
Пример использования MySQL-клиента:
mysql -P9306 -h0 -C
Сжатие можно использовать как в защищённых, так и в незашищённых подключениях.
Официальные коннекторы MySQL можно использовать для подключения к Manticore Search, однако им могут потребоваться определённые настройки, передаваемые в строке DSN, поскольку коннектор может попытаться выполнить SQL-команды, которые ещё не реализованы в Manticore.
JDBC коннектор 6.x и выше требует Manticore Search версии 2.8.2 или выше, и строка DSN должна содержать следующие опции:
jdbc:mysql://IP:PORT/DB/?characterEncoding=utf8&maxAllowedPacket=512000&serverTimezone=XXX
По умолчанию Manticore Search сообщает коннектору свою собственную версию, однако это может вызвать некоторые проблемы. Для их решения директива mysql_version_string в разделе searchd конфигурационного файла должна быть установлена на версию ниже 5.1.1:
searchd {
...
mysql_version_string = 5.0.37
...
}
.NET коннектор MySQL по умолчанию использует пулы подключений. Для правильного получения статистики SHOW META запросы вместе с командой SHOW META должны отправляться как единое многокомандное выражение (SELECT ...;SHOW META). Если пулы включены, в строку подключения необходимо добавить опцию Allow Batch=True, чтобы разрешить многокомандность:
Server=127.0.0.1;Port=9306;Database=somevalue;Uid=somevalue;Pwd=;Allow Batch=True;
К Manticore можно получить доступ с помощью ODBC. Рекомендуется устанавливать charset=UTF8 в строке ODBC. Некоторые драйверы ODBC не понравится версия, сообщаемая сервером Manticore, так как они увидят её как очень старую версию сервера MySQL. Это можно переопределить с помощью опции mysql_version_string.
SQL Manticore через MySQL поддерживает синтаксис комментариев в стиле C. Всё от начальной последовательности /* до конечной последовательности */ игнорируется. Комментарии могут занимать несколько строк, не могут вкладываться и не должны записываться в лог. Специфичные для MySQL комментарии /*! ... */ также в настоящее время игнорируются. (Поддержка комментариев была добавлена скорее для лучшей совместимости с дампами, созданными mysqldump, а не для улучшения общей интероперабельности запросов между Manticore и MySQL.)
SELECT /*! SQL_CALC_FOUND_ROWS */ col1 FROM table1 WHERE ...