TOC
数据复制
复制仅支持MergeTree系列的表:
- ReplicatedMergeTree
- ReplicatedSummingMergeTree
- ReplicatedReplacingMergeTree
- ReplicatedAggregatingMergeTree
- ReplicatedCollapsingMergeTree
- ReplicatedVersionedCollapsingMergeTree
- ReplicatedGraphiteMergeTree
复制工作在单个表的级别,而不是整个服务器。一个服务器可以同时存储复制表和非复制表。
复制不依赖于分片。每个shard都有自己独立的复制。
复制INSERT
和ALTER
查询的压缩数据(更多信息,请参考ALTER
文档)。
CREATE
,DROP
,ATTACH
,DETACH
和RENAME
查询在单个服务器上执行,不复制:
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_queries
和fallback_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-5
或RAID-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中的数据丢失或损坏,可以按上面所述的将数据移动到未复制的表来保存数据。
「如果这篇文章对你有用,请支持一下哦」
如果这篇文章对你有用,请支持一下哦
使用微信扫描二维码完成支付