在大数据分析领域,随着数据量的迅猛增长,如何高效管理和利用数据成为了关键问题。Doris 作为一款强大的分析型数据库,其冷热分离功能为解决这一问题提供了有力的支持。本文将深入探讨 Doris 冷热分离的相关知识,包括其重要性、原理、使用方式、最佳实践以及常见问题解答等,帮助读者全面了解并掌握这一功能。
随着业务的发展,数据量呈爆发式增长。企业不仅需要存储海量数据,还面临着如何在保证查询性能的同时降低存储成本的挑战。在这种情况下,冷热分离技术应运而生。
在许多业务场景中,数据的访问频率具有明显的时间特征。近期产生的数据通常会被频繁查询和分析,这些数据被称为热数据。而随着时间的推移,数据的访问频率逐渐降低,这些数据则成为冷数据。如果将所有数据都存储在高性能、高成本的存储介质上,无疑会造成资源的浪费。因此,冷热分离的核心目的就是将热数据和冷数据分开存储,热数据存储在高性能的存储介质中以保证查询性能,冷数据则存储在低成本的存储介质中以降低存储成本,从而实现查询性能和存储成本的平衡。
以日志分析场景为例,新产生的日志数据对于实时监控和故障排查至关重要,需要快速查询和分析,属于热数据。而历史日志数据虽然访问频率较低,但出于合规性和偶尔的数据分析需求,仍需要长期保存,这些就是冷数据。通过冷热分离,将近期的日志数据存储在 Doris 的本地存储中,保证实时查询的高性能,而将历史日志数据存储到对象存储等低成本存储介质中,既能满足数据保存需求,又能大幅降低存储成本。
Doris 的冷热分离功能主要基于存储策略和资源管理来实现。用户可以创建不同的存储资源,如基于对象存储(如 S3 兼容模式、AZURE 模式)或 HDFS 的资源,并通过创建存储策略来指定数据何时以及如何移动到不同的存储资源上。
在 Doris 中,每个表或分区都可以绑定一个存储策略。当数据满足存储策略中定义的冷却条件(如达到指定的时间 TTL 或具体的冷却时间点)时,Doris 会自动将数据从本地存储迁移到指定的远程存储资源中,如对象存储。在查询时,Doris 会根据数据的存储位置,自动从相应的存储介质中读取数据。如果查询涉及到冷数据,Doris 会高效地从远程存储中获取数据并进行处理,同时结合本地缓存和优化的查询执行计划,尽量减少查询延迟,确保查询性能。
例如,创建一个存储策略,设置冷却时间为数据导入后的 1 天(即 cooldown_ttl = "1d"),并指定存储资源为一个 S3 兼容的对象存储资源。那么,在数据导入 Doris 一天后,符合条件的数据就会被自动迁移到该对象存储中。
CREATE RESOURCE "remote_s3"
PROPERTIES
(
"type" = "s3",
"s3.endpoint" = "bj.s3.com",
"s3.region" = "bj",
"s3.access_key" = "bbb",
"s3.secret_key" = "aaaa",
-- 以下为可选属性
"s3.root.path" = "prefix",
"s3.connection.maximum" = "50",
"s3.connection.request.timeout" = "3000",
"s3.connection.timeout" = "1000"
);
在创建 S3 兼容的存储资源时,需要指定关键的属性,如端点(s3.endpoint)、区域(s3.region)、访问密钥(s3.access_key)和秘密密钥(s3.secret_key)。可选属性如根路径(s3.root.path)可以用于在对象存储中指定一个特定的前缀路径来存储数据,连接最大数(s3.connection.maximum)等属性可以优化与对象存储的连接性能。
(1) 关于 path style:
Path style 和 Virtual hosted style:Virtual hosted style 是指将 Bucket 置于 Host Header 的访问方式。基于安全考虑,OSS 仅支持 virtual hosted 访问方式。所以在 S3 迁移至 OSS 后,客户端应用需要进行相应设置。部分 S3 工具默认使用 Path style,也需要进行相应配置,否则可能导致 OSS 报错,并禁止访问。可参考阿里云文档进行详细配置。
(2) AZURE 这类和 S3 不兼容的模式:
CREATE RESOURCE "remote_s3"
PROPERTIES
(
"type" = "azure",
"s3.endpoint" = "${ak}.blob.core.windows.net/",
"s3.region" = "bj",
"s3.access_key" = "bbb",
"s3.secret_key" = "aaaa",
-- 以下为可选属性
"s3.root.path" = "prefix",
"s3.connection.maximum" = "50",
"s3.connection.request.timeout" = "3000",
"s3.connection.timeout" = "1000"
);
对于 AZURE 模式,同样需要指定类型(type = "azure")以及相关的连接和认证信息。特别要注意的是,AZURE 的 endpoint 需要按照特定格式 "${ak}.blob.core.windows.net/" 填写,并且要清楚 AZURE blob 和 S3 之间概念的对应关系,如 AK 对应 AccountName,SK 对应 AccountKey,Bucket 对应 Container,Object 对应 Blob(在 Doris/Selectdb 中只使用 BlockBlob)。
使用如下语句创建基于 HDFS 的存储资源:
CREATE RESOURCE hdfs_resource PROPERTIES (
"type"="hdfs",
"fs.defaultFS" = "hdfs://10.220.147.151:8020",
"hadoop.username" = "root",
"password"="passwd",
"root_path"="prefix",
"dfs.nameservices" = "my_ha",
"dfs.ha.namenodes.my_ha" = "my_namenode1, my_namenode2",
"dfs.namenode.rpc-address.my_ha.my_namenode1" = "nn1_host:rpc_port",
"dfs.namenode.rpc-address.my_ha.my_namenode2" = "nn2_host:rpc_port",
"dfs.client.failover.proxy.provider" = "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider"
);
在创建 HDFS 资源时,需要详细指定 HDFS 的默认文件系统地址(fs.defaultFS)、用户名(hadoop.username)、密码(password)、根路径(root_path)等信息。如果是高可用的 HDFS 集群(HA),还需要配置相关的名称服务(dfs.nameservices)、名称节点(dfs.ha.namenodes.my_ha)以及它们的 RPC 地址等,以确保 Doris 能够正确连接和使用 HDFS 存储。
Doris 支持在不同磁盘类型(SSD 和 HDD)之间进行分层存储,结合动态分区功能,根据冷热数据的特性将数据从 SSD 动态迁移到 HDD。这种方式既降低了存储成本,又在热数据的读写上保持了高性能。
通过配置动态分区参数,用户可以设置哪些分区存储在 SSD 上,以及冷却后自动迁移到 HDD 上。
有关动态分区的更多信息,请参考:数据划分 - 动态分区。
基于这种做冷热分层比较简单,不需要创建存储策略,直接在建表的时候指定动态分区的策略就可以了,例如
CREATE TABLE tiered_table (k DATE)
PARTITION BY RANGE(k)()
DISTRIBUTED BY HASH (k) BUCKETS 5
PROPERTIES
(
"dynamic_partition.storage_medium" = "hdd",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.hot_partition_num" = "2",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "5",
"dynamic_partition.create_history_partition"= "true",
"dynamic_partition.start" = "-3"
);
在创建完存储资源之后,即可创建使用该资源的存储策略。例如:
CREATE STORAGE POLICY testPolicy
PROPERTIES(
"storage_resource" = "s3",
"cooldown_datetime" = "2024-06-08 00:00:00"
);
或
CREATE STORAGE POLICY testPolicy
PROPERTIES(
"storage_resource" = "s3",
"cooldown_ttl" = "1d"
);
第一个例子中,通过指定 cooldown_datetime 来设置数据在特定时间点进行冷却迁移。第二个例子则是通过设置 cooldown_ttl,让数据在导入后经过 1 天时间进行冷却迁移。在实际使用中,用户需要根据业务需求合理设置冷却条件。同时要注意,cooldown_ttl 不要设置得太短,因为每次 tablet 到达 cooldown_ttl 后都可能进行对象存储 IO,这会占据带宽且高频率的 IO 会产生费用。
而且,从最佳实践角度,建议是 tablet 做完 compaction 之后把版本 range 比较大的 rowset 上传到对象存储,否则多个冷数据 rowset 如果要做 cold compaction 则会把数据全部都下载到本地再次做 compaction 并且再次上传到对象存储,增加不必要的开销。
CREATE TABLE IF NOT EXISTS create_table_use_created_policy
(
k1 BIGINT,
k2 LARGEINT,
v1 VARCHAR(2048)
)
UNIQUE KEY(k1)
DISTRIBUTED BY HASH (k1) BUCKETS 3
PROPERTIES(
"enable_unique_key_merge_on_write" = "false",
"storage_policy" = "testPolicy"
);
★注意: UNIQUE 表如果设置了 "enable_unique_key_merge_on_write" = "true" 的话,无法使用此功能。
show proc '/dbs/10008/10013/partitions/'
返回结果中,RemoteStoragePolicy 表示绑定到 partition 的 storage policy,CooldownTime 表示 tablet 移动到冷存的时间。通过检查这些字段的值,用户可以明确 partition 的 cooldown 设置是否生效,以及数据预计何时会被迁移到冷存储中。
show tablets from $table_name;
show tablet $tablet_id;
然后执行 DetailCmd,例如:
SHOW PROC '/dbs/10008/10013/partitions/10012/10014/10029';
show backends;
grep "delete unused files" be.INFO | grep ${tablet_id}
grep "delete unused file" be.INFO | grep ${rowset_id}
这些日志记录了数据删除的相关信息,包括删除的文件、对应的 tablet 或 rowset 等。通过分析这些日志,用户可以了解数据删除的过程和原因,排查数据删除过程中出现的问题。
CREATE TABLE IF NOT EXISTS ${tableName} (
L_ORDERKEY INTEGER NOT NULL
)
DUPLICATE KEY(L_ORDERKEY, L_PARTKEY, L_SUPPKEY, L_LINENUMBER)
PARTITION BY RANGE(`L_SHIPDATE`)
(
PARTITION `p202301` VALUES LESS THAN ("1995-12-01") ("storage_policy" = "B"),
PARTITION `p202302` VALUES LESS THAN ("2017-03-01")
)
DISTRIBUTED BY HASH(L_ORDERKEY) BUCKETS 3
PROPERTIES (
"replication_num" = "1",
"storage_policy" = "B"
)
最后是按照整张表的 policy B 来设置各个 partition 的 policy B。如果需要修改 partition 的 policy,则可以手动 alter partition properties 来修改 partition 的 policy。用户在设置表和分区的存储策略时,需要明确这种优先级关系,根据实际业务需求进行合理配置,以确保数据按照预期的方式进行冷热分离存储。
failed to cooldown
:如果日志中出现 failed to get file size
报错,通常是非 cooldown 副本的同步问题:cooldowned version larger than that to follow with cooldown version
。多副本场景下,cooldown 副本可能发生切换,导致不同副本的冷却版本不一致:[0-11]
,后切换为副本 A 上传版本[0-7]
,副本 B 同步时发现本地版本(11)高于最新元数据版本(7),从而报错。cooldowned version is not aligned with version
,多副本冷却版本未对齐时触发,例如:[0-11]
,副本 A 同步时发现本地版本无法与[0-11]
对齐(如本地版本为[0-5]
),则会等待后续冷却完成。BE 的配置 generate_cooldown_task_interval_sec
可控制冷却任务的生成间隔(单位:秒),默认值根据集群规模自动调整。若冷却任务过于密集(如占用过多 IO),可适当调大该参数。
grep "cooldown producer get tablet num" be.INFO
(查看全局任务数量);grep cooldown be.INFO | grep ${tablet_id}
;grep ${tablet_id} be.INFO | grep rowset
(查看具体 rowset 的上传状态);grep ${tablet_id} be.INFO | grep "remove files in rowset"
(确认本地冷数据已被回收)。Doris 的冷热分离功能通过智能区分热数据(本地存储)和冷数据(对象存储 / HDFS),在保证查询性能的同时大幅降低存储成本,尤其适合日志分析、历史数据归档等场景。通过本文的指南,相信你已掌握 Doris 冷热分离的核心用法和最佳实践,可根据业务需求灵活配置,让数据管理更高效、成本更可控!
如有其他疑问或者方案欢迎留言讨论~
完