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 命令行选项来强制覆盖此保护,并从另一台服务器启动集群。或者,可以通过 systemd 运行 manticore_new_cluster --force。
如果所有服务器发生严重崩溃或不干净关闭,必须识别出 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 都停止的场景下,集群规模减少到 1,由节点 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
"重要的是,在执行该命令之前,必须确认其他节点确实无法访问。否则,可能会发生脑裂,形成分离的集群。
所有节点崩溃。在这种情况下,集群目录中的 grastate.dat 文件未更新,且不包含有效的 seqno 序列号。
如果发生这种情况,需要有人找到数据最新的节点,并使用命令行参数 --new-cluster-force 启动该节点上的服务器。所有其他节点将按正常方式启动,如情况 3所述。
在 Linux 上,也可以使用 manticore_new_cluster --force 命令,通过 systemd 以 --new-cluster-force 模式启动 Manticore。
脑裂可能导致集群转变为非主状态。例如,考虑一个由偶数个节点(四个)组成的集群,比如位于不同数据中心的两对节点。如果网络故障中断了数据中心之间的连接,脑裂就会发生,因为每组节点恰好持有半数仲裁。结果,两组节点都停止处理写事务,因为Galera复制模型优先考虑数据一致性,没有仲裁的集群无法接受写事务。然而,两组中的节点都会尝试与另一组的节点重新连接,以努力恢复集群。
如果有人在网络恢复之前想要恢复集群,应采取案例5中概述的相同步骤,但仅在其中一组节点上执行。
执行该语句后,运行该语句的节点所在组将能够再次处理写事务。
- SQL
- JSON
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1POST /cli -d "
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1
"然而,需要注意的是,如果在两组节点上都执行该语句,将导致形成两个独立的集群,随后的网络恢复也不会使两组重新合并。