ClickHouse官方文档翻译_引擎-表引擎-MergeTree系列-数据复制

Posted by Lance Lee on Tuesday, May 26, 2020

TOC

数据复制

复制仅支持MergeTree系列的表:

  • ReplicatedMergeTree
  • ReplicatedSummingMergeTree
  • ReplicatedReplacingMergeTree
  • ReplicatedAggregatingMergeTree
  • ReplicatedCollapsingMergeTree
  • ReplicatedVersionedCollapsingMergeTree
  • ReplicatedGraphiteMergeTree

复制工作在单个表的级别,而不是整个服务器。一个服务器可以同时存储复制表和非复制表。

复制不依赖于分片。每个shard都有自己独立的复制。

复制INSERTALTER查询的压缩数据(更多信息,请参考ALTER文档)。

CREATEDROPATTACHDETACHRENAME查询在单个服务器上执行,不复制:

  • CREATE TABLE查询在运行查询的服务器上创建一个新的可复制表。如果这个表已经存DROP TABLE查询删除运行查询的服务器上的副本。在于其他服务器上,它将添加一个新的副本。
  • DROP TABLE查询删除运行查询的服务器上的副本。
  • RENAME查询将重命名其中一个副本的对应表。换句话说,副本表在不同的副本上可以有不同的名称。【注意:根据副本引擎中的配置来区分而不是物理表名】

ClickHouse使用Apache ZooKeeper来存储副本元数据信息。使用ZooKeeper3.4.5或更新版本。

要使用复制,请在zookeeper服务器配置部分设置参数。

注意:不要忽视安全设置。ClickHouse支持ZooKeeper安全子系统的ACL摘要模式。

设定ZooKeeper集群地址的例子:

<zookeeper>
    <node index="1">
        <host>example1</host>
        <port>2181</port>
    </node>
    <node index="2">
        <host>example2</host>
        <port>2181</port>
    </node>
    <node index="3">
        <host>example3</host>
        <port>2181</port>
    </node>
</zookeeper>

您可以指定任意已有的ZooKeeper集群,系统将在Zookeeper集群上使用一个目录存储自己的数据(在创建副本表表时指定该目录)。

如果配置文件中没有设置ZooKeeper,就不能创建复制表,而且所有已有的复制表都是只读的。

ZooKeeper不用于SELECT查询,因此复制不会影响SELECT的性能,而且查询的运行速度与非复制表一样快。在查询分布式复制表时,ClickHouse的行为由设置max_replica_delay_for_distributed_queriesfallback_to_stale_replicas_for_distributed_queries控制。

对于每个INSERT查询,通过几个事务将大约10个条目添加到ZooKeeper。(更精确地说,这是针对每个插入的数据块;每个INSERT查询包含一个数据块或每max_insert_block_size = 1048576行一个数据块。)这导致与非复制表相比,INSERT的延迟稍微长一些。但是,如果按照建议以每秒不超过一次INSERT来批量插入数据,则不会产生任何问题。整个ClickHouse集群使用一个Zookeeper集群来协调,Zookeeper集群每秒总共有几百个INSERT。数据插入的吞吐量(每秒的行数)非复制数据一样高。

对于非常大的集群,可以为不同的分片使用不同的ZooKeeper集群。然而,在Yandex.Metrica集群上,这并不证明是必须的(大约300台服务器)。

复制是异步和多主机的。可以将INSERT查询(以及ALTER)发送到任何可用的服务器。数据被插入到运行查询的服务器上,然后被拷贝到其他服务器。因为它是异步的,所以最近插入的数据在其他副本上出现具有一定的延迟。如果部分副本不可用,数据将在变的可用时写入。如果副本是可用的,延迟就是通过网络传输压缩数据块所需的时间。

默认情况下,一个INSERT查询只需等待从一个副本获取数据写入的确认。如果数据只成功写入一个副本,并且具有此副本的服务器不复存在,则存储的数据将丢失。要启用从多个副本获取数据写入的确认,请使用insert_quorum选项。

每个数据块都是自动写入。INSERT查询被划分为最多为max_insert_block_size = 1048576行的块。换句话说,如果INSERT查询的行数小于1048576,那么它是自动生成的。

数据块会删除重复数据。对于同一数据块的多次写入(相同大小的数据块包含相同的行以相同的顺序),该数据块只写入一次。这样做的原因是网络故障的情形,当客户端应用程序不知道数据是否已写入数据库时,可以简单地重复INSERT查询。相同的数据发送到哪个副本INSERT并不重要。INSERT是等幂的。删除重复数据参数由merge_tree服务器设置控制。

在复制期间,只有要插入的源数据通过网络传输。此外,数据转换(合并)是协同的,在所有的副本上以相同的方式执行。这将最小化网络使用,这意味着当副本属于不同的数据中心时,复本可以很好地工作。(注意,在不同的数据中心复制数据是复制的主要目标。)

您可以相同数据拥有任意数量的副本。Yandex.Metrica在生产中使用双重复制。在某些情况下,每台服务器使用RAID-5RAID-6,以及RAID-10。这是一个相对可靠和方便的解决方案。

系统监视副本上的数据同步性,并且能够在出现故障后恢复。故障转移是自动的(对于数据中的小差异)或半自动的(当数据差异太大时,可能表示配置错误)。

创建可复制的表

在添加到表引擎名称中添加Replicated前缀。例如:ReplicatedMergeTree

Replicated*MergeTree 参数:

  • zoo_path — 表在Zookeeper中的路径。
  • replica_name — ZooKeeper中的副本名。
  • 其他参数 — 用于创建复制版本的引擎的参数,例如,ReplacingMergeTree中的版本。

例子:

CREATE TABLE table_name
(
    EventDate DateTime,
    CounterID UInt32,
    UserID UInt32,
    ver UInt16
) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{layer}-{shard}/table_name', '{replica}', ver)
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID))
SAMPLE BY intHash32(UserID)

已弃置语法的例子:

CREATE TABLE table_name
(
    EventDate DateTime,
    CounterID UInt32,
    UserID UInt32
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/table_name', '{replica}', EventDate, intHash32(UserID), (CounterID, EventDate, intHash32(UserID), EventTime), 8192)

如示例所示,这些花括号中的参数可以被替换。替换的值取自配置文件的macros部分。例子:

<macros>
    <layer>05</layer>
    <shard>02</shard>
    <replica>example05-02-1.yandex.ru</replica>
</macros>

对于每个复制表,ZooKeeper中表的路径应该是唯一的。表中的不同分片应该有不同的路径。 在这种情况下,路径由以下部分组成:

  • /clickhouse/tables/是共享的前缀。建议使用这个。
  • {layer}-{shard}是不同分片的标识符。由于Yandex.Metrica集群使用双层分片,这个例子由2部分组成。
  • table_name是ZooKeeper中表的节点名,使其与表名相同是一个好主意。它是显式定义的,因为与表名不同,它在RENAME查询之后不会更改。

提示:可以在table_name前面添加一个数据库名称。例如db_name.table_name

副本名称标识同一表的不同副本。可以使用服务器名,如本例所示。名称只需要在每个shard中是唯一的。

可以显式定义参数来取代使用替换。这对于测试和配置小型集群可能很方便。但是,在这种情况下,不能使用分布式DDL查询(在集群上)。

在处理大型集群时,我们建议使用替换,因为这样可以降低出错的概率。

在每个副本上运行CREATE TABLE查询。 这个查询创建一个新的复制表,或向现有表添加一个新的副本。

如果表在其他副本上已经包含一些数据后添加一个新的副本,那么在运行查询之后,这些数据将从其他副本复制到新的副本。 换句话说,新的副本与其他副本同步。

删除副本,运行DROP TABLE。 但是,只会删除运行查询的服务器上的副本。

失败后恢复

如果服务器启动时ZooKeeper不可用,则复制表切换到只读模式。系统定期尝试连接到ZooKeeper。

如果在INSERT期间ZooKeeper不可用,或者在与ZooKeeper交互时发生错误,则抛出异常。

连接到ZooKeeper之后,系统检查本地文件系统中的数据集与预期的数据集是否匹配(ZooKeeper存储这些信息)。如果有轻微的不一致,系统会通过与副本同步数据来解决这些问题。

如果系统检测到损坏的数据片段(文件大小错误)或无法识别的数据片段(写入文件系统但没有在ZooKeeper中记录的部分),则将它们移动到detached的子目录(它们没有被删除)。任何缺少的数据片段都会从副本中复制。

请注意,ClickHouse不执行任何破坏性操作,例如自动删除大量数据。

当服务器启动(或与ZooKeeper建立新会话)时,它只检查所有文件的数量和大小。如果文件大小匹配,但是字节在中间的某个地方发生了更改,则不会立即检测到这种情况,而是当在尝试使用SELECT查询读取数据时才会检测到。查询抛出一个数据校验不匹配或压缩数据块大小的异常。在这种情况下,数据片段被添加到验证队列中,并在必要时从副本中拷贝。

如果本地数据集与预期数据集差异太大,就会触发安全机制。服务器将其输入到日志中并拒绝启动。这样做的原因是,这种情况可能表明了配置错误,例如,如果一个分片上的副本被意外地配置为另一个分片上的副本。但是,此机制的阈值设置得相当低,这种情况可能发生在正常故障恢复期间。在这种情况下,数据是通过“按下按钮”来半自动恢复。

开始恢复时,在ZooKeeper中创建包含任何内容的节点/path_to_table/replica_name/flags/force_restore_data,或者运行命令来恢复所有复制的表:

sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data

然后重新启动服务器。在启动时,服务器删除这些标志并开始恢复。

数据完全丢失后恢复

如果所有数据和元数据从其中一台服务器上消失,请遵循以下步骤进行恢复:

  • 1.在服务器上安装ClickHouse。在包含分片标识符和副本(如果有使用的话)的配置文件中正确定义替换。
  • 2.如果您有在服务器上必须手动复制的未复制表,请从一个副本拷贝它们的数据(在/var/lib/clickhouse/data/db_name/table_name/目录中)。
  • 3.从一个副本拷贝位于/var/lib/clickhouse/metadata/中的表定义。如果在表结构定义中显式定义了分片或副本标识符,请纠正它,使其与此副本相对应。(或者,启动服务器,然后执行/var/lib/clickhouse/metadata/的.sql文件中ATTACH TABLE查询。)
  • 4.开始恢复时,在ZooKeeper中创建包含任何内容的节点/path_to_table/replica_name/flags/force_restore_data,或者运行命令来恢复所有复制的表:sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data

然后启动服务器(如果已经在运行,则重新启动)。数据将从副本下载。

另一个恢复选项是从ZooKeeper中删除关于丢失副本的信息(/path_to_table/replica_name),然后按照“创建复制表”中的描述再次创建副本。

在恢复期间对网络带宽没有限制。如果一次要还原多个副本,请记住这一点。

从 MergeTree 转换到 ReplicatedMergeTree

我们使用术语MergeTree来指代MergeTree系列中的所有表引擎,这与ReplicatedMergeTree相同。

如果您有一个手动复制的MergeTree表,可以将其转换为一个复制表。如果MergeTree表中已经有大量数据,并且现在希望启用复制,那么可能需要这样做。

如果不同的副本上的数据不同,那么首先同步它,或者删除除一个副本之外的所有副本上的数据。

重命名现有的MergeTree表,然后用旧名称创建一个ReplicatedMergeTree表。 将数据从旧表移动到新表数据目录(/var/lib/clickhouse/data/db_name/table_name/)中的detached 子目录。 然后在其中一个副本上运行ALTER TABLE ATTACH分区,将这些数据片段添加到工作集中。

从 ReplicatedMergeTree 转换到 MergeTree

创建一个具有不同名称的MergeTree表。移动ReplicatedMergeTree表的数据目录中的所有数据到新表的数据目录。然后删除ReplicatedMergeTree表并重新启动服务器。

如果你想在不启动服务器的情况下删除一个ReplicatedMergeTree表:

  • 删除元数据目录(/var/lib/clickhouse/metadata/)中相应的.sql文件。
  • 删除ZooKeeper(/path_to_table/replica_name)中的对应路径。
  • Delete the corresponding .sql file in the metadata directory

在此之后,您可以启动服务器,创建一个MergeTree表,将数据移动到其目录,然后重新启动服务器。

当Zookeeper集群中的元数据丢失或损坏时恢复

如果ZooKeeper中的数据丢失或损坏,可以按上面所述的将数据移动到未复制的表来保存数据。

「如果这篇文章对你有用,请支持一下哦」

Attack On Programmer

如果这篇文章对你有用,请支持一下哦

使用微信扫描二维码完成支付