ClickHouse 认识到,对于希望将存储与计算分离的用户来说,GCS 是一种很有吸引力的存储解决方案。为此,现已支持将 GCS 用作 MergeTree 引擎的存储后端。这样,您既可以利用 GCS 在可扩展性和成本方面的优势,也能获得 MergeTree 引擎的插入和查询性能。
要将 GCS 存储桶用作磁盘,首先必须在 conf.d 下的某个文件中,在 ClickHouse 配置里声明它。下面展示了一个 GCS 磁盘声明示例。此配置包含多个部分,分别用于配置 GCS“磁盘”、缓存,以及在需要在 GCS 磁盘上创建表时在 DDL queries 中指定的策略。下面将分别介绍这些部分。
配置中的这一部分显示在高亮区域,用于指定以下内容:
- 磁盘类型为
s3,因为这里使用的是 S3 API。
- GCS 提供的端点
- 服务账号的 HMAC 密钥和 secret
- 本地磁盘上的元数据路径
<clickhouse>
<storage_configuration>
<disks>
<gcs>
<support_batch_delete>true</support_batch_delete>
<type>s3</type>
<endpoint>https://storage.googleapis.com/BUCKET NAME/FOLDER NAME/</endpoint>
<access_key_id>SERVICE ACCOUNT HMAC KEY</access_key_id>
<secret_access_key>SERVICE ACCOUNT HMAC SECRET</secret_access_key>
<metadata_path>/var/lib/clickhouse/disks/gcs/</metadata_path>
</gcs>
</disks>
<policies>
<gcs_main>
<volumes>
<main>
<disk>gcs</disk>
</main>
</volumes>
</gcs_main>
</policies>
</storage_configuration>
</clickhouse>
下面高亮显示的示例配置会为 gcs 磁盘启用 10Gi 的内存缓存。
<clickhouse>
<storage_configuration>
<disks>
<gcs>
<support_batch_delete>true</support_batch_delete>
<type>s3</type>
<endpoint>https://storage.googleapis.com/BUCKET NAME/FOLDER NAME/</endpoint>
<access_key_id>SERVICE ACCOUNT HMAC KEY</access_key_id>
<secret_access_key>SERVICE ACCOUNT HMAC SECRET</secret_access_key>
<metadata_path>/var/lib/clickhouse/disks/gcs/</metadata_path>
</gcs>
<gcs_cache>
<type>cache</type>
<disk>gcs</disk>
<path>/var/lib/clickhouse/disks/gcs_cache/</path>
<max_size>10Gi</max_size>
</gcs_cache>
</disks>
<policies>
<gcs_main>
<volumes>
<main>
<disk>gcs_cache</disk>
</main>
</volumes>
</gcs_main>
</policies>
</storage_configuration>
</clickhouse>
存储配置策略可用于指定数据的存储位置。下面重点说明的策略通过指定 gcs_main,允许将数据存储在磁盘 gcs 上。例如:CREATE TABLE ... SETTINGS storage_policy='gcs_main'。
<clickhouse>
<storage_configuration>
<disks>
<gcs>
<support_batch_delete>true</support_batch_delete>
<type>s3</type>
<endpoint>https://storage.googleapis.com/BUCKET NAME/FOLDER NAME/</endpoint>
<access_key_id>SERVICE ACCOUNT HMAC KEY</access_key_id>
<secret_access_key>SERVICE ACCOUNT HMAC SECRET</secret_access_key>
<metadata_path>/var/lib/clickhouse/disks/gcs/</metadata_path>
</gcs>
</disks>
<policies>
<gcs_main>
<volumes>
<main>
<disk>gcs</disk>
</main>
</volumes>
</gcs_main>
</policies>
</storage_configuration>
</clickhouse>
此磁盘声明的相关设置完整列表可参见此处。
假设你已将磁盘配置为使用具有写入权限的 存储桶,那么你应该能够像下面的示例一样创建一个表。为简洁起见,我们只使用 NYC taxi 部分列,并将数据直接流式写入以 GCS 作为后端的表中:
CREATE TABLE trips_gcs
(
`trip_id` UInt32,
`pickup_date` Date,
`pickup_datetime` DateTime,
`dropoff_datetime` DateTime,
`pickup_longitude` Float64,
`pickup_latitude` Float64,
`dropoff_longitude` Float64,
`dropoff_latitude` Float64,
`passenger_count` UInt8,
`trip_distance` Float64,
`tip_amount` Float32,
`total_amount` Float32,
`payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4)
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(pickup_date)
ORDER BY pickup_datetime
SETTINGS storage_policy='gcs_main'
INSERT INTO trips_gcs SELECT trip_id, pickup_date, pickup_datetime, dropoff_datetime, pickup_longitude, pickup_latitude, dropoff_longitude, dropoff_latitude, passenger_count, trip_distance, tip_amount, total_amount, payment_type FROM s3('https://ch-nyc-taxi.s3.eu-west-3.amazonaws.com/tsv/trips_{0..9}.tsv.gz', 'TabSeparatedWithNames') LIMIT 1000000;
根据硬件配置不同,最后这次插入 100 万行数据可能需要几分钟才能完成。你可以通过 system.processes 表查看进度。你也可以将行数提高到 1000 万的上限,并尝试运行一些示例查询。
SELECT passenger_count, avg(tip_amount) AS avg_tip, avg(total_amount) AS avg_amount FROM trips_gcs GROUP BY passenger_count;
使用 GCS 磁盘时,可以通过 ReplicatedMergeTree 表引擎实现复制。详情请参阅使用 GCS 在两个 GCP 区域间复制单个分片指南。
Cloud Storage XML API 可与部分适用于 Amazon Simple Storage Service (Amazon S3) 等服务的工具和库互操作。
有关线程调优的更多信息,请参阅性能优化。
使用 Google Cloud Storage (GCS)
ClickHouse Cloud 默认使用对象存储;如果您运行在 ClickHouse Cloud 上,则无需遵循此流程。
本教程介绍如何在 Google Cloud 上部署一个复制的 ClickHouse 集群,并使用 Google Cloud Storage (GCS) 作为 ClickHouse 存储磁盘的“类型”。
在本教程中,您将在 Google Cloud Engine VM 中部署 ClickHouse 服务器 节点,并为每个节点关联一个 GCS 存储桶用于存储。复制由一组同样部署为 VM 的 ClickHouse Keeper 节点负责协调。
高可用性的示例要求:
- 两个 ClickHouse 服务器 节点,位于两个 GCP 区域
- 两个 GCS 存储桶,部署在与这两个 ClickHouse 服务器 节点相同的区域
- 三个 ClickHouse Keeper 节点,其中两个部署在与 ClickHouse 服务器 节点相同的区域。第三个可以与前两个 Keeper 节点中的一个位于同一区域,但需处于不同的可用区。
ClickHouse Keeper 至少需要两个节点才能正常工作,因此要实现高可用性,需要三个节点。
在三个区域部署五台虚拟机:
| 区域 | ClickHouse Server | 存储桶 | ClickHouse Keeper |
|---|
| 1 | chnode1 | bucket_regionname | keepernode1 |
| 2 | chnode2 | bucket_regionname | keepernode2 |
3 * | | | keepernode3 |
* 这也可以是在与 1 或 2 相同区域内的另一个可用区。
在两台主机上部署 ClickHouse;在示例配置中,这两台主机分别命名为 chnode1 和 chnode2。
将 chnode1 放在一个 GCP 区域中,将 chnode2 放在另一个区域中。本指南中,Compute Engine 虚拟机和 GCS 存储桶分别使用 us-east1 和 us-east4。
在完成配置之前,不要启动 clickhouse server,只需先安装即可。
在 ClickHouse 服务器 节点上执行部署步骤时,请参阅安装说明。
在三台主机上部署 ClickHouse Keeper。在示例配置中,这三台主机分别命名为 keepernode1、keepernode2 和 keepernode3。keepernode1 可部署在与 chnode1 相同的区域,keepernode2 可与 chnode2 部署在同一区域,keepernode3 则可部署在任一区域,但需与该区域中的 ClickHouse 节点位于不同的可用区。
在 ClickHouse Keeper 节点上执行部署步骤时,请参阅安装说明。
两个 ClickHouse 服务器将部署在不同区域中,以实现高可用性。每个服务器都会在相同区域中配备一个 GCS 存储桶。
在 Cloud Storage > Buckets 中选择 CREATE BUCKET。在本教程中,需要创建两个存储桶,分别位于 us-east1 和 us-east4。这些存储桶均为单区域、标准存储类别,且不公开。出现提示时,请启用公共访问防护。不要创建文件夹;ClickHouse 在写入存储时会自动创建它们。
如果你需要创建存储桶和 HMAC 密钥的分步说明,请展开 创建 GCS 存储桶和 HMAC 密钥 并按步骤操作:
ch_bucket_us_east1
ch_bucket_us_east4
生成访问密钥
创建服务账号 HMAC 密钥和密钥内容
打开 Cloud Storage > Settings > Interoperability,选择现有的 Access key,或选择 CREATE A KEY FOR A SERVICE ACCOUNT。本指南介绍的是为新的服务账号创建新密钥的流程。添加新的服务账号
如果该项目还没有现有服务账号,请选择 CREATE NEW ACCOUNT。创建服务账号共分三步。第一步,为该账号填写有意义的名称、ID 和描述。在 Interoperability 设置对话框中,推荐使用 IAM role Storage Object Admin;请在第二步选择该角色。第三步为可选项,本指南中不会用到。你可以根据自身策略决定是否向用户授予这些特权。系统会显示服务账号的 HMAC 密钥。请保存这些信息,因为稍后会在 ClickHouse 配置中使用。
除 server_id 这一行 (下方第一处高亮的行) 外,所有 ClickHouse Keeper 节点的配置文件都相同。请将文件中的主机名替换为你的 ClickHouse Keeper 服务器主机名,并在每台服务器上将 server_id 设置为与 raft_configuration 中对应 server 条目一致的值。由于此示例中的 server_id 设为 3,我们在 raft_configuration 中高亮了对应的行。
- 用你的主机名编辑此文件,并确保这些主机名能够被 ClickHouse 服务器 节点和 Keeper 节点解析
- 将文件复制到相应位置 (每台 Keeper 服务器上的
/etc/clickhouse-keeper/keeper_config.xml)
- 根据每台机器在
raft_configuration 中的条目编号,修改其 server_id
/etc/clickhouse-keeper/keeper_config.xml
<clickhouse>
<logger>
<level>trace</level>
<log>/var/log/clickhouse-keeper/clickhouse-keeper.log</log>
<errorlog>/var/log/clickhouse-keeper/clickhouse-keeper.err.log</errorlog>
<size>1000M</size>
<count>3</count>
</logger>
<listen_host>0.0.0.0</listen_host>
<keeper_server>
<tcp_port>9181</tcp_port>
<server_id>3</server_id>
<log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<session_timeout_ms>30000</session_timeout_ms>
<raft_logs_level>warning</raft_logs_level>
</coordination_settings>
<raft_configuration>
<server>
<id>1</id>
<hostname>keepernode1.us-east1-b.c.clickhousegcs-374921.internal</hostname>
<port>9234</port>
</server>
<server>
<id>2</id>
<hostname>keepernode2.us-east4-c.c.clickhousegcs-374921.internal</hostname>
<port>9234</port>
</server>
<server>
<id>3</id>
<hostname>keepernode3.us-east5-a.c.clickhousegcs-374921.internal</hostname>
<port>9234</port>
</server>
</raft_configuration>
</keeper_server>
</clickhouse>
最佳实践本指南中的某些步骤会要求你将配置文件放到 /etc/clickhouse-server/config.d/ 中。这是 Linux 系统中配置覆盖文件的默认位置。将这些文件放入该目录后,ClickHouse 会把其中的内容与默认配置合并。把这些文件放在 config.d 目录中,可以避免在升级时丢失配置。
默认情况下,ClickHouse 仅监听回环接口;在启用复制的部署中,机器之间必须能够进行网络通信。请监听所有接口:
/etc/clickhouse-server/config.d/network.xml
<clickhouse>
<listen_host>0.0.0.0</listen_host>
</clickhouse>
复制由 ClickHouse Keeper 负责协调。此配置文件通过主机名和端口号指定 ClickHouse Keeper 节点。
/etc/clickhouse-server/config.d/use-keeper.xml
<clickhouse>
<zookeeper>
<node index="1">
<host>keepernode1.us-east1-b.c.clickhousegcs-374921.internal</host>
<port>9181</port>
</node>
<node index="2">
<host>keepernode2.us-east4-c.c.clickhousegcs-374921.internal</host>
<port>9181</port>
</node>
<node index="3">
<host>keepernode3.us-east5-a.c.clickhousegcs-374921.internal</host>
<port>9181</port>
</node>
</zookeeper>
</clickhouse>
此文件用于配置集群中每个 ClickHouse 服务器的主机名和端口。默认配置文件包含示例集群定义;为了只显示已完整配置的集群,需要在 remote_servers 条目中添加 replace="true" 标签。这样,当此配置与默认配置合并时,它会替换 remote_servers 部分,而不是在其中追加内容。
- 用你的主机名编辑此文件,并确保这些主机名可从 ClickHouse 服务器节点解析
/etc/clickhouse-server/config.d/remote-servers.xml
<clickhouse>
<remote_servers replace="true">
<cluster_1S_2R>
<shard>
<replica>
<host>chnode1.us-east1-b.c.clickhousegcs-374921.internal</host>
<port>9000</port>
</replica>
<replica>
<host>chnode2.us-east4-c.c.clickhousegcs-374921.internal</host>
<port>9000</port>
</replica>
</shard>
</cluster_1S_2R>
</remote_servers>
</clickhouse>
此文件用于配置与 ClickHouse Keeper 路径相关的设置。具体来说,是配置用于标识数据所属副本的宏。在一台服务器上,副本应指定为 replica_1,而在另一台服务器上则应指定为 replica_2。这些名称可以更改;根据我们的示例,如果一个副本存储在南卡罗来纳,另一个存储在北弗吉尼亚,那么相应的值也可以设为 carolina 和 virginia;只需确保它们在每台机器上各不相同即可。
/etc/clickhouse-server/config.d/macros.xml
<clickhouse>
<distributed_ddl>
<path>/clickhouse/task_queue/ddl</path>
</distributed_ddl>
<macros>
<cluster>cluster_1S_2R</cluster>
<shard>1</shard>
<replica>replica_1</replica>
</macros>
</clickhouse>
ClickHouse 存储配置包含 disks 和 policies。下面配置的磁盘名为 gcs,其 type 为 s3。之所以使用 s3 类型,是因为 ClickHouse 访问 GCS 存储桶时,会将其视为 AWS S3 存储桶。此配置需要准备两份,每个 ClickHouse 服务器 节点各一份。
需要在下面的配置中进行以下替换。
以下替换项在两个 ClickHouse 服务器 节点之间有所不同:
REPLICA 1 BUCKET 应设置为与 server 位于同一区域的存储桶名称
REPLICA 1 FOLDER 应在其中一个 server 上改为 replica_1,在另一个 server 上改为 replica_2
以下替换项在两个节点上相同:
access_key_id 应设置为之前生成的 HMAC Key
secret_access_key 应设置为之前生成的 HMAC Secret
/etc/clickhouse-server/config.d/storage.xml
<clickhouse>
<storage_configuration>
<disks>
<gcs>
<support_batch_delete>true</support_batch_delete>
<type>s3</type>
<endpoint>https://storage.googleapis.com/REPLICA 1 BUCKET/REPLICA 1 FOLDER/</endpoint>
<access_key_id>SERVICE ACCOUNT HMAC KEY</access_key_id>
<secret_access_key>SERVICE ACCOUNT HMAC SECRET</secret_access_key>
<metadata_path>/var/lib/clickhouse/disks/gcs/</metadata_path>
</gcs>
<cache>
<type>cache</type>
<disk>gcs</disk>
<path>/var/lib/clickhouse/disks/gcs_cache/</path>
<max_size>10Gi</max_size>
</cache>
</disks>
<policies>
<gcs_main>
<volumes>
<main>
<disk>gcs</disk>
</main>
</volumes>
</gcs_main>
</policies>
</storage_configuration>
</clickhouse>
使用适合您所用操作系统的命令,例如:
sudo systemctl enable clickhouse-keeper
sudo systemctl start clickhouse-keeper
sudo systemctl status clickhouse-keeper
使用 netcat 向 ClickHouse Keeper 发送命令。例如,mntr 会返回 ClickHouse Keeper 集群的状态信息。如果在每个 Keeper 节点上运行该命令,你会看到其中一个是 leader,另外两个是跟随者:
echo mntr | nc localhost 9181
zk_version v22.7.2.15-stable-f843089624e8dd3ff7927b8a125cf3a7a769c069
zk_avg_latency 0
zk_max_latency 11
zk_min_latency 0
zk_packets_received 1783
zk_packets_sent 1783
zk_num_alive_connections 2
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count 135
zk_watch_count 8
zk_ephemerals_count 3
zk_approximate_data_size 42533
zk_key_arena_size 28672
zk_latest_snapshot_size 0
zk_open_file_descriptor_count 182
zk_max_file_descriptor_count 18446744073709551615
zk_followers 2
zk_synced_followers 2
在 chnode1 和 chnode 上运行:
sudo service clickhouse-server start
sudo service clickhouse-server status
system.disks 中应包含每个磁盘对应的记录:
SELECT *
FROM system.disks
FORMAT Vertical
Row 1:
──────
name: cache
path: /var/lib/clickhouse/disks/gcs/
free_space: 18446744073709551615
total_space: 18446744073709551615
unreserved_space: 18446744073709551615
keep_free_space: 0
type: s3
is_encrypted: 0
is_read_only: 0
is_write_once: 0
is_remote: 1
is_broken: 0
cache_path: /var/lib/clickhouse/disks/gcs_cache/
Row 2:
──────
name: default
path: /var/lib/clickhouse/
free_space: 6555529216
total_space: 10331889664
unreserved_space: 6555529216
keep_free_space: 0
type: local
is_encrypted: 0
is_read_only: 0
is_write_once: 0
is_remote: 0
is_broken: 0
cache_path:
Row 3:
──────
name: gcs
path: /var/lib/clickhouse/disks/gcs/
free_space: 18446744073709551615
total_space: 18446744073709551615
unreserved_space: 18446744073709551615
keep_free_space: 0
type: s3
is_encrypted: 0
is_read_only: 0
is_write_once: 0
is_remote: 1
is_broken: 0
cache_path:
3 rows in set. Elapsed: 0.002 sec.
create table trips on cluster 'cluster_1S_2R' (
`trip_id` UInt32,
`pickup_date` Date,
`pickup_datetime` DateTime,
`dropoff_datetime` DateTime,
`pickup_longitude` Float64,
`pickup_latitude` Float64,
`dropoff_longitude` Float64,
`dropoff_latitude` Float64,
`passenger_count` UInt8,
`trip_distance` Float64,
`tip_amount` Float32,
`total_amount` Float32,
`payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4))
ENGINE = ReplicatedMergeTree
PARTITION BY toYYYYMM(pickup_date)
ORDER BY pickup_datetime
SETTINGS storage_policy='gcs_main'
┌─host───────────────────────────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.us-east4-c.c.gcsqa-375100.internal │ 9000 │ 0 │ │ 1 │ 1 │
└────────────────────────────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
┌─host───────────────────────────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode1.us-east1-b.c.gcsqa-375100.internal │ 9000 │ 0 │ │ 0 │ 0 │
└────────────────────────────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
2 rows in set. Elapsed: 0.641 sec.
INSERT INTO trips SELECT
trip_id,
pickup_date,
pickup_datetime,
dropoff_datetime,
pickup_longitude,
pickup_latitude,
dropoff_longitude,
dropoff_latitude,
passenger_count,
trip_distance,
tip_amount,
total_amount,
payment_type
FROM s3('https://ch-nyc-taxi.s3.eu-west-3.amazonaws.com/tsv/trips_{0..9}.tsv.gz', 'TabSeparatedWithNames')
LIMIT 1000000
SELECT
engine,
data_paths,
metadata_path,
storage_policy,
formatReadableSize(total_bytes)
FROM system.tables
WHERE name = 'trips'
FORMAT Vertical
Row 1:
──────
engine: ReplicatedMergeTree
data_paths: ['/var/lib/clickhouse/disks/gcs/store/631/6315b109-d639-4214-a1e7-afbd98f39727/']
metadata_path: /var/lib/clickhouse/store/e0f/e0f3e248-7996-44d4-853e-0384e153b740/trips.sql
storage_policy: gcs_main
formatReadableSize(total_bytes): 36.42 MiB
1 row in set. Elapsed: 0.002 sec.
在 Google Cloud Console 中验证
查看这些存储桶时,你会看到系统已在每个存储桶中创建了一个文件夹,名称与 storage.xml 配置文件中使用的名称相同。展开这些文件夹后,你会看到许多文件,对应各个数据分区。