blog-post

复制:创建集群、连接、更新表设置

关于我

Mike

你好,我是Mike。

我最近开始在Manticore担任开发倡导者。我是一个与IT并不完全陌生的人,但我正在追赶现代技术。在这个博客中,我将分享我的经验以及我对Manticore的学习。我计划以日志格式记录我的旅程,解释Manticore是什么以及如何使用它。让我们一起发现事物是如何协同工作的,识别问题,并与开发者实时互动。

这是我第一篇博客文章之一。如果你对与我一起学习Manticore感兴趣,我会通过以下渠道与你保持联系:

复制

复制的目的是什么?

上一篇文章 中,我们通过替换词形文件来更新全文搜索设置。在此过程中,我们的表暂时不可用。在我们的商店示例中,停机时间很短——只有几秒钟。对于小型项目来说,这样的短暂中断可能是增强便利性的微不足道的代价。然而,随着我们的商店扩展,增加更多产品和客户,对服务器设置的更改现在可能导致系统停机几个小时。数据库越大,重新索引的过程就越长。虽然使用Manticore进行重新索引只需几个小时——而不是几天或几周——我们还是希望避免这样的短暂延迟。此外,如果我们的单一服务器发生故障会怎样?或者如果客户端的数量对一台服务器来说过多?高速搜索引擎的所有优势都会丧失。因此,我们现在考虑创建多个同时并行运行的数据库副本。这样的设置将确保当数据写入一台服务器时,它会自动复制到其他连接的服务器或节点。

在Manticore中,节点之间的复制是通过 Galera库 实现的。Galera使用同步多主复制技术,为数据库集群提供高可用性和容错能力。当新记录被添加到其中一台服务器(节点)时,变更会即时传输到所有连接的节点。这个过程包括三个阶段:在源节点上的本地事务日志中写入、将更改复制到其他节点以及在事务实际应用之前确认所有节点已接收数据。只有在收到集群所有节点的确认后,事务才会被应用,这确保了所有节点的数据一致性。对于用户来说,这些过程是不可见的,任何节点对新数据的访问都是在该节点的事务成功完成后立即发生的。

初始设置

目前,我们在 上一篇文章 中创建的容器运行正常,但如果它停止并被删除,数据将永远丢失。 Manticore Docker指南 建议将数据目录映射到容器外。此外,我们上次所做的配置没有包括转发进行复制所需的二进制端口9312。让我们通过创建正在运行的容器的文件夹快照,并启动一个具有正确端口和存储设置的新容器来解决这个问题。

首先,我们需要确保数据完整性。我们进入容器,登录Manticore并“冻结”表,以便所有可能在内存中的数据将可靠地移动到磁盘上,并且在复制期间磁盘上的数据不会改变。

FREEZE products;

接下来,从容器中复制数据目录:

docker cp Manticore:/var/lib/manticore .

该命令由三个部分组成:

  • cp - 复制,
  • Manticore:/var/lib/manticore - 容器名称及其内部文件夹的路径,
  • . - 复制的本地路径,在此情况下为当前目录。

为了让当前容器继续像以前一样工作,我们“解冻”表:

UNFREEZE products;

现在,让我们以所需的设置创建一个新的容器:

docker run —name manticore_new -v $(pwd)/manticore:/var/lib/manticore -p 10306:9306 -p 10312:9312 -d manticoresearch/manticore
docker exec -it manticore_new mysql

最终,我们得到了一个具有转发端口和数据库文件在容器外的服务器上的位置的新容器的克隆。让我们检查一下新容器中的一切是否正常:

新容器视图

很好,所有数据已被转移,包括配置和词形文件,现在我们将基于此容器创建一个集群。

顺便提一下,关于词形文件的一点信息:在我们复制的文件夹中,有一个该文件的副本。我建议将其复制出来,因为未来的实践表明,你可能需要编辑它,而使用位于表格文件夹中的文件是一个坏主意,这最终可能导致一些问题。我在数据库文件夹外做了一个副本: cp manticore/products/wf_pet_products.txt wf_pet_products.txt。还有一些好消息,我和我的同事谈过了——不久你就不需要在使用 mysqldump 时手动移动词形文件,所有内容将自动保存在转储中。这是 任务 在 GitHub 上。

创建我们的第一个集群

要实现我们的新集群,不需要复杂的操作——只需使用一个命令创建一个名称的集群,然后将必要的表附加到其上。之后,我们只需检查一切是否设置正确。

  • 要添加一个集群,请使用 CREATE CLUSTER 命令。
  • 要将表添加到集群,请使用 ALTER CLUSTER ADD 命令。需要注意的是,聚类、复制和 Manticore 的其他功能仅对 实时表 可用!

所以,让我们创建第一个集群,并立即将我们的表添加到其中:

create cluster pet_shop;
alter cluster pet_shop add products;

现在让我们检查一下我们得到了什么。为此,请使用 show status 命令,但它会给出很多信息,为了避免迷失在其中,你可以使用带有 like 操作符的过滤器:

show status like '%cluster%'

显示状态结果

目前,我们感兴趣的行包括: cluster_name, cluster_pet_shop_status, cluster_pet_shop_indexes。这些显示了集群的名称,状态(如果显示为 Primary,那么一切都很好),以及当前在集群中的表。
我们还应该注意这一行 cluster_pet_shop_incoming_addresses。在我的设置中,它看起来是这样的: 172.17.0.5:9312,172.17.0.5:9315:replication。我们需要地址 172.17.0.5:9312。我们已将端口 9312 映射到 Docker 外部的端口 10312,但在示例中,我们将在同一个 Docker 网络 172.17.0.0 内部运行一个新节点,使得端口使用更简单。

从技术上讲,我们可以使用来自 关于词形的文章 的原始容器,只需将集群添加到其中并连接表。然后我们可以使用外部存储创建一个新容器,复制将所有内容复制到本地镜像。但那样我就无法展示如何通过从容器中复制文件夹来以另一种方式解决问题… =)
我们自作自受,然后再躺在上面。

第一个节点已经设置好,不需要任何其他操作。简单?这很轻松!

向集群添加另一个节点

首先,我们需要启动另一个 Manticore 容器。我们不会向它转移任何内容,只需将其连接到现有集群。本地存储必须不同(如果在同一服务器上进行此操作,连接的文件夹应该是不同的)。重要的是要提示端口,因为我们已经使用了端口 9306、10306 和 10312。因此,让我们分配不同的端口,例如 11306 和 11312。

我们创建另一个 Manticore 实例的容器,将其命名为 Manticore_new_1。我们指定端口 11306 和 11312,卷我们指定 manticore_new_1(本地文件夹必须已经存在)。

新节点

或者在一个命令中执行所有操作:

docker run --name manticore_new_1 -v $(pwd)/manticore_new_1:/var/lib/manticore -p 11306:9306 -p 11312:9312 -d manticoresearch/manticore

通过 MySQL 客户端登录。这是一个细节:如果你使用本地 MySQL 客户端连接,而不是容器内部的客户端,那么请使用在创建节点时指定的外部端口——11306。如果你使用 Docker 接口并通过容器终端进入(docker exec),则使用 Manticore 的默认端口——9306。在任何情况下,都要连接。是否有任何表(show tables)。结果意料之中是空的,因为我们刚刚创建了一个空的 Manticore 容器。现在将其连接到现有集群—— join cluster pet_shop at '172.17.0.5:9312';

连接到集群并检查参数

为了清晰起见,我将第二个节点的控制台颜色改了。

如我们所见,表已添加,记录数量与原始节点匹配,词干和词形文件的配置是正确的。
基本上就这些。集群已经组装并正常工作,数据在节点间传输。

重要提示。 如果你要连接到集群的节点的表名与集群中的表名相同,则该节点上的表将被集群中的数据覆盖。集群数据优先于本地表,因此如果你连接一个已经有一些数据的现有节点,请确保现有表的名称与集群中的名称不同。和往常一样,在任何冒险的情况下, 备份

管理集群中的数据

在集群中处理表数据时,有一些不同之处。插入命令现在需要一些调整——我们需要指定,除了表名外,还要指定其相应集群的名称: insert into <cluster name>: <table name>(<fields>) values (<values>)。不要忘记在你的客户端中更新此命令。

让我们在新创建的节点中添加另一条记录:

insert into pet_shop:products (name, info, price, avl) values ('Aquarium ship', 'Decorative ship model for aquarium', 6, 1);

添加新记录的结果

根据结果,记录已被添加,但另一个节点呢?
Result for second node

这里一切也都准备妥当!
让我们尝试更新数据:

mysql> update products set price = 8.0 where id = 3317338896206921730;
ERROR 1064 (42000): table products: table 'products' is a part of cluster 'pet_shop', use 'pet_shop:products'

对于更新、修改,尤其是删除记录,现在我们也需要在表名中指定集群名称:

update pet_shop:products set price = 8 where id = 3317338896206921730;
Query OK, 1 row affected (0.01 sec)

因此,现在数据在节点之间自动传输,没有太多复杂性,仅仅是在写命令上需要稍作变化。

更改复制表的设置

如果我们需要更改表的配置或删除它,例如,更新词形文件怎么处理?在 上一篇文章 中,我们不得不删除并重新创建表,这使用户在一段时间内无法获得服务器响应。在那个例子中,更新设置所需的时间非常短,因为表很小。但是对于更大的数据集、数百万和数十亿条记录的表等,更新和索引可能需要很长时间,通常是以小时来计算。为了确保基于 Manticore 的应用程序的服务不中断,有 分布式表 ,不过我们将在另一篇文章中讨论这个问题。

现在,我们在多个节点之间有一个复制的数据库,其中包含 products 表。我们可以通过使用集群名称前缀来更改此表的配置,但即使有前缀,我们也无法删除它。为了更改复制表的设置,首先将其从集群中断开连接: ALTER CLUSTER <cluster name> DROP <table name>。这将仅从集群中移除表,而不是从数据库中移除。表从集群中分离后,应用程序将无法更新数据,因为它引用了集群(例如,insert into pet_shop:products ...),而该表已不在其中(应用程序应该处理这种情况)。现在我们可以删除或重新配置该表。

例如,我们来更新表的配置:从词干分析器切换到词形分析器。以下是步骤:

  • 从集群中断开表。
  • 将表中的形态学从词干分析器更改为词形分析器。
  • 重新加载数据到表中。
  • 在集群中恢复该表。
  • 检查第二个节点。

从集群中断开表:

ALTER CLUSTER pet_shop DROP products;

现在集群中所有节点上的表均已与之断开,其架构和设置可以进行修改。我们的工作逻辑意味着在一个节点上进行一些技术工作,另一个节点则为用户处理 select 查询。作为保护措施,不再可能添加新记录,因为应用程序使用的命令格式为 <cluster>:<table>,而该表已不在集群中。

update pet_shop:products set price = 9 where id = 3317338896206921730;
ERROR 1064 (42000): table products: table 'products' is not in any cluster, use just 'products'

在我们将表从集群中分离后,让我们尝试执行 select 查询:

Result for other node

如我们所见,查询已被处理,数据已提供,最终用户应该感到满意。

现在让我们将形态学从词干分析器修改为词形分析器,重新索引记录,并重新连接所有内容。在 上一篇文章 中,我们使用一些粗略的方法替换了词形文件和词干分析器。在这里,我们将使用更为文明的工具。所有替换词形文件或更改表中使用的形态学的操作都可以通过一个命令完成:ALTER TABLE <table name> morphology='<morph type>'。让我们将我们的词干分析器替换为词形分析器:

ALTER TABLE products morphology='lemmatize_en_all';

在更改与数据库中文本预处理相关的任何参数后,必须重新索引所有现有记录,以便形态学和其他标记设置应用到旧文档中:

mysqldump -P9306 -h0 --replace --skip-comments manticore products | mysql -P9306 -h0;

在这里,我们使用 mysqldump 技术,将转储输出直接重定向到 Manticore 通过 MySQL。--replace 选项强制 mysqldump 生成 REPLACE 命令而不是 INSERT,从而允许我们一次“重新加载”整个表。请注意,对于大型表或在较弱的服务器上,此命令的执行时间可能很长,但这并不令我们感到害怕,因为我们有一个备份节点目前正在处理用户请求,并且 mysqldump 命令不会锁定表。

在对 products 表进行简单的重新配置后,我们得到了一个新版本:

New table

新设置和所有数据均已应用,现在让我们将该表添加回集群:

ALTER CLUSTER pet_shop ADD products;

就这样,该表现在所有服务器上都已更新,同时在我们配置和检查一切以确保正常工作的过程中,数据始终可供用户使用。

Other node

重要的是要注意在所有节点故障时整个集群的恢复 — 如果恢复顺序错误,可能会有丢失所有设置的风险。详细的恢复方法在 文档 中描述。


顺便说一下,您可以轻松地在我们的互动课程 play.manticoresearch.com. 中尝试复制。

今天就到此为止!祝顺利!我是 Mike,祝你好运!

安装Manticore Search

安装Manticore Search