要理解如何添加带有远程代理的分布式表,首先需要基本了解 分布式表。本文将重点介绍如何使用分布式表作为创建 Manticore 实例集群的基础。
以下是一个将数据拆分到 4 台服务器上的示例,每台服务器负责一个分片:
- ini
table mydist {
type = distributed
agent = box1:9312:shard1
agent = box2:9312:shard2
agent = box3:9312:shard3
agent = box4:9312:shard4
}如果发生服务器故障,分布式表仍能工作,但来自故障分片的结果将会缺失。
现在我们已经添加了镜像,每个分片都位于 2 台服务器上。默认情况下,主节点(拥有分布式表的 searchd 实例)会随机选择一个镜像。
用于选择镜像的模式可以通过 ha_strategy 设置来配置。除了默认的 random 模式外,还有 ha_strategy = roundrobin。
基于延迟加权概率的更高级策略包括 noerrors 和 nodeads。这些策略不仅会排除有问题的镜像,还会监控响应时间并进行负载均衡。如果某个镜像响应较慢(例如,由于其上正在运行某些操作),它将收到更少的请求。当镜像恢复并提供更好的响应时间时,它将收到更多的请求。
- ini
table mydist {
type = distributed
agent = box1:9312|box5:9312:shard1
agent = box2:9312:|box6:9312:shard2
agent = box3:9312:|box7:9312:shard3
agent = box4:9312:|box8:9312:shard4
}对于使用 镜像 的任何 分布式表,默认情况下会启用负载均衡。默认情况下,查询会在镜像之间随机分配。您可以通过 ha_strategy 更改此行为。
ha_strategy = {random|nodeads|noerrors|roundrobin}
负载均衡的镜像选择策略是可选的,默认设置为 random。
ha_strategy 可以在 searchd 配置中全局设置,也可以针对每个分布式表进行设置。此指令控制镜像选择策略,换句话说,就是在分布式表中选择特定 代理镜像 的策略。实际上,此指令控制主节点如何在镜像代理节点之间平衡请求。已实现以下策略:
默认的平衡模式是在镜像之间进行简单的线性随机分配。每个镜像被分配相等的选择概率。这类似于轮询(RR),但不会强制执行严格的选择顺序。
- Config
- SQL
ha_strategy = randomCREATE TABLE products_dist type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='random';默认的简单随机策略不会考虑镜像的状态、错误率,最重要的是实际响应延迟。为了解决异构集群和代理节点负载的临时峰值问题,有一组基于查询延迟动态调整概率的平衡策略。
基于 延迟加权概率 的自适应策略工作方式如下。统计窗口的大小由 ha_period_karma 控制,而空闲镜像健康状态和往返跟踪则由 ha_ping_interval 驱动。两者将在本文档和 Searchd 设置 中进一步描述。
- 延迟统计以
ha_period_karma秒为一个块进行累积。 - 延迟加权概率每个 karma 周期重新计算一次。
- “存活或死亡”标志每次请求,包括 ping 请求时调整。
初始时概率相等。每一步概率按上一个 karma 周期内观察到的延迟的倒数进行缩放,然后归一化。例如,在主节点启动后前 60 秒内,4 个镜像的延迟分别为 10 毫秒、5 毫秒、30 毫秒和 3 毫秒,第一次调整步骤如下:
- 初始百分比:0.25, 0.25, 0.25, 0.25。
- 观察到的延迟:10 ms, 5 ms, 30 ms, 3 ms。
- 延迟倒数:0.1, 0.2, 0.0333, 0.333。
- 缩放后的百分比:0.025, 0.05, 0.008333, 0.0833。
- 归一化百分比:0.15, 0.30, 0.05, 0.50。
这意味着,在下一个 karma 周期内,第一个镜像被选中的概率为 15%,第二个为 30%,第三个(最慢,30 毫秒)仅为 5%,第四个(最快,3 毫秒)为 50%。之后,第二次调整步骤会再次更新这些概率,依此类推。
这个想法是,一旦 观察到的延迟 稳定,延迟加权概率 也会稳定。所有这些调整迭代旨在收敛到一个点,即所有镜像的平均延迟大致相等。
延迟加权概率,但连续失败次数过多的镜像将被排除在选择之外。只有完全成功的查询才会重置连续错误计数器。警告不会重置它。当某个镜像连续非成功结果超过 3 次时,它将被视为“死”镜像,因此前 3 次连续失败是可容忍的,但第 4 次失败将使该镜像在成功响应之前无法被 nodeads 选择。
- Config
- SQL
ha_strategy = nodeadsCREATE TABLE products_dist type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='nodeads';延迟加权概率,但近期错误/成功比率较差的镜像会被降级,甚至可能被排除在选择之外。
noerrors 会检查最近 ha_period_karma 窗口内收集的每个镜像的计数器。它首先比较关键传输失败(connect_timeouts、connect_failures、network_errors、wrong_replies、unexpected_closings)与总近期活动的比率。比率在 3% 及以下的被视为有效为零。如果多个镜像在此处并列,它会进一步比较包含警告回复的更广泛的错误比率。在最近窗口内完全没有成功查询的镜像将被完全跳过。
因此,noerrors 最适用于间歇性传输层故障和性能下降的镜像,而不是保证每个逻辑远程表问题立即消失。例如,如果一个镜像指向一个缺失的表,您可能在该镜像积累足够的不良历史记录之前仍然看到查询失败。使用 SHOW AGENT STATUS 检查每个镜像的近期成功、警告和网络错误。
- Config
- SQL
ha_strategy = noerrorsCREATE TABLE products_dist type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='noerrors';简单的轮询选择,即依次选择列表中的第一个镜像,然后是第二个,然后是第三个,依此类推,当到达列表中的最后一个镜像后,再重复该过程。与随机化策略不同,RR(轮询)强制执行一个严格的查询顺序(1, 2, 3, ..., N-1, N, 1, 2, 3, ... 等等),并保证在所有镜像都正常的情况下,不会将两个连续的查询发送到同一个镜像。
- Config
- SQL
ha_strategy = roundrobinCREATE TABLE products_dist type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='roundrobin';假设镜像分布式表已经存在,例如:
CREATE TABLE products_random type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products';
CREATE TABLE products_rr type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='roundrobin';
当您重复查询镜像分布式表时,random 和 roundrobin 的区别就会显现出来。
- SQL
SELECT node FROM products_random;
SELECT node FROM products_random;
SELECT node FROM products_rr;
SELECT node FROM products_rr;+-------+
| node |
+-------+
| node2 |
+-------+
+-------+
| node |
+-------+
| node1 |
+-------+
+-------+
| node |
+-------+
| node1 |
+-------+
+-------+
| node |
+-------+
| node2 |
+-------+SHOW AGENT STATUS 是镜像分布式表的主要调试工具。有关完整语句语法和所有输出格式,请参见 SHOW AGENT STATUS。就负载均衡而言,最有用的字段是:
ag_N_pingtripmsec- 镜像N的当前 ping 往返时间ag_N_errorsarow- 连续的非成功结果;这就是nodeads实际上监控的内容ag_N_1periods_connect_timeouts,connect_failures,network_errors,wrong_replies,unexpected_closings- 最近的传输失败ag_N_1periods_warnings- 成功但返回警告的回复ag_N_1periods_succeeded_queries- 最近的成功查询ag_N_1periods_msecsperquery- 最近的平均查询时间
这些每周期计数器会针对 1、5 和 15 个滚动窗口进行报告,每个窗口的长度为 ha_period_karma 秒。
在主节点上使用这些命令来检查已存储的内容以及镜像的行为。
- SQL
SHOW CREATE TABLE products_rr;
SHOW AGENT STATUS;
SHOW AGENT STATUS LIKE '%errorsarow%';
SHOW AGENT STATUS LIKE '%1periods_%';+---------------------------------+-------+
| Key | Value |
+---------------------------------+-------+
| ag_0_pingtripmsec | 0.233 |
| ag_0_errorsarow | 0 |
| ag_0_1periods_network_errors | 0 |
| ag_0_1periods_warnings | 0 |
| ag_0_1periods_succeeded_queries | 11 |
| ag_0_1periods_msecsperquery | n/a |
+---------------------------------+-------+实际解释:
- 如果
errorsarow上升到 3 以上,nodeads会开始将该镜像视为已死。 - 如果某个镜像没有最近的
succeeded_queries,noerrors会完全跳过它。 - 如果多个镜像的错误率较低,
noerrors仍然会优先选择延迟较低的镜像,因为正常的权重重新平衡机制仍然生效。 pingtripmsec帮助您区分“可到达但较慢”和“失败”的镜像。
与镜像、超时和重试相关的选项并非都在相同范围内得到支持。本页重点介绍它们如何影响负载均衡。如需完整的语法和守护进程级别的行为,请使用链接的参考页面。
| 选项 | 实例范围 | 每表 | 每查询 | 每代理 | 详细信息 |
|---|---|---|---|---|---|
ha_strategy |
是 | 是 | 否 | 是 | 负载均衡, 远程表 |
ha_period_karma |
是 | 否 | 否 | 否 | Searchd: ha_period_karma |
ha_ping_interval |
是 | 否 | 否 | 否 | Searchd: ha_ping_interval |
agent_connect_timeout |
是 | 是 | 否 | 否 | Searchd: agent_connect_timeout, 远程表: agent_connect_timeout |
agent_query_timeout |
是 | 是 | 是 | 否 | Searchd: agent_query_timeout, 远程表: agent_query_timeout |
agent_retry_count / mirror_retry_count / retry_count |
是 (agent_retry_count) |
是 (agent_retry_count 或 mirror_retry_count) |
是 (OPTION retry_count=...) |
是 (agent=...[retry_count=...]) |
Searchd: agent_retry_count, 远程表: agent_retry_count, 远程表: mirror_retry_count, 远程表: agent |
agent_retry_delay |
是 | 否 | 是 | 否 | Searchd: agent_retry_delay |
ha_strategy 控制如何选择镜像代理。它可以在 searchd 中全局设置,也可以在每个分布式表中设置,或者在 agent = ... [ha_strategy=...] 中每个代理内部设置。较窄的作用域会覆盖较宽的作用域。
上面的策略示例已经展示了全局和每表形式。有关每代理覆盖语法,请参见 远程表。
如果您希望某个分布式表使用与全局默认值不同的平衡策略,请在该表上设置它。
- Config
- SQL
ha_strategy = random
table products_rr {
type = distributed
agent = 127.0.0.1:9312|127.0.0.1:9313:products
ha_strategy = roundrobin
}CREATE TABLE products_rr type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='roundrobin';ha_period_karma 定义了上述自适应平衡策略使用的代理镜像统计窗口,仅支持作为实例范围的 searchd 设置。完整的守护进程级别详细信息请参见 Searchd: ha_period_karma。
- Config
ha_period_karma = 2mha_ping_interval 定义了对空闲镜像进行 ping 的频率,仅支持作为全局实例级的 searchd 设置。完整的守护进程级别详情请参见 Searchd: ha_ping_interval。
- Config
ha_ping_interval = 3sagent_connect_timeout 定义了 Manticore 等待与远程代理建立连接的时间。它支持作为全局实例默认值和每个分布式表的设置。完整详情请参见 Searchd: agent_connect_timeout 和 远程表: agent_connect_timeout。
- Config
- SQL
agent_connect_timeout = 300msCREATE TABLE products_dist type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
agent_connect_timeout='300ms';agent_query_timeout 定义了 Manticore 等待已连接的远程代理完成查询的时间。它支持作为全局实例默认值、每个分布式表以及每个查询的 OPTION agent_query_timeout=...。完整详情请参见 Searchd: agent_query_timeout 和 远程表: agent_query_timeout。
如果达到 agent_query_timeout,查询不会自动重试;而是会生成一个警告。
- Config
- SQL
agent_query_timeout = 500msSELECT * FROM products_dist OPTION agent_query_timeout=750;agent_retry_count 定义了 Manticore 在报告致命查询错误之前重试远程代理工作的次数。名称因作用域而异:使用 agent_retry_count 作为全局实例设置,在分布式表上使用 agent_retry_count 或其别名 mirror_retry_count,在每个查询中使用 OPTION retry_count=...,并在单个 agent=... 声明内部使用 [retry_count=...]。完整详情请参见 Searchd: agent_retry_count、远程表: agent_retry_count 和 远程表: mirror_retry_count。
如果您使用代理镜像,重试次数将在镜像之间汇总。每个代理的 [retry_count=...] 选项对该特定代理声明起到绝对上限的作用。
- Config
- SQL
table products_dist {
type = distributed
agent = 127.0.0.1:9312|127.0.0.1:9313:products[retry_count=2]
}SELECT * FROM products_dist OPTION retry_count=1;agent_retry_delay 定义了重试尝试之间的延迟时间。它支持作为全局实例默认值和每个查询的 OPTION retry_delay=...,但不支持每个分布式表。完整详情请参见 Searchd: agent_retry_delay。
当通过 agent_retry_count 或 OPTION retry_count=... 启用重试时,此选项才相关。
- Config
- SQL
agent_retry_delay = 500msSELECT * FROM products_dist OPTION retry_count=2, retry_delay=300;Agent 镜像在处理搜索查询时可以互换使用。托管分布式表的 Manticore 实例会跟踪镜像状态(存活或死亡)和响应时间,并基于这些信息执行自动故障转移和负载均衡。
agent = node1|node2|node3:9312:shard2
上面的示例声明 node1:9312、node2:9312 和 node3:9312 都有一个名为 shard2 的表,并且可以作为可互换的镜像使用。如果这些服务器中的任何一个宕机,查询将分布在其余的服务器之间。当服务器重新上线时,主节点会检测到并重新开始将查询路由到所有镜像。
镜像也可以包含单独的表列表,如下所示:
agent = node1:9312:node1shard2|node2:9312:node2shard2
这与前面的示例类似,但在查询不同服务器时会使用不同的表名。例如,查询 node1:9312 时将使用 node1shard2,查询 node2:9312 时将使用 node2shard2。
默认情况下,镜像选择使用全局或表级的 ha_strategy。如果您未显式设置它,默认策略是 random。主节点会存储每个代理的指标,如总查询数、错误数和响应时间,并将其分组到由 ha_period_karma 控制的时间段中。这些统计信息随后用于 Load balancing 中描述的平衡策略。
karma period 以秒为单位,默认为 60 秒。主节点为每个代理存储最多 15 个 karma 时间段的统计信息以供仪器使用(参见 SHOW AGENT STATUS)。但是,仅最后两个时间段用于 HA/LB 逻辑。
当没有查询时,主节点会定期发送 ping 命令,间隔为 ha_ping_interval,以收集统计信息并检查远程主机是否仍然存活。ha_ping_interval 默认为 1000 毫秒。将其设置为 0 会禁用 ping,统计信息将仅基于实际查询进行累积。结合 ha_period_karma,这控制镜像健康状况和延迟变化影响负载均衡的速度。
这一区别很重要:
- 一个
agent='host1|host2:table'条目表示一个具有镜像后端的远程分片。 - 多个
agent='...'条目表示多个远程分片。
例如:
# one shard, two mirrors
agent = node1|node2:9312:products
# two shards
agent = node1:9312:products_a
agent = node2:9312:products_b
镜像概念可以通过配置文件或 CREATE TABLE 进行配置。对于 TCP 连接,agent= 必须使用远程代理/API 端口(通常是 9312),而不是 MySQL 端口(9306)。如果您只想为一个分布式表设置特定的平衡策略,请在该表上设置 ha_strategy,而不是仅依赖全局默认值。
- Config
- SQL
table products_dist {
type = distributed
agent = 127.0.0.1:9312|127.0.0.1:9313:products
ha_strategy = roundrobin
}CREATE TABLE products_dist type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='roundrobin';假设镜像表已经存在,例如:
- SQL
CREATE TABLE products_dist type='distributed'
agent='127.0.0.1:9312:products|127.0.0.1:9313:products'
ha_strategy='roundrobin';从主节点正常使用分布式表,然后验证它是如何存储的以及镜像的行为。
- SQL
SELECT id, title, node FROM products_dist;
SHOW CREATE TABLE products_dist;
SHOW AGENT STATUS;+------+------------+-------+
| id | title | node |
+------+------------+-------+
| 1 | same title | node1 |
+------+------------+-------+
+---------------+----------------------------------------------------------------------------------+
| Table | Create Table |
+---------------+----------------------------------------------------------------------------------+
| products_dist | CREATE TABLE products_dist type='distributed' agent='127.0.0.1:9312:products|... |
+---------------+----------------------------------------------------------------------------------+在总共 4 台服务器上对表进行分片的示例,分为 2 个分片,每个分片有 2 个镜像。
- Config
# node1, node2 carry shard1 as local
# node3, node4 carry shard2 as local
# config on node1, node2
agent = node3:9312|node4:9312:shard2
# config on node3, node4
agent = node1:9312|node2:9312:shard1使用 Manticore,写事务(例如 INSERT、REPLACE、DELETE、TRUNCATE、UPDATE、COMMIT)可以在当前节点完全应用事务之前复制到其他集群节点。目前,复制支持 Linux 和 macOS 下的 percolate、rt 和 distributed 表。
Manticore 的 原生 Windows 二进制文件 不支持复制。我们推荐通过 WSL(Windows 子系统 Linux)安装 Manticore。
在 macOS 上,复制支持有限,仅建议用于开发目的。
Manticore 的复制由 Galera 库 提供支持,具有以下卓越功能:
- 真正的多主:随时可读取及写入任何节点。
- 几乎同步复制,无从属延迟及节点崩溃后无数据丢失。
- 热备份:切换时无停机(因为不存在故障转移)。
- 紧密耦合:所有节点保持相同状态,不允许节点间数据分歧。
- 自动节点配置:无需手动备份数据库并恢复到新节点。
- 易于使用和部署。
- 不可靠节点的检测及自动剔除。
- 基于认证的复制。
要在 Manticore Search 中设置复制:
- 配置文件中 "searchd" 部分必须设置 data_dir 选项。纯模式不支持复制。
- 必须指定一个包含其他节点可访问 IP 地址的 listen 指令,或一个有可访问 IP 的 node_address。
- 可以选择在每个集群节点上为 server_id 设置唯一值。如果未设置该值,节点将尝试使用 MAC 地址或随机数生成
server_id。
如果启用了身份验证和授权,集群操作需要 replication 权限。请将其授予应当拥有该集群复制操作的用户:
GRANT replication ON 'posts' TO 'repl_user';
CREATE CLUSTER 和 JOIN CLUSTER 可以通过 '<user>' AS user 指定该用户。参与该操作的各节点上必须存在该用户,且存储的认证数据必须匹配。仅在每个节点上独立创建相同的用户名和密码还不够,因为存储的认证数据可能不同。如果你在 daemon 之外更改了 auth data,请先在受影响的节点上运行 RELOAD AUTH,然后再使用集群操作。
后续的 ALTER CLUSTER ... ADD、ALTER CLUSTER ... DROP、ALTER CLUSTER ... UPDATE nodes 和 DELETE CLUSTER 会使用已存储的集群用户。启用身份验证时,成功执行的 JOIN CLUSTER 会用 donor 集群的认证数据替换加入节点上的所有本地认证数据。
如果没有设置 replication 类型的 listen 指令,Manticore 将在默认协议监听端口之后的 200 端口范围内为每个创建的集群使用前两个空闲端口。若要手动设置复制端口,必须定义 listen 指令(类型为 replication)的端口范围,且同一服务器不同节点的地址/端口范围不能交叉。通常,端口范围应为每个集群指定至少两个端口。当定义带端口范围的复制监听器(例如 listen = 192.168.0.1:9320-9328:replication)时,Manticore 不会立即在这些端口监听。它仅在开始使用复制时,从指定范围内随机选取空闲端口。
复制集群是一组节点,其中写事务被复制。复制是按表设置的,即一张表只能属于一个集群。集群中表的数量没有限制。属于集群的任何 percolate 或实时表上的所有事务如 INSERT、REPLACE、DELETE、TRUNCATE 都会复制到该集群的所有其他节点。分布式 表也可以参与复制过程。复制是多主的,因此对任何节点或多个节点同时写入均可正常工作。
创建集群通常使用命令 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 目录的相对路径指定。默认情况下,它设置为 data_dir 的值。
破坏性变更: 较早版本也会将传入的复制表文件存储在 cluster path 下。如果你使用了自定义的 cluster
path,升级时请格外小心,因为较早版本接收的复制表可能需要移动到正常的data_dir/<table>布局中,或者重新同步。
nodes 选项是集群所有节点的地址和端口对列表,以逗号分隔。该列表应通过节点的 API 接口获取,可以包含当前节点地址。用于加入集群以及重启后重新加入。
options 选项允许直接传递额外参数给 Galera 复制插件,详情请参见 Galera 文档参数。
在使用复制集群时,所有修改集群表内容的写语句,如 INSERT、REPLACE、DELETE、TRUNCATE、UPDATE,必须使用 cluster_name:table_name 表达式替代表名。这样可以确保变更传播到集群中的所有副本。如果不使用正确表达式,将触发错误。
在JSON接口中,所有写入集群表的语句都必须设置cluster属性以及table名称。如果没有设置cluster属性,将会导致错误。
- 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 文档参数 中找到可用选项的列表。
- 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集群状态变量值。如果所有服务器当前都在运行,无需重启集群。相反,可以使用SET语句将具有最高last_committed值的节点提升为primary component(如示例所示)。
其他节点将重新连接到主节点并根据该节点重新同步其数据。
- SQL
- JSON
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1POST /cli -d "
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1
"- 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:或在HTTP请求对象中使用cluster属性。
- 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;集群中所有修改表的查询现在都会复制到集群中的所有节点。