clickhouse 多磁盘存储策略

 


说明

MergeTree 系列表引擎可以将数据存储在多个块设备上。这对某些可以潜在被划分为“冷”“热”的表来说是很有用的。最新数据被定期的查询但只需要很小的空间。相反,详尽的历史数据很少被用到。如果有多块磁盘可用,那么“热”的数据可以放置在快速的磁盘上(比如 NVMe 固态硬盘或内存),“冷”的数据可以放在相对较慢的磁盘上(比如机械硬盘)。

数据片段是 MergeTree 引擎表的最小可移动单元。属于同一个数据片段的数据被存储在同一块磁盘上。数据片段会在后台自动的在磁盘间移动,也可以通过 ALTER 查询来移动。

配置

<storage_configuration>
    <disks>
        <disk_name_1> <!-- disk name -->
            <path>/mnt/fast_ssd/clickhouse/</path>
        </disk_name_1>
        <disk_name_2>
            <path>/mnt/hdd1/clickhouse/</path>
            <keep_free_space_bytes>10485760</keep_free_space_bytes>
        </disk_name_2>
        <disk_name_3>
            <path>/mnt/hdd2/clickhouse/</path>
            <keep_free_space_bytes>10485760</keep_free_space_bytes>
        </disk_name_3>

        ...
    </disks>

    ...
</storage_configuration>
<disk_name_N> — 磁盘名,名称必须与其他磁盘不同.
path — 服务器将用来存储数据 (data 和 shadow 目录) 的路径, 应当以 ‘/’ 结尾.
keep_free_space_bytes — 需要保留的剩余磁盘空间.

存储策略(Storage Policies)

存储策略定义了数据在多个存储设备(磁盘、卷)上的分布规则,支持冷热数据分层、多磁盘负载均衡等功能。
磁盘(Disk):表示一个物理存储设备(如本地磁盘、SSD、HDD、S3 等)。

卷(Volume):由多个磁盘组成的逻辑存储单元,可定义数据的冗余和分层策略。

存储策略(Storage Policy):定义数据在卷之间的分布规则(如优先写入热卷,冷卷作为备份)。

卷类型(Volume Types)

卷是存储策略的核心组件,支持多种类型以实现不同存储目标:

基础卷(Simple Volume)

定义:将数据均匀分布在卷内的所有磁盘上。

场景:负载均衡,避免单磁盘 I/O 瓶颈。

配置示例

<storage_configuration>
  <disks>
    <disk1> <path>/data1/</path> </disk1>
    <disk2> <path>/data2/</path> </disk2>
  </disks>
  <policies>
    <default>
      <volumes>
        <default>  <!-- 卷名称 -->
          <disk>disk1</disk>
          <disk>disk2</disk>
        </default>
      </volumes>
    </default>
  </policies>
</storage_configuration>

分层卷(Tiered Volume)

定义:数据按时间或策略在不同卷之间迁移(如热卷 → 冷卷)。

场景:冷热数据分离,优化存储成本。

配置示例

<storage_configuration>
  <disks>
    <ssd> <path>/mnt/ssd/</path> </ssd>
    <hdd> <path>/mnt/hdd/</path> </hdd>
  </disks>
  <policies>
    <hot_cold>
      <volumes>
        <hot>      <!-- 热卷 -->
          <disk>ssd</disk>
        </hot>
        <cold>     <!-- 冷卷 -->
          <disk>hdd</disk>
        </cold>
      </volumes>
    </hot_cold>
  </policies>
</storage_configuration>

冗余卷(Replicated Volume)

定义:数据在卷内的多个磁盘上冗余存储。

场景:提高数据可靠性(类似 RAID 1)。
<storage_configuration>
  <disks>
    <disk1> <path>/data1/</path> </disk1>
    <disk2> <path>/data2/</path> </disk2>
  </disks>
  <policies>
    <replicated>
      <volumes>
        <replicated_volume>
          <disk>disk1</disk>
          <disk>disk2</disk>
          <max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
        </replicated_volume>
      </volumes>
    </replicated>
  </policies>
</storage_configuration>

配置存储策略

定义磁盘和卷

<storage_configuration>
  <disks>
    <fast_ssd> <path>/mnt/ssd/</path> </fast_ssd>
    <slow_hdd> <path>/mnt/hdd/</path> </slow_hdd>
    <s3_storage> <!-- S3 磁盘 -->
      <type>s3</type>
      <endpoint>https://s3.amazonaws.com/your-bucket/</endpoint>
      <access_key_id>AKIAXXX</access_key_id>
      <secret_access_key>XXXXXX</secret_access_key>
    </s3_storage>
  </disks>
  <policies>
    <tiered_policy>
      <volumes>
        <hot>        <!-- 热数据卷 -->
          <disk>fast_ssd</disk>
        </hot>
        <cold>       <!-- 冷数据卷 -->
          <disk>slow_hdd</disk>
        </cold>
        <archive>    <!-- 归档数据卷 -->
          <disk>s3_storage</disk>
        </archive>
      </volumes>
    </tiered_policy>
  </policies>
</storage_configuration>

创建表时指定存储策略

CREATE TABLE logs (
    timestamp DateTime,
    message String
) ENGINE = MergeTree
ORDER BY timestamp
SETTINGS storage_policy = 'tiered_policy';  -- 指定存储策略

数据迁移与冷热分层

手动迁移数据

ALTER TABLE logs MOVE PARTITION '2023-10-01' TO VOLUME 'cold';

自动迁移(TTL 规则)

ALTER TABLE logs MODIFY TTL 
    timestamp + INTERVAL 7 DAY TO VOLUME 'cold',
    timestamp + INTERVAL 30 DAY TO VOLUME 'archive';

存储策略的应用场景

场景 存储策略配置 优势
冷热数据分离 热数据在 SSD,冷数据在 HDD,归档数据在 S3 优化性能,降低成本
负载均衡 数据均匀分布在多个磁盘 避免单磁盘 I/O 瓶颈
数据冗余 数据在多个磁盘上复制 提高可靠性
云存储集成 热数据在本地磁盘,冷数据在 S3 弹性扩展存储容量

数据迁移策略

<storage_configuration>
    ...
    <policies>
        <policy_name_1>
            <volumes>
                <volume_name_1>
                    <disk>disk_name_from_disks_configuration</disk>
                    <max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
                    <load_balancing>round_robin</load_balancing>
                </volume_name_1>
                <volume_name_2>
                    <!-- configuration -->
                </volume_name_2>
                <!-- more volumes -->
            </volumes>
            <move_factor>0.2</move_factor>
        </policy_name_1>
        <policy_name_2>
            <!-- configuration -->
        </policy_name_2>

        <!-- more policies -->
    </policies>
    ...
</storage_configuration>
policy_name_N — 策略名称。策略名称必须是唯一的。

volume_name_N — 卷名称。卷名称必须是唯一的。

disk — 卷内的磁盘。

max_data_part_size_bytes — 可以在卷的任何磁盘上存储的部分的最大大小。如果合并的部分大小估计大于max_data_part_size_bytes,则此部分将写入下一个卷。基本上,此功能允许将新的/较小的部分保存在热的(SSD)卷上,并在它们达到较大大小时将它们移动到冷的(HDD)卷上。如果您的策略只有一个卷,请不要使用此设置。

move_factor — 当可用空间低于此因子时,数据会自动移动到下一个卷(默认为0.1)。ClickHouse按大小从大到小(降序)排序现有部分,并选择总大小足以满足move_factor条件的部分。如果所有部分的总大小不足,所有部分都将被移动。

perform_ttl_move_on_insert — 禁用数据部分插入时的TTL移动。默认情况下(如果启用),如果插入一个已根据TTL移动规则过期的数据部分,它将立即移动到移动规则中声明的卷/磁盘。如果目标卷/磁盘速度较慢(例如S3),这可能会显著减慢插入速度。如果禁用,则已过期的数据部分将写入默认卷,然后立即移动到TTL卷。

load_balancing - 磁盘平衡的策略,round_robin或least_used。

least_used_ttl_ms - 配置更新所有磁盘上可用空间的超时时间(以毫秒为单位)(0表示始终更新,-1表示从不更新,默认为60000)。注意,如果磁盘只能由ClickHouse使用并且不受在线文件系统调整大小/缩小的影响,则可以使用-1,在所有其他情况下不建议这样做,因为这最终会导致空间分布不正确。

prefer_not_to_merge — 不应使用此设置。禁用此卷上的数据部分合并(这有害并导致性能下降)。当启用此设置时(请不要这样做),不允许在此卷上合并数据(这不好)。这允许(但不需要)控制ClickHouse与慢盘的工作方式(不建议使用此设置)。

volume_priority — 定义填充卷的优先级(顺序)。数值越低,优先级越高。参数值应为自然数,从1到N(最低优先级)连续覆盖,不要跳过任何数字。如果所有卷都被标记了,它们将按给定的顺序优先。如果只有部分卷被标记,没有标记的卷具有最低优先级,并且它们按配置中定义的顺序优先。如果没有卷被标记,它们的优先级将按照它们在配置中声明的顺序相应设置。两个卷不能有相同的优先级值。

示例

<storage_configuration>
    ...
    <policies>
        <hdd_in_order> <!-- policy name -->
            <volumes>
                <single> <!-- volume name -->
                    <disk>disk1</disk>
                    <disk>disk2</disk>
                </single>
            </volumes>
        </hdd_in_order>

        <moving_from_ssd_to_hdd>
            <volumes>
                <hot>
                    <disk>fast_ssd</disk>
                    <max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
                </hot>
                <cold>
                    <disk>disk1</disk>
                </cold>
            </volumes>
            <move_factor>0.2</move_factor>
        </moving_from_ssd_to_hdd>

        <small_jbod_with_external_no_merges>
            <volumes>
                <main>
                    <disk>jbod1</disk>
                </main>
                <external>
                    <disk>external</disk>
                </external>
            </volumes>
        </small_jbod_with_external_no_merges>
    </policies>
    ...
</storage_configuration>
在给出的例子中, hdd_in_order 策略实现了循环方法。因此这个策略只定义了一个卷(single),数据片段会以循环的顺序全部存储到它的磁盘上。当有多个类似的磁盘挂载到系统上,但没有配置 RAID 时,这种策略非常有用。请注意一个每个独立的磁盘驱动都并不可靠,您可能需要用3份或更多的复制份数来补偿它。

如果在系统中有不同类型的磁盘可用,可以使用 moving_from_ssd_to_hdd。hot 卷由 SSD 磁盘(fast_ssd)组成,这个卷上可以存储的数据片段的最大大小为 1GB。所有大于 1GB 的数据片段都会被直接存储到 cold 卷上,cold 卷包含一个名为 disk1 的 HDD 磁盘。 同样,一旦 fast_ssd 被填充超过 80%,数据会通过后台进程向 disk1 进行转移。

存储策略中卷的枚举顺序是很重要的。因为当一个卷被充满时,数据会向下一个卷转移。磁盘的枚举顺序同样重要,因为数据是依次存储在磁盘上的。

策略应用

CREATE TABLE table_with_non_default_policy (
    EventDate Date,
    OrderID UInt64,
    BannerID UInt64,
    SearchPhrase String
) ENGINE = MergeTree
ORDER BY (OrderID, BannerID)
PARTITION BY toYYYYMM(EventDate)
SETTINGS storage_policy = 'moving_from_ssd_to_hdd'

参考文档

https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree#table_engine-mergetree-multiple-volumes

posted @   小吉猫  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示

目录导航