Loading......

文章背景图

📘 Doris 存储体系与关键技术

2025-12-01
5
-
- 分钟

本笔记详细介绍 Doris 底层存储结构 Segment V2、文件格式组成、索引区域设计、Bitmap 正交去重原理、主键模型并发控制机制 等知识点。


🧱 1. Doris 的底层文件存储结构(Segment V2)

Doris 底层文件存储设计大量参考 ORC File,使用 Segment V2 文件格式 作为最小的数据存储与索引组织单元。

📁 1.1 Doris 数据存储分层结构

Doris 表数据的落盘结构大体如下:

其中:

  • Partition 解决大数据集管理、冷热分层等问题

  • Bucket(Tablet) 是分布式存储的基本分散单元

  • Rowset 表示一个数据写入批次或版本

  • Segment最小的存储文件单元,包含数据与索引


📦 2. Segment 文件格式详解

Segment 文件内容结构如下:

🔍 2.1 Data Region(数据区)

  • 列式存储

  • 每列按多个 Page(64KB) 切分

  • Page 是最小的读取单元

  • Data Page 内包含:

    • 压缩数据

    • 字段编码信息

    • Null Bitmap 等

📑 2.2 Index Region(索引区)

Doris 索引非常丰富,用于加速过滤 & 快速定位数据:

索引类型

作用

Short Key Index

Tablet 内快速定位 Rowset/Segment 范围

Zone Map

快速跳过无关数据块

Bloom Filter

高效判断值是否不存在

Bitmap Index

等值过滤加速

Ordinal Index

映射 Page ID 与行号

在查询时,Doris 会根据过滤条件动态加载对应索引,从而降低 IO。

🦶 2.3 Footer(文件尾部)

Footer 主要包含:

  • SegmentFooterPB:记录整体结构信息

  • Checksum:校验完整性

  • PB Length:Footer 结构大小

  • MAGIC CODE:文件尾标识

Footer 是整个文件的“说明书”,Doris 启动查询时优先读取这里的内容。


🧮 3. Doris 正交 Bitmap(Orthogonal Bitmap)原理与使用

正交 Bitmap 是 Doris 提供的一种 高效去重计算优化 技术,用于提升 UV / 去重计数场景的性能。


🎯 3.1 背景:为什么需要正交 Bitmap?

传统方案(Doris / Spark 都一样):

  • 全量用户 id bitmap 放在同一 FE 或同一任务中

  • Bitmap 可能超过 500MB–1GB

  • 计算速度明显下降,引发性能瓶颈

尤其在:

  • UV 计算

  • 用户数去重

  • 高频维度统计

都会出现瓶颈。


🔧 3.2 解决思路:分桶 + 分而治之

核心思路:

将用户 ID 通过 Hash 分桶
每个桶单独生成 bitmap
最终只需要对各桶 bitmap 的 “cardinality” 求和即可

这是一种 正交(Orthogonal)拆分,不同桶之间互不影响。

⭐ 优点:

  • 不同桶之间互斥 → 不会重复计数

  • Bitmap 尺寸大幅下降

  • 查询速度显著提升

  • 支持高度并行化


🚀 3.3 Spark 离线处理示例(原理介绍)

假设表结构如下:

user_id BIGINT COMMENT '用户id'
bucket_no INT COMMENT '分桶号'

分桶方式:

bucket_no = hash(user_id) % N

之后聚合:

SELECT dim1, dim2, bucket_no,
       bitmap_union(user_id) AS bucket_uv
FROM test.table
GROUP BY dim1, dim2, bucket_no;

最终:

SUM(bucket_uv) = 全局 UV

🔥 3.4 Doris 内置正交 Bitmap

Doris 2.0 已提供内置支持:

官方文档(说明用,无需访问)
orthogonal-bitmap-manual

应用场景包括:

  • 大规模 UV 统计

  • 复杂多维去重

  • 高并发查询场景


🔐 4. Doris 主键模型的并发控制(Unique Key + Sequence Column)

在实时与离线写入场景中,并发更新主键 会出现覆盖冲突问题。

Doris 引入类似 HBase 的 版本号控制机制(Sequence Column) 来保证最终一致性。


🎯 4.1 背景问题

多写入源同时更新同一个主键:

  • 写入顺序非严格有序

  • 不同批次会互相覆盖

  • 数据可能回退

  • 最终结果不正确(如首单、最早时间等)


🔧 4.2 Doris 的解决方案:Sequence Column

Doris 提供:

  • Sequence Column(版本列)

  • 高版本覆盖低版本(与 HBase 类似)

  • 结合 Unique Key,可保证数据最新性

写入时一般:

sequence_col = event_time 或 batch_time

越大代表越新。


🧰 4.3 应用场景

⭐ 场景1:极值获取(首单、最早时间)

例如:

order_time 最小 → 首单时间

order_time 作为 sequence column,Doris 会自动取:

最早 order_time 的记录

⭐ 场景2:防回退 + 并发更新控制

在多源写入用户表、资产表、订单表时,可以防止:

  • 旧数据覆盖新数据

  • 程序异常导致回滚写入


📝 5. Example:典型首单查询逻辑

首单场景典型数据写入方式:

  • sequence column = order_time

  • 较小值优先(因为表示更早)

例如占位时间设定为:

9999-12-31 00:00:00

写入后 Doris 根据 sequence column 自动保持:

  • 主键唯一

  • 时间最早的记录


🎉 结语

通过以上内容,我们全面整理了 Doris 的核心底层机制:

  • Segment V2 存储结构

  • 数据与索引区域细节

  • 正交 Bitmap 的性能优化原理

  • 主键模型并发控制的序列号机制

评论交流