在数据剖析的实际场景中,冷热数据往往面临着不同的查询频次及响应速度要求。例如在电商订单场景中,用户常常拜访近 6 个月的订单,时刻较长远的订单拜访次数十分少;在行为剖析场景中,需支撑近期流量数据的高频查询且时效性要求高,但为了确保历史数据随时可查,往往要求数据保存周期更为长远;在日志剖析场景中,历史数据的拜访频次很低,但需长时刻备份以确保后续的审计和回溯的工作…往往历史数据的应用价值会跟着时刻推移而下降,且需求应对的查询需求也会随之锐减。而跟着历史数据的不断增多,假如咱们将一切数据存储在本地,将形成很多的资源糟蹋。

为了处理满意以上问题,冷热数据分层技能应运而生,以更好满意企业降本增效的趋势。望文生义,冷热分层是将 热数据 别离 存储在 本钱不同 的存储介质上,例如热数据存储在本钱更高的 SSD 盘上、以进步时效数据的查询速度和响应才能,而冷数据则存储在相对低本钱的 HDD 盘甚至更为廉价的目标存储上,以下降存储本钱。咱们还能够依据实际业务需求进行灵敏的装备和调整,以满意不同场景的要求。

冷热分层一般适用于以下需求场景:

  • 数据存储周期长:面对历史数据的不断添加,存储本钱也随之添加;

  • 冷热数据拜访频率及功用要求不同:热数据拜访频率高且需求快速响应,而冷数据拜访频率低且响应速度要求不高;

  • 数据备份和康复本钱高:备份和康复很多数据需求消耗很多的时刻和资源。

  • ……

更高存储功率的冷热分层技能

自 Apache Doris 0.12 版别引进动态分区功用,开始支撑对表分区进行生命周期办理,能够设置热数据转冷时刻以及存储介质标识,经过后台任务将热数据从 SSD 主动冷却到 HDD,以协助用户较大程度地下降存储本钱。用户能够在建表特点中装备参数 storage_cooldown_time 或许 dynamic_partition.hot_partition_num 来控制数据从 SSD 冷却到 HDD,当分区满意冷却条件时,Doris 会主动履行任务。而 HDD 上的数据是以多副本的方法存储的,并没有做到最大程度的本钱节省,因而对于冷数据存储本钱依然有较大的优化空间。

为了协助用户进一步下降存储本钱,社区在已有功用进步行了优化,并在 Apache Doris 2.0 版别中推出了冷热 数据 分层的功用。冷热数据分层功用使 Apache Doris 能够将冷数据下沉到存储本钱愈加低价的目标存储中,一起冷数据在目标存储上的保存方法也从多副本变为单副本,存储本钱进一步降至原先的三分之一,一起也削减了因存储附加的核算资源本钱和网络开支本钱。

如下图所示,在 Apache Doris 2.0 版别中支撑三级存储,别离是 SSD、HDD 和目标存储。用户能够装备使数据从 SSD 下沉到 HDD,并运用冷热分层功用将数据从 SSD 或许 HDD 下沉到目标存储中。

Apache Doris 冷热分层技术如何实现存储成本降低 70%?

以公有云价格为例,云磁盘的价格一般是目标存储的 5-10 倍,假如能够将 80% 的冷数据保存到目标存储中,存储本钱至少可下降 70%。

咱们运用以下公式核算节省的本钱,设冷数据比率为 rate,目标存储价格为 OSS,云磁盘价格为 CloudDisk

1−rate∗100∗OSS+(1−rate)∗100∗CloudDisk100∗CloudDisk1 – \frac{rate * 100 * OSS + (1 – rate) * 100 * CloudDisk}{100 * CloudDisk}

这儿咱们假定用户有 100TB 的数据,咱们依照不同比例将冷数据迁移到目标存储,来核算一下假如运用冷热分层之后,相较于全量运用普通云盘、SSD 云盘 可节省 多少 本钱

  • 阿里云 OSS 标准存储本钱是 120 元/ T /月
  • 阿里云普通云盘的价格是 300 元/ T /月
  • 阿里云 SSD 云盘的价格是 1000 元/ T /月

Apache Doris 冷热分层技术如何实现存储成本降低 70%?

例如在 80% 冷数据占比的情况下,剩下 20% 运用普通云盘每月仅花费 80T120 + 20T * 300 = 15600元,而全量运用普通云盘则需求花费 30000 元,经过冷热数据分层节省了 48% 的存储本钱。假如用户运用的是 SSD 云盘,那么花费则会从全量运用需花费的 100000 元下降到 80T120 + 20T * 1000 = 29600元,存储本钱最高下降超越 70%!

运用指南

若要运用 Doris 的冷热分层功用,首要需求预备一个目标存储的 Bucket 并获取对应的 AK/SK。当预备就绪之后,下面为详细的运用过程:

1. 创立 Resource

能够运用目标存储的 Bucket 以及 AK/SK 创立 Resource,现在支撑 AWS、Azure、阿里云、华为云、腾讯云、百度云等多个云的目标存储。

CREATE RESOURCE IF NOT EXISTS "${resource_name}"
        PROPERTIES(
            "type"="s3",
            "s3.endpoint" = "${S3Endpoint}",
            "s3.region" = "${S3Region}",
            "s3.root.path" = "path/to/root",
            "s3.access_key" = "${S3AK}",
            "s3.secret_key" = "${S3SK}",
            "s3.connection.maximum" = "50",
            "s3.connection.request.timeout" = "3000",
            "s3.connection.timeout" = "1000",
            "s3.bucket" = "${S3BucketName}"
        );

2. 创立 Storage Policy

能够经过 Storage Policy 控制数据冷却时刻,现在支撑相对和肯定两种冷却时刻的设置。

CREATE STORAGE POLICY testPolicy
PROPERTIES(
  "storage_resource" = "remote_s3",
  "cooldown_ttl" = "1d"
);

例如上方代码中名为 testPolicystorage policy 设置了新导入的数据将在一天后开始冷却,而且冷却后的冷数据会存放到 remote_s3 所表示的目标存储的 root path 下。除了设置 TTL 以外,在 Policy 中也支撑设置冷却的时刻点,能够直接设置为:

CREATE STORAGE POLICY testPolicyForTTlDatatime
PROPERTIES(
  "storage_resource" = "remote_s3",
  "cooldown_datetime" = "2023-06-07 21:00:00"
);

3. 给表或许分区设置 Storage Policy

在创立出对应的 Resource 和 Storage Policy 之后,咱们能够在建表的时分对整张表设置 Cooldown Policy,也能够针对某个 Partition 设置 Cooldown Policy。这儿以 TPCH 测验数据集中的 lineitem 表举例。假如需求将整张表都设置冷却的战略,则能够直接在整张表的 properties 中设置:

CREATE TABLE IF NOT EXISTS lineitem1 (
            L_ORDERKEY    INTEGER NOT NULL,
            L_PARTKEY     INTEGER NOT NULL,
            L_SUPPKEY     INTEGER NOT NULL,
            L_LINENUMBER  INTEGER NOT NULL,
            L_QUANTITY    DECIMAL(15,2) NOT NULL,
            L_EXTENDEDPRICE  DECIMAL(15,2) NOT NULL,
            L_DISCOUNT    DECIMAL(15,2) NOT NULL,
            L_TAX         DECIMAL(15,2) NOT NULL,
            L_RETURNFLAG  CHAR(1) NOT NULL,
            L_LINESTATUS  CHAR(1) NOT NULL,
            L_SHIPDATE    DATEV2 NOT NULL,
            L_COMMITDATE  DATEV2 NOT NULL,
            L_RECEIPTDATE DATEV2 NOT NULL,
            L_SHIPINSTRUCT CHAR(25) NOT NULL,
            L_SHIPMODE     CHAR(10) NOT NULL,
            L_COMMENT      VARCHAR(44) NOT NULL
            )
            DUPLICATE KEY(L_ORDERKEY, L_PARTKEY, L_SUPPKEY, L_LINENUMBER)
            PARTITION BY RANGE(`L_SHIPDATE`)
            (
                PARTITION `p202301` VALUES LESS THAN ("2017-02-01"),
                PARTITION `p202302` VALUES LESS THAN ("2017-03-01")
            )
            DISTRIBUTED BY HASH(L_ORDERKEY) BUCKETS 3
            PROPERTIES (
            "replication_num" = "3",
            "storage_policy" = "${policy_name}"
            )

用户能够经过 show tablets 获得每个 Tablet 的信息,其中 CooldownReplicaId 不为 -1 而且 CooldownMetaId 不为空的 Tablet 阐明运用了 Storage Policy。如下方代码,经过 show tablets 能够看到上面的 Table 的一切 Tablet 都设置了 CooldownReplicaId 和 CooldownMetaId,这阐明整张表都是运用了 Storage Policy。

               TabletId: 3674797
              ReplicaId: 3674799
              BackendId: 10162
             SchemaHash: 513232100
                Version: 1
      LstSuccessVersion: 1
       LstFailedVersion: -1
          LstFailedTime: NULL
          LocalDataSize: 0
         RemoteDataSize: 0
               RowCount: 0
                  State: NORMAL
LstConsistencyCheckTime: NULL
           CheckVersion: -1
           VersionCount: 1
              QueryHits: 0
               PathHash: 8030511811695924097
                MetaUrl: http://172.16.0.16:6781/api/meta/header/3674797
       CompactionStatus: http://172.16.0.16:6781/api/compaction/show?tablet_id=3674797
      CooldownReplicaId: 3674799
         CooldownMetaId: TUniqueId(hi:-8987737979209762207, lo:-2847426088899160152)

咱们也能够对某个详细的 Partition 设置 Storage Policy,只需求在 Partition 的 Properties 中加上详细的 Policy Name 即可:

CREATE TABLE IF NOT EXISTS lineitem1 (
            L_ORDERKEY    INTEGER NOT NULL,
            L_PARTKEY     INTEGER NOT NULL,
            L_SUPPKEY     INTEGER NOT NULL,
            L_LINENUMBER  INTEGER NOT NULL,
            L_QUANTITY    DECIMAL(15,2) NOT NULL,
            L_EXTENDEDPRICE  DECIMAL(15,2) NOT NULL,
            L_DISCOUNT    DECIMAL(15,2) NOT NULL,
            L_TAX         DECIMAL(15,2) NOT NULL,
            L_RETURNFLAG  CHAR(1) NOT NULL,
            L_LINESTATUS  CHAR(1) NOT NULL,
            L_SHIPDATE    DATEV2 NOT NULL,
            L_COMMITDATE  DATEV2 NOT NULL,
            L_RECEIPTDATE DATEV2 NOT NULL,
            L_SHIPINSTRUCT CHAR(25) NOT NULL,
            L_SHIPMODE     CHAR(10) NOT NULL,
            L_COMMENT      VARCHAR(44) NOT NULL
            )
            DUPLICATE KEY(L_ORDERKEY, L_PARTKEY, L_SUPPKEY, L_LINENUMBER)
            PARTITION BY RANGE(`L_SHIPDATE`)
            (
                PARTITION `p202301` VALUES LESS THAN ("2017-02-01") ("storage_policy" = "${policy_name}"),
                PARTITION `p202302` VALUES LESS THAN ("2017-03-01")
            )
            DISTRIBUTED BY HASH(L_ORDERKEY) BUCKETS 3
            PROPERTIES (
            "replication_num" = "3"
            )

这张 Lineitem1 设置了两个分区,每个分区 3 个 Bucket,别的副本数设置为 3,能够核算出一共有 23 = 6 个 Tablet,那么副本数一共是 63 = 18 个 Replica,经过 show tablets 指令能够检查到一切的 Tablet 以及 Replica 的信息,能够看到只要部分 Tablet 的 Replica 是设置了CooldownReplicaId 和 CooldownMetaId 。用户能够经过 ADMIN SHOW REPLICA STATUS FROM TABLE PARTITION(PARTITION)`` 检查 Partition 下的 Tablet 以及Replica,经过比照能够发现其中只要归于 p202301 这个 Partition 的 Tablet 的 Replica 设置了CooldownReplicaId 和 CooldownMetaId,而归于 p202302 这个 Partition 下的数据没有设置,所以依旧会悉数存放到本地磁盘。 以上表的 Tablet 3691990 为例,该 Tablet 归于 p202301,截取 show tablets 拿到的部分关键信息如下:

*****************************************************************
               TabletId: 3691990
              ReplicaId: 3691991
      CooldownReplicaId: 3691993
         CooldownMetaId: TUniqueId(hi:-7401335798601697108, lo:3253711199097733258)
*****************************************************************
               TabletId: 3691990
              ReplicaId: 3691992
      CooldownReplicaId: 3691993
         CooldownMetaId: TUniqueId(hi:-7401335798601697108, lo:3253711199097733258)
*****************************************************************
               TabletId: 3691990
              ReplicaId: 3691993
      CooldownReplicaId: 3691993
         CooldownMetaId: TUniqueId(hi:-7401335798601697108, lo:3253711199097733258)

能够观察到 3691990 的 3 个副本都选择了 3691993 副本作为 CooldownReplica,在用户指定的 Resource 上也只会保存这个副本的数据。

4. 检查数据信息

咱们能够依照上述 3 中的 Linetem1 来演示如何检查是运用冷热数据分层战略的 Table 的数据信息,一般能够经过 show tablets from lineitem1 直接检查这张表的 Tablet 信息。Tablet 信息中区分了 LocalDataSize 和 RemoteDataSize,前者表示存储在本地的数据,后者表示现已冷却并移动到目标存储上的数据。详细信息可见下方代码:

下方为数据刚导入到 BE 时的数据信息,能够看到数据还悉数存储在本地。

*************************** 1. row ***************************
               TabletId: 2749703
              ReplicaId: 2749704
              BackendId: 10090
             SchemaHash: 1159194262
                Version: 3
      LstSuccessVersion: 3
       LstFailedVersion: -1
          LstFailedTime: NULL
          LocalDataSize: 73001235
         RemoteDataSize: 0
               RowCount: 1996567
                  State: NORMAL
LstConsistencyCheckTime: NULL
           CheckVersion: -1
           VersionCount: 3
              QueryHits: 0
               PathHash: -8567514893400420464
                MetaUrl: http://172.16.0.8:6781/api/meta/header/2749703
       CompactionStatus: http://172.16.0.8:6781/api/compaction/show?tablet_id=2749703
      CooldownReplicaId: 2749704
         CooldownMetaId:

当数据抵达冷却时刻后,再次进行 show tablets from table 能够看到对应的数据变化。

*************************** 1. row ***************************
               TabletId: 2749703
              ReplicaId: 2749704
              BackendId: 10090
             SchemaHash: 1159194262
                Version: 3
      LstSuccessVersion: 3
       LstFailedVersion: -1
          LstFailedTime: NULL
          LocalDataSize: 0
         RemoteDataSize: 73001235
               RowCount: 1996567
                  State: NORMAL
LstConsistencyCheckTime: NULL
           CheckVersion: -1
           VersionCount: 3
              QueryHits: 0
               PathHash: -8567514893400420464
                MetaUrl: http://172.16.0.8:6781/api/meta/header/2749703
       CompactionStatus: http://172.16.0.8:6781/api/compaction/show?tablet_id=2749703
      CooldownReplicaId: 2749704
         CooldownMetaId: TUniqueId(hi:-8697097432131255833, lo:9213158865768502666)

除了经过上述指令检查数据信息之外,咱们也能够在目标存储上检查冷数据的信息。以腾讯云为例,能够在 Policy 指定的 Bucket 的 Path 下能够检查冷却过后的数据的信息:

Apache Doris 冷热分层技术如何实现存储成本降低 70%?

进入对应文件后能够看到数据和元数据文件

Apache Doris 冷热分层技术如何实现存储成本降低 70%?

咱们能够看到在目标存储上数据是单副本。

Apache Doris 冷热分层技术如何实现存储成本降低 70%?

5. 查询

假定 Table Lineitem1 中的一切数据都现已冷却而且上传到目标存储中,假如用户在 Lineitem1 进步行对应的查询,Doris 会依据对应 Partition 运用的 Policy 信息找到对应的 Bucket 的 Root Path,并依据不同 Tablet 下的 Rowset 信息下载查询所需的数据到本地进行运算。

Doris 2.0 在查询进步行了优化,冷数据第一次查询会进行完好的 S3 网络 IO,并将 Remote Rowset 的数据下载到本地后,存放到对应的 Cache 之中,后续的查询将主动射中 Cache,以此来确保查询功率。(功用比照可见后文评测部分)。

6. 冷却后继续导入数据

在某些场景下,用户需求对历史数据进行数据的修正或弥补数据,而新数据会依照分区列信息导入到对应的 Partition中。在 Doris 中,每次数据导入都会产生一个新的 Rowset,以确保冷数据的 Rowset 在不会影响新导入数据的 Rowset 的前提下,满意冷热数据一起存储的需求。Doris 2.0 的冷热分层粒度是根据 Rowset 的,当抵达冷却时刻时会将当前满意条件的 Rowset 悉数上传到 S3 上并删去本地数据,之后新导入的数据生成的新 Rowset 会在抵达冷却时刻后也上传到 S3。

查询功用测验

为了测验运用冷热分层功用之后,查询目标存储中的数据是否占用会较大网络 I/O,然后影响查询功用,因而咱们以 SSB SF100 标准集为例,对冷热分层表和非冷热分层表进行了查询耗时的比照测验。

装备:均在 3 台 16C 64G 的机器上部署 1FE、3BE 的集群

暂时无法在飞书文档外展示此内容

如上图所示,在充分预热之后(数据现已缓存在 Cache 中),冷热分层表共耗时 5.799s,非冷热分层表共耗时 5.822s,由此可知,运用冷热分层查询表和非冷热分层表的查询功用几乎相同。这表明,运用 Doris 2.0 供给的冷热分层功用,不会对查询功用形成的影响。

冷热分层技能的详细完成

存储方法的优化

在 Doris 之前的版别中,数据从 SSD 冷却到 HDD 后,为了确保数据的高可用和牢靠性,一般会将一个 Tablet 存储多份副本在不同 BE 上,为了进一步下降本钱,咱们在 Apache Doris 2.0 版别引进了目标存储,推出了冷热分层功用。由于目标存储本身具有高牢靠高可用性,冷数据在目标存储上只需求一份即可,元数据以及热数据依然保存在 BE,咱们称之为本地副本,本地副本同步冷数据的元数据,这样就能够完成多个本地副本共用一份冷却数据的目的,有用防止冷数据占用过多的存储空间,然后下降数据存储本钱。

详细而言,Doris 的 FE 会从 Tablet 的一切可用本地副本中选择一个本地副本作为上传数据的 Leader,并经过 Doris 的周期报告机制同步 Leader 的信息给其它本地副本。在 Leader 上传冷却数据时,也会将冷却数据的元数据上传到目标存储,以便其他副本同步元数据。因而,任何本地副本都能够供给查询所需的数据,一起也确保了数据的高可用性和牢靠性。

Apache Doris 冷热分层技术如何实现存储成本降低 70%?

冷数据 Compaction

在一些场景下会有很多修补数据的需求,在很多补数据的场景下往往需求删去历史数据,删去能够经过 delete where完成,Doris 在 Compaction 时会对契合删去条件的数据做物理删去。根据这些场景,冷热分层也有必要完成对冷数据进行 Compaction,因而在 Doris 2.0 版别中咱们支撑了对冷却到目标存储的冷数据进行 Compaction(ColdDataCompaction)的才能,用户能够经过冷数据 Compaction,将分散的冷数据重新组织并压缩成更紧凑的格式,然后削减存储空间的占用,进步存储功率。

Doris 对于本地副本是各自进行 Compaction,在后续版别中会优化为单副本进行 Compaction。由于冷数据只要一份,因而天然的单副本做 Compaction 是最优异方案,一起也会简化处理数据抵触的操作。BE 后台线程会定时从冷却的 Tablet 依照必定规矩选出 N 个 Tablet 发起 ColdDataCompaction。与数据冷却流程类似,只要 CooldownReplica 能履行该 Tablet 的 ColdDataCompaction。Compaction下刷数据时每堆集必定巨细(默许5MB)的数据,就会上传一个 Part 到目标,而不会占用很多本地存储空间。Compaction 完成后,CooldownReplica 将冷却数据的元数据更新到目标存储,其他 Replica 只需从目标存储同步元数据,然后很多削减目标存储的 IO 和节点本身的 CPU 开支。

冷数据 Cache

冷数据 Cache 在数据查询中具有重要的效果。冷数据一般是数据量较大、运用频率较低的数据,假如每次查询都需求从目标中读取,会导致查询功率低下。经过冷数据 Cache 技能,能够将冷数据缓存在本地磁盘中,进步数据读取速度,然后进步查询功率。而 Cache 的粒度巨细直接影响 Cache 的功率,比较大的粒度会导致 Cache 空间以及带宽的糟蹋,过小粒度的 Cache 会导致目标存储 IO 功率低下,Apache Doris 选用了以 Block 为粒度的 Cache 完成。

如前文所述,Apache Doris 的冷热分层会将冷数据上传到目标存储上,上传成功后本地的数据将会被删去。因而,后续涉及到冷数据的查询均需求对目标存储发起 IO 。为了优化功用,Apache Doris 完成了根据了 Block 粒度的 Cache 功用,当远程数据被拜访时会先将数据依照 Block 的粒度下载到本地的 Block Cache 中存储,且 Block Cache 中的数据拜访功用和非冷热分层表的数据功用一致(可见后文查询功用测验)。

详细来讲,前文提到 Doris 的冷热分层是在 Rowset 等级进行的,当某个 Rowset 在冷却后其一切的数据都会上传到目标存储上。而 Doris 在进行查询的时分会读取涉及到的 Tablet 的 Rowset 进行数据聚合和运算,当读取到冷却的 Rowset 时,会把查询需求的冷数据下载到本地 Block Cache 之中。根据功用考量,Doris 的 Cache 依照 Block 对数据进行区分。Block Cache 本身选用的是简略的 LRU 战略,能够确保越是运用程度较高数据越能在 Block Cache 中存放的久。

结束语

Apache Doris 2.0 版别完成了根据目标存储的冷热数据分层,该功用能够协助咱们有用下降存储本钱、进步存储功率,并进步数据查询和处理功率。未来,Apache Doris 将会根据冷热数据分层以及弹性核算节点,为用户供给更好的资源弹性、更低的运用本钱以及更灵敏的负载隔离服务。

在前段时刻推出的 Apache Doris 2.0 Alpha 版别中,现已完成了单节点数万 QPS 的高并发点查询才能、高功用的倒排索引、高效安稳的内存办理、根据代价模型的全新查询优化器以及 Pipeline 履行引擎等,欢迎我们下载体会。与此一起, Apache Doris 2.0 Beta 版别也将于近两周上线。除了已知功用外,还会进一步支撑 Unique 模型上的部排列更新,并将 Pipeline 履行引擎、查询优化器、主键模型 Merge-on-Write 等最新特性作为安稳功用默许开启,并包含了社区近期对功用方面的诸多优化,详细功用测验结果敬请期待后续社区动态。

为了让用户能够体会社区开发的最新特性,一起确保最新功用能够收获到更广规模的运用反应,咱们建立了 2.0 版别的专项支撑群,请我们填写申请,欢迎广阔社区用户在运用最新版别过程中多多反应运用意见,协助 Apache Doris 继续改进。

作者介绍:

杨勇强,SelectDB联合创始人、技能副总裁

岳靖、程宇轩,SelectDB 存储层研制工程师