在多主复制集群中,必须建立一个参考点,其他节点才能加入并形成集群。这称为集群引导,涉及将单个节点作为primary component启动。单个节点的重启或关机后的重新连接可以正常进行。
在完全关闭集群的情况下,应首先启动最后停止的服务器,并使用--new-cluster命令行选项或通过systemd运行manticore_new_cluster。为了确保服务器能够作为参考点,位于集群路径的grastate.dat文件中的safe_to_bootstrap选项应更新为1。必须满足两个条件,--new-cluster和safe_to_bootstrap=1。如果启动其他节点时未设置这些选项,将会发生错误。可以使用--new-cluster-force命令行选项来覆盖此保护,强制从另一台服务器启动集群。或者,可以运行manticore_new_cluster --force来使用systemd。
在集群中所有服务器发生硬崩溃或非正常关闭的情况下,必须识别并启动位于集群路径的grastate.dat文件中具有最大seqno的最先进节点,并使用--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,它将通过 systemd 以 --new-cluster 模式启动 Manticore。
如果另一个节点先启动并引导集群,则最先进的节点加入该集群,执行完整 SST,并接收一个表文件,其中某些事务与之前获得的表文件相比缺失。这就是为什么重要的是先启动最后关闭的节点,该节点在 grastate.dat 中应有标志 safe_to_bootstrap: 1。
在发生崩溃或网络故障导致节点 A 从集群中消失的情况下,节点 B 和 C 会尝试重新连接节点 A。连接失败后,它们会将节点 A 从集群中移除。由于三个节点中仍有两个节点运行,集群保持法定人数并继续正常运行。
当节点 A 重启时,它将自动加入集群,如 情况 1 所述。
节点 A 和 B 已离线。节点 C 无法单独形成法定人数,因为 1 个节点少于总节点数(3)的一半。因此,节点 C 上的集群被转移到非主状态,并拒绝任何写事务,返回错误消息。
同时,节点 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 命令,它将通过 systemd 以 --new-cluster-force 模式启动 Manticore。
Split-brain 可能导致集群转变为非主状态。例如,考虑一个由偶数个节点(四个)组成的集群,比如位于不同数据中心的两对节点。如果网络故障中断了数据中心之间的连接,就会发生 split-brain,因为每组节点恰好持有半数的法定人数。因此,两个组都停止处理写事务,因为 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 节点和基于 Manticore 二进制 API 的客户端的连接
- 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 使用 MySQL 协议实现了一个 SQL 接口,允许使用任何 MySQL 库或连接器以及许多 MySQL 客户端连接到 Manticore Search,并像操作 MySQL 服务器一样操作它,而不是 Manticore。
然而,SQL 方言不同,只实现了 MySQL 中可用的 SQL 命令或函数的子集。此外,还有一些特定于 Manticore Search 的子句和函数,例如用于全文搜索的 MATCH() 子句。
Manticore Search 不支持服务器端预处理语句,但可以使用客户端预处理语句。需要注意的是,Manticore 实现了多值(MVA)数据类型,这在 MySQL 或实现预处理语句的库中没有对应类型。在这些情况下,MVA 值必须在原始查询中构造。
一些 MySQL 客户端/连接器需要用户/密码和/或数据库名称的值。由于 Manticore Search 没有数据库的概念,也没有实现用户访问控制,这些值可以任意设置,因为 Manticore 会简单地忽略它们。
SQL 接口的默认端口是 9306,且默认启用。
您可以在配置文件的 searchd 部分使用 listen 指令配置 MySQL 端口,如下所示:
searchd {
...
listen = 127.0.0.1:9306:mysql
...
}
请记住,Manticore 没有用户认证,因此请确保 MySQL 端口不对网络外部的任何人开放。
可以使用单独的 MySQL 端口进行“VIP”连接。连接到此端口时,将绕过线程池,并始终创建一个新的专用线程。这在严重过载的情况下非常有用,此时服务器可能会停滞或阻止通过常规端口的连接。
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 字符串中传递某些设置,因为连接器可能尝试运行 Manticore 尚未实现的某些 SQL 命令。
JDBC 连接器 6.x 及以上版本需要 Manticore Search 2.8.2 或更高版本,且 DSN 字符串应包含以下选项:
jdbc:mysql://IP:PORT/DB/?characterEncoding=utf8&maxAllowedPacket=512000&serverTimezone=XXX
默认情况下,Manticore Search 会向连接器报告其自身版本,但这可能会引起一些问题。为解决此问题,应在配置文件的 searchd 部分设置 mysql_version_string 指令为低于 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;
可以使用 ODBC 访问 Manticore。建议在 ODBC 字符串中设置 charset=UTF8。某些 ODBC 驱动程序不喜欢 Manticore 服务器报告的版本,因为它们会将其视为非常旧的 MySQL 服务器。可以通过 mysql_version_string 选项覆盖此行为。
基于 MySQL 的 Manticore SQL 支持 C 风格的注释语法。从开头的 /* 到结尾的 */ 之间的所有内容都会被忽略。注释可以跨多行,不能嵌套,也不应被记录。MySQL 特有的 /*! ... */ 注释目前也被忽略。(注释支持主要是为了更好地兼容 mysqldump 生成的转储文件,而不是为了改善 Manticore 和 MySQL 之间的一般查询互操作性。)
SELECT /*! SQL_CALC_FOUND_ROWS */ col1 FROM table1 WHERE ...