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%'

Show status result

目前,我们感兴趣的行是:cluster_namecluster_pet_shop_statuscluster_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 内运行一个新节点,使端口使用更简单。

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

第一个节点已经设置好,不需要更多额外的操作。简单吗?轻而易举!

向集群添加另一个节点

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

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

New node

或者在一个命令中完成所有操作:

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';

Connect to cluster and checking parameters

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

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

重要说明。 如果您要连接到集群的节点上有与集群中表同名的表,则节点上的表将被集群中的数据覆盖。集群数据优先于本地表,因此如果您连接一个已经有一些数据的现有节点,请确保现有表的名称与集群中的名称不同。并且一如既往,在任何风险情况下, 备份

管理集群中的数据

在集群中处理表数据时,有一些不同之处。插入命令现在需要一些调整——我们需要指定除了表名之外,还要指定其对应集群的名称: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 from add new record

根据结果,记录已添加,但另一个节点怎么样?
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)

因此,数据现在在节点之间自动传输,且没有太多复杂性,除了写命令中的小变化。

更改复制表的设置

What if we need to change the table configuration or delete it, for example, to update the wordforms file? In the previous article , we had to delete and recreate the table, leaving users without server responses for some time. In that example, the time needed to update the settings was very short because the table was small. But with larger data sets, tables with millions and billion of records, etc., updating and indexing can take a long time, often measured in hours. To ensure uninterrupted service for Manticore-based applications, there are distributed tables , but we will discuss this in another article.

对于现在,我们在几个节点上有一个复制的数据库,包含 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

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

现在让我们将形态学从词干提取器修改为词形还原器,重新索引记录,并重新连接所有内容。在 the previous article 中,我们使用一些粗略的方法替换了词形文件和词干提取器。在这里,我们将使用更文明的工具。所有替换词形文件或更改表中使用的形态学的操作都可以通过一个命令完成: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

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


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

今天就到这里!顺风顺水!我是 Mike,祝你好运!

安装Manticore Search

安装Manticore Search