ALTER CLUSTER <cluster_name> UPDATE nodes 语句会更新指定集群中每个节点上的节点列表,以包含集群中的所有活动节点。有关节点列表的更多信息,请参见 加入集群。
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
ALTER CLUSTER posts UPDATE nodesPOST /cli -d "
ALTER CLUSTER posts UPDATE nodes
"$params = [
'cluster' => 'posts',
'body' => [
'operation' => 'update',
]
];
$response = $client->cluster()->alter($params);utilsApi.sql('ALTER CLUSTER posts UPDATE nodes')await utilsApi.sql('ALTER CLUSTER posts UPDATE nodes')res = await utilsApi.sql('ALTER CLUSTER posts UPDATE nodes');utilsApi.sql("ALTER CLUSTER posts UPDATE nodes");utilsApi.Sql("ALTER CLUSTER posts UPDATE nodes");utils_api.sql("ALTER CLUSTER posts UPDATE 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":""}例如,当集群最初建立时,用于重新加入集群的节点列表是 10.10.0.1:9312,10.10.1.1:9312。此后,其他节点加入了集群,现在的活动节点是 10.10.0.1:9312,10.10.1.1:9312,10.15.0.1:9312,10.15.0.3:9312。然而,用于重新加入集群的节点列表尚未更新。
为了解决此问题,您可以运行 ALTER CLUSTER ... UPDATE nodes 语句,将活动节点列表复制到用于重新加入集群的节点列表中。之后,用于重新加入集群的节点列表将包含集群中的所有活动节点。
两个节点列表都可以通过使用 集群状态 语句查看(cluster_post_nodes_set 和 cluster_post_nodes_view)。
要从复制集群中移除节点,请执行以下步骤:
- 停止该节点
- 从已停止节点的
<data_dir>/manticore.json(通常是/var/lib/manticore/manticore.json)中删除有关集群的信息。 - 在其他任一节点上运行
ALTER CLUSTER cluster_name UPDATE nodes。
完成这些步骤后,其他节点将忘记已分离的节点,已分离的节点也将忘记该集群。此操作不会影响集群中或已分离节点上的表。
您可以通过检查节点状态来查看集群状态信息。这可以使用节点状态命令完成,该命令显示有关节点的各种信息,包括集群状态变量。
集群状态变量的输出格式如下:cluster_name_variable_name variable_value。大多数变量在Galera 文档状态变量中有描述。除了这些变量外,Manticore Search 还显示:
cluster_name- 集群的名称,如复制设置中定义node_state- 节点的当前状态:closed,destroyed,joining,donor,syncedindexes_count- 集群管理的表的数量indexes- 集群管理的表名列表nodes_set- 使用CREATE、JOIN或ALTER UPDATE命令定义的集群节点列表nodes_view- 当前节点可见的集群实际节点列表。state_uuid- 集群的 UUID 状态。如果它与 local_state_uuid 中的值匹配,则本地和集群节点同步。conf_id- 集群成员变更的总次数。status- 集群组件状态。可能的值为 primary(主组配置,存在法定人数)、non_primary(非主组配置,失去法定人数)或 disconnected(未连接到组,正在重试)。size- 当前集群中的节点数。local_index- 节点在集群中的索引。last_error- 与集群操作相关的最后记录的错误消息。该消息提供问题的高级摘要。有关更详细的上下文,应查阅searchd.log文件。
在状态快照传输(SST)期间,节点通过传输完整数据副本来为另一个节点提供数据。当新节点加入集群 JOIN CLUSTER 或添加新表 ALTER CLUSTER ADD 时会发生此情况。在 SST 活动期间,以下额外的状态变量将在捐赠节点和加入节点上可用,其进度保持同步。
cluster_name_sst_total- 整个 SST 操作的总体进度,范围从 0 到 100。这是主要的计数器。cluster_name_sst_stage- 当前工作阶段的名称。该过程为每个传输的表循环经过以下阶段:await nodes syncblock checksum calculateanalyze remotesend filesactivate tables
cluster_name_sst_stage_total- 当前阶段的进度,范围从 0 到 100。cluster_name_sst_tables- SST 中传输的表的总数。cluster_name_sst_table- 当前处理的表的名称和索引(例如,3 (products))。
对于大多数用例,cluster_name_sst_total 就足够了。然而,其他计数器对于调查特定 SST 阶段或特定表上的停滞或性能问题非常有用。
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
SHOW STATUSPOST /cli -d "
SHOW STATUS
"$params = [
'body' => []
];
$response = $client->nodes()->status($params);utilsApi.sql('SHOW STATUS')await utilsApi.sql('SHOW STATUS')res = await utilsApi.sql('SHOW STATUS');utilsApi.sql("SHOW STATUS");utilsApi.sql("SHOW STATUS");utils_api.sql("SHOW STATUS", Some(true)).await;+---------------------------------+-------------------------------------------------------------------------------------+
| Counter | Value |
+---------------------------------+-------------------------------------------------------------------------------------+
| cluster_name | post |
| cluster_post_state_uuid | fba97c45-36df-11e9-a84e-eb09d14b8ea7 |
| cluster_post_conf_id | 1 |
| cluster_post_status | primary |
| cluster_post_size | 5 |
| cluster_post_local_index | 0 |
| cluster_post_node_state | donor |
| cluster_post_indexes_count | 2 |
| cluster_post_indexes | pq1,pq_posts |
| cluster_post_nodes_set | 10.10.0.1:9312 |
| cluster_post_nodes_view | 10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication |
| cluster_post_sst_total | 65 |
| cluster_post_sst_stage | send files |
| cluster_post_sst_stage_total | 78 |
| cluster_post_sst_tables | 5 |
| cluster_post_sst_table | 3 (products) |
+---------------------------------+-------------------------------------------------------------------------------------+"
{"columns":[{"Counter":{"type":"string"}},{"Value":{"type":"string"}}],
"data":[
{"Counter":"cluster_name", "Value":"post"},
{"Counter":"cluster_post_state_uuid", "Value":"fba97c45-36df-11e9-a84e-eb09d14b8ea7"},
{"Counter":"cluster_post_conf_id", "Value":"1"},
{"Counter":"cluster_post_status", "Value":"primary"},
{"Counter":"cluster_post_size", "Value":"5"},
{"Counter":"cluster_post_local_index", "Value":"0"},
{"Counter":"cluster_post_node_state", "Value":"donor"},
{"Counter":"cluster_post_indexes_count", "Value":"2"},
{"Counter":"cluster_post_indexes", "Value":"pq1,pq_posts"},
{"Counter":"cluster_post_nodes_set", "Value":"10.10.0.1:9312"},
{"Counter":"cluster_post_nodes_view", "Value":"10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication"},
{"Counter":"cluster_post_sst_total", "Value":"65"},
{"Counter":"cluster_post_sst_stage", "Value":"send files"},
{"Counter":"cluster_post_sst_stage_total", "Value":"78"},
{"Counter":"cluster_post_sst_tables", "Value":"5"},
{"Counter":"cluster_post_sst_table", "Value":"3 (products)"}
],
"total":0,
"error":"",
"warning":""
}(
"cluster_name" => "post",
"cluster_post_state_uuid" => "fba97c45-36df-11e9-a84e-eb09d14b8ea7",
"cluster_post_conf_id" => 1,
"cluster_post_status" => "primary",
"cluster_post_size" => 5,
"cluster_post_local_index" => 0,
"cluster_post_node_state" => "donor",
"cluster_post_indexes_count" => 2,
"cluster_post_indexes" => "pq1,pq_posts",
"cluster_post_nodes_set" => "10.10.0.1:9312",
"cluster_post_nodes_view" => "10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication",
"cluster_post_sst_total" => 65,
"cluster_post_sst_stage" => "send files",
"cluster_post_sst_stage_total" => 78,
"cluster_post_sst_tables" => 5,
"cluster_post_sst_table" => "3 (products)"
){u'columns': [{u'Key': {u'type': u'string'}},
{u'Value': {u'type': u'string'}}],
u'data': [
{u'Key': u'cluster_name', u'Value': u'post'},
{u'Key': u'cluster_post_state_uuid', u'Value': u'fba97c45-36df-11e9-a84e-eb09d14b8ea7'},
{u'Key': u'cluster_post_conf_id', u'Value': u'1'},
{u'Key': u'cluster_post_status', u'Value': u'primary'},
{u'Key': u'cluster_post_size', u'Value': u'5'},
{u'Key': u'cluster_post_local_index', u'Value': u'0'},
{u'Key': u'cluster_post_node_state', u'Value': u'donor'},
{u'Key': u'cluster_post_indexes_count', u'Value': u'2'},
{u'Key': u'cluster_post_indexes', u'Value': u'pq1,pq_posts'},
{u'Key': u'cluster_post_nodes_set', u'Value': u'10.10.0.1:9312'},
{u'Key': u'cluster_post_nodes_view', u'Value': u'10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication'},
{u'Key': u'cluster_post_sst_total', u'Value': u'65'},
{u'Key': u'cluster_post_sst_stage', u'Value': u'send files'},
{u'Key': u'cluster_post_sst_stage_total', u'Value': u'78'},
{u'Key': u'cluster_post_sst_tables', u'Value': u'5'},
{u'Key': u'cluster_post_sst_table', u'Value': u'3 (products)'}],
u'error': u'',
u'total': 0,
u'warning': u''}{u'columns': [{u'Key': {u'type': u'string'}},
{u'Value': {u'type': u'string'}}],
u'data': [
{u'Key': u'cluster_name', u'Value': u'post'},
{u'Key': u'cluster_post_state_uuid', u'Value': u'fba97c45-36df-11e9-a84e-eb09d14b8ea7'},
{u'Key': u'cluster_post_conf_id', u'Value': u'1'},
{u'Key': u'cluster_post_status', u'Value': u'primary'},
{u'Key': u'cluster_post_size', u'Value': u'5'},
{u'Key': u'cluster_post_local_index', u'Value': u'0'},
{u'Key': u'cluster_post_node_state', u'Value': u'donor'},
{u'Key': u'cluster_post_indexes_count', u'Value': u'2'},
{u'Key': u'cluster_post_indexes', u'Value': u'pq1,pq_posts'},
{u'Key': u'cluster_post_nodes_set', u'Value': u'10.10.0.1:9312'},
{u'Key': u'cluster_post_nodes_view', u'Value': u'10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication'},
{u'Key': u'cluster_post_sst_total', u'Value': u'65'},
{u'Key': u'cluster_post_sst_stage', u'Value': u'send files'},
{u'Key': u'cluster_post_sst_stage_total', u'Value': u'78'},
{u'Key': u'cluster_post_sst_tables', u'Value': u'5'},
{u'Key': u'cluster_post_sst_table', u'Value': u'3 (products)'}],
u'error': u'',
u'total': 0,
u'warning': u''}{"columns": [{"Key": {"type": "string"}},
{"Value": {"type": "string"}}],
"data": [
{"Key": "cluster_name", "Value": "post"},
{"Key": "cluster_post_state_uuid", "Value": "fba97c45-36df-11e9-a84e-eb09d14b8ea7"},
{"Key": "cluster_post_conf_id", "Value": "1"},
{"Key": "cluster_post_status", "Value": "primary"},
{"Key": "cluster_post_size", "Value": "5"},
{"Key": "cluster_post_local_index", "Value": "0"},
{"Key": "cluster_post_node_state", "Value": "donor"},
{"Key": "cluster_post_indexes_count", "Value": "2"},
{"Key": "cluster_post_indexes", "Value": "pq1,pq_posts"},
{"Key": "cluster_post_nodes_set", "Value": "10.10.0.1:9312"},
{"Key": "cluster_post_nodes_view", "Value": "10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication"},
{"Key": "cluster_post_sst_total", "Value": "65"},
{"Key": "cluster_post_sst_stage", "Value": "send files"},
{"Key": "cluster_post_sst_stage_total", "Value": "78"},
{"Key": "cluster_post_sst_tables", "Value": "5"},
{"Key": "cluster_post_sst_table", "Value": "3 (products)"}],
"error": "",
"total": 0,
"warning": ""}{columns=[{ Key : { type=string }},
{ Value : { type=string }}],
data : [
{ Key=cluster_name, Value=post},
{ Key=cluster_post_state_uuid, Value=fba97c45-36df-11e9-a84e-eb09d14b8ea7},
{ Key=cluster_post_conf_id, Value=1},
{ Key=cluster_post_status, Value=primary},
{ Key=cluster_post_size, Value=5},
{ Key=cluster_post_local_index, Value=0},
{ Key=cluster_post_node_state, Value=donor},
{ Key=cluster_post_indexes_count, Value=2},
{ Key=cluster_post_indexes, Value=pq1,pq_posts},
{ Key=cluster_post_nodes_set, Value=10.10.0.1:9312},
{ Key=cluster_post_nodes_view, Value=10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication},
{ Key=cluster_post_sst_total, Value=65},
{ Key=cluster_post_sst_stage, Value=send files},
{ Key=cluster_post_sst_stage_total, Value=78},
{ Key=cluster_post_sst_tables, Value=5},
{ Key=cluster_post_sst_table, Value=3 (products)}],
error= ,
total=0,
warning= }{columns=[{ Key : { type=String }},
{ Value : { type=String }}],
data : [
{ Key=cluster_name, Value=post},
{ Key=cluster_post_state_uuid, Value=fba97c45-36df-11e9-a84e-eb09d14b8ea7},
{ Key=cluster_post_conf_id, Value=1},
{ Key=cluster_post_status, Value=primary},
{ Key=cluster_post_size, Value=5},
{ Key=cluster_post_local_index, Value=0},
{ Key=cluster_post_node_state, Value=donor},
{ Key=cluster_post_indexes_count, Value=2},
{ Key=cluster_post_indexes, Value=pq1,pq_posts},
{ Key=cluster_post_nodes_set, Value=10.10.0.1:9312},
{ Key=cluster_post_nodes_view, Value=10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication},
{ Key=cluster_post_sst_total, Value=65},
{ Key=cluster_post_sst_stage, Value=send files},
{ Key=cluster_post_sst_stage_total, Value=78},
{ Key=cluster_post_sst_tables, Value=5},
{ Key=cluster_post_sst_table, Value=3 (products)}],
error="" ,
total=0,
warning="" }{columns=[{ Key : { type=String }},
{ Value : { type=String }}],
data : [
{ Key=cluster_name, Value=post},
{ Key=cluster_post_state_uuid, Value=fba97c45-36df-11e9-a84e-eb09d14b8ea7},
{ Key=cluster_post_conf_id, Value=1},
{ Key=cluster_post_status, Value=primary},
{ Key=cluster_post_size, Value=5},
{ Key=cluster_post_local_index, Value=0},
{ Key=cluster_post_node_state, Value=donor},
{ Key=cluster_post_indexes_count, Value=2},
{ Key=cluster_post_indexes, Value=pq1,pq_posts},
{ Key=cluster_post_nodes_set, Value=10.10.0.1:9312},
{ Key=cluster_post_nodes_view, Value=10.10.0.1:9312,10.10.0.1:9320:replication,10.10.1.1:9312,10.10.1.1:9320:replication},
{ Key=cluster_post_sst_total, Value=65},
{ Key=cluster_post_sst_stage, Value=send files},
{ Key=cluster_post_sst_stage_total, Value=78},
{ Key=cluster_post_sst_tables, Value=5},
{ Key=cluster_post_sst_table, Value=3 (products)}],
error="" ,
total=0,
warning="" }在多主复制集群中,必须建立一个参考点,其他节点才能加入并形成集群。这称为集群引导,涉及将单个节点作为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
"但是,需要注意的是,如果该语句在两个组都执行,将导致形成两个独立的集群,随后网络恢复时这两个组不会重新合并。