Hbase 三维有序存储

本文详细介绍了HBase的三维存储特性:行主键(rowkey)、列键(columnkey)及时间戳(timestamp)。阐述了这些维度如何影响数据的存储与查询效率,并提供了具体的rowkey设计案例。
hbase所谓的三维存储的三维是指:rowkey(行主键),column key(columnFamily+qualifier),timestamp(时间戳)

先说rowkey,我们知道rowkey是行的主键,而且hbase只能用个rowkey,或者一个rowkey范围即scan来查找数据。所以rowkey的设计是至关重要的,关系到你应用层的查询效率。我们知道,rowkey是以字典顺序排序的。而存储的字节码,字典排序,我们知道,如果是字母,那就是字母的顺序,如,有两个rowkey,rowkey1:aaa222,rowkey2:bbb111,那么rowkey1是排在rowkey2前面的,因为按字典,a排在b前面,如果rowkey2的第一位也是a,那么就根据第二位来比较,如果还相同,则比较第三为,后面同样。这个理解了,我们在根据rowkey范围查询的时候,我们一般是知道startRowkey,如果我们通过scan只传startRowKey : d开头的,那么查询的是所有比d大的都查了,而我们只需要d开头的数据,那就要通过endRowKey来限制。我们可以通过设定endRowKey为:d开头,后面的根据你的rowkey组合来设定,一般是加比startKey大一位。比如说rowkey设计为:用户ID-日期,那么查某个用户某天的数据,startKEY为3231-20121212,endKey为:3231+201213,那么你查到的就是用户为3231在20121212这一天的数据。

column key

column key是第二维,数据按rowkey字典排序后,如果rowkey相同,则是根据column key来排序的,也是按字典排序。
我们在设计table的时候要学会利用这一点。比如我们的收件箱。我们有时候需要按主题排序,那我们就可以把主题这设置为我们的column key,即设计为columnFamily+主题.,这样的设计。

timestamp

timestamp 时间戳,是第三维,这是个按降序排序的,即最新的数据排在最前面。这个就没有什么说的了。网上其他的博客也提到比较多。


原文地址:http://ronxin999.blog.163.com/blog/static/4221792020121114105727722/


<think>我们正在讨论HBase表的存储逻辑和机制。根据引用[1],HBase是一个稀疏的、分布式的、持久的多维排序映射(map)。这个映射由行键(row key)、列键(column key)和时间戳(timestamp)索引,每个值都是未解释的字节数组。 引用[2]提到HBase运行在HDFS上,数据以多副本形式存放,保证了分布式存储和恢复。同时,HMaster和RegionServer也是多副本的,确保了高可用性。 现在,我们将详细解释HBase表的存储逻辑和数据存储机制。 一、HBase数据模型 1. 表(Table):HBase中的数据存储在表中,表由行和列组成。 2. 行(Row):每一行由一个行键(Row Key)唯一标识。行键是字节数组,按字典顺序排序。这个排序特性使得行键的设计对查询性能有重要影响。 3. 列族(Column Family):列被分组为列族。列族在表创建时定义,每个列族内的列由列限定符(Column Qualifier)标识。列族是物理存储单元,同一列族的数据存储在一起。 4. 列限定符(Column Qualifier):列族内的具体列由列限定符标识,列限定符不需要预先定义,可以动态添加。 5. 时间戳(Timestamp):每个单元格(cell)可以存储多个版本的数据,每个版本通过时间戳标识。默认情况下,时间戳由系统自动分配,也可以由用户指定。 6. 单元格(Cell):由行键、列族、列限定符和时间戳唯一确定,存储的数据是字节数组。 二、物理存储结构 HBase的物理存储依赖于HDFS。表被分割成多个区域(Region),每个Region由一段连续的行键范围组成。Region是HBase分布式存储和负载均衡的基本单位,由RegionServer负责管理。 1. Region的划分: - 表初始时只有一个Region,随着数据增长,当Region大小达到阈值(默认10GB)时,会分裂成两个新的Region。 - 每个Region负责一定范围的行键,如Region1负责[0, 1000),Region2负责[1000, 2000)等。 2. RegionServer: - RegionServer运行在HDFS的DataNode上,负责处理Region的读写请求。 - 一个RegionServer可以管理多个Region,但一个Region只能由一个RegionServer管理。 3. 存储文件(StoreFile): - 每个列族在Region中对应一个存储单元(Store),每个Store包含一个内存存储(MemStore)和多个存储文件(StoreFile)。 - 写入数据时,首先写入MemStore,当MemStore达到一定大小后,会异步刷写到磁盘,生成StoreFile(实际是HFile格式)。 - StoreFile是HBase存储数据的文件格式,基于HDFS,因此具有多副本特性(默认3副本)。 4. HFile格式: - HFile是HBase的底层存储文件格式,它存储有序的键值对(key-value)。 - 每个键值对的结构如下: - 行键(Row Key) - 列族(Column Family) - 列限定符(Column Qualifier) - 时间戳(Timestamp) - 类型(Type,如Put、Delete) - 值(Value) 5. 写操作流程: - 客户端写入数据时,先写入预写日志(WAL,Write Ahead Log)用于故障恢复,然后写入MemStore。 - 当MemStore满时,数据被刷写到HDFS,形成新的HFile。 - 随着HFile增多,后台线程会合并(Compaction)多个HFile为更大的文件,以减少文件数量,提高读取效率。 6. 读操作流程: - 读取数据时,RegionServer会同时检查MemStore和StoreFile,合并结果后返回给客户端。 - 由于数据可能分布在多个HFile中,HBase使用布隆过滤器(Bloom Filter)和块缓存(Block Cache)来加速读取。 7. 数据局部性: - HBase通过将RegionServer和HDFS的DataNode部署在同一节点上,实现数据局部性,减少网络传输。 三、多维映射的实现 如前所述,HBase的数据模型是一个多维映射。在物理存储中,这个映射通过以下方式实现: - 行键、列族、列限定符和时间戳共同组成一个复合键(Composite Key),用于定位一个单元格(Cell)。 - 在HFile中,所有键值对按照复合键排序(行键→列族→列限定符→时间戳,时间戳倒序排列,以便读取最新版本)。 四、稀疏性的实现 - 由于HBase是按列族存储的,每个列族对应一个存储单元,因此对于没有数据的列,不会占用存储空间(即不会存储空值)。 - 同一行的不同列族可以存储在不同的物理机器上(因为Region按行键范围划分,而列族在同一个Region中存储在一起,但不同列族可能存储在不同的StoreFile中)。 五、数据恢复机制 - 通过WAL(预写日志)保证数据持久性。每次写入操作都会先写入WAL,然后才写入MemStore。如果RegionServer崩溃,重启后可以通过重放WAL恢复数据。 - 另外,HDFS的多副本机制保证了数据不会因为节点故障而丢失。 六、总结 HBase存储逻辑可以概括为: - 表按行键范围划分为多个Region,分布在不同的RegionServer上。 - 每个Region内,按列族存储,每个列族对应一个Store,包含一个MemStore和多个StoreFile(HFile)。 - 数据写入先写WAL,再写MemStore,最后刷写到HFile。 - 读取时合并MemStore和StoreFile中的数据,通过布隆过滤器和块缓存优化性能。 通过以上机制,HBase实现了稀疏、分布式、多维、排序的映射模型,并保证了高可用性和可扩展性[^1][^2]。 下面,我们将用图示和公式进一步说明。 1. 复合键的排序: 在HFile中,键值对按照复合键排序,排序规则如下: 首先按行键升序,然后按列族升序,再按列限定符升序,最后按时间戳降序(这样在读取时,最新版本的数据会先被找到)。 用数学表达式表示两个键值对的顺序关系: 设键值对A的键为$(row_A, cf_A, cq_A, ts_A)$,键值对B的键为$(row_B, cf_B, cq_B, ts_B)$。 则A排在B之前当且仅当: $$ \begin{cases} row_A < row_B & \text{或} \\ row_A = row_B \text{ 且 } cf_A < cf_B & \text{或} \\ row_A = row_B \text{ 且 } cf_A = cf_B \text{ 且 } cq_A < cq_B & \text{或} \\ row_A = row_B \text{ 且 } cf_A = cf_B \text{ 且 } cq_A = cq_B \text{ 且 } ts_A > ts_B \end{cases} $$ 2. 数据存储示意图(简化): 假设有一个表,行键为row1,有两个列族cf1和cf2,每个列族下有两个列(cf1:col1, cf1:col2; cf2:col3, cf2:col4),每个列有两个版本(时间戳t1和t2)。 在物理存储中,每个列族对应一个Store,因此会生成两个HFile(一个对应cf1,一个对应cf2)。在cf1的HFile中,存储的键值对按行键、列限定符和时间戳排序,例如: row1, cf1, col1, t2, value row1, cf1, col1, t1, value row1, cf1, col2, t2, value row1, cf1, col2, t1, value 3. 合并(Compaction): 当StoreFile数量达到阈值时,会触发合并操作。合并分为两种: - Minor Compaction:将多个小的StoreFile合并成一个大的StoreFile,但不会删除已标记删除的数据。 - Major Compaction:将一个Store中的所有StoreFile合并成一个新的StoreFile,并清理已删除的数据(包括标记删除和过期的版本)。Major Compaction会消耗大量资源,通常安排在低峰期执行。 4. 拆分(Split): 当Region的大小达到阈值(如10GB)时,RegionServer会将其拆分成两个新的Region。拆分过程: - 首先在RegionServer上创建两个子Region,并将原Region标记为离线。 - 然后,将原Region的数据按照中间行键(Mid Key)分成两部分,分别写入两个子Region。 - 最后,将两个子Region上线,并更新元数据(hbase:meta表)。 通过以上机制,HBase能够高效地存储和访问海量数据。 相关问题: 1. HBase中行键设计对性能有哪些影响? 2. 如何优化HBase的读写性能? 3. HBase的合并(Compaction)过程是如何工作的?有哪些配置参数? 4. HBase如何实现数据的高可用和容错?</think>### HBase表的存储逻辑与数据存储机制详解 #### 一、**核心存储模型:多维排序映射** HBase 的数据存储基于 Google BigTable 论文提出的 **稀疏分布式多维排序映射模型**,其核心结构可表示为: $$ \text{Table} = \text{Map} \left( \text{RowKey}, \ \text{Map} \left( \text{Column}, \ \text{Map} \left( \text{Timestamp}, \ \text{Value} \right) \right) \right) $$ - **行键 (RowKey)** 数据的唯一标识,按字典序排序(如 `0001`, `0002`, `0003`)。行键设计直接影响数据分布和查询性能[^1]。 - **列族 (Column Family)** 逻辑分组单元(如 `info`, `stats`),物理存储的最小单位。每个列族独立存储,支持动态添加列。 - **列限定符 (Column Qualifier)** 列族内的具体列(如 `info:name`, `stats:views`),无需预定义。 - **时间戳 (Timestamp)** 数据版本标识(默认64位整数),支持多版本存储。 - **值 (Value)** 未解释的字节数组(如 `Bytes.toBytes("Alice")`)。 > **示例数据单元**: > `{RowKey="user001", Column="info:name", Timestamp=1625097600000, Value="Alice"}` #### 二、**物理存储架构** ##### 1. 分布式存储层 - **Region 分区** 表按行键范围自动拆分为 **Region**(如 `[A-G]`, `[H-Z]`),每个 Region 默认 10GB $$ \text{Table} \xrightarrow{\text{Split}} \text{Region}_1 + \text{Region}_2 + \cdots + \text{Region}_n $$ - **RegionServer 托管** 每个 Region 由 **RegionServer** 管理(物理节点),支持水平扩展[^2]。 - **HDFS 持久化** 数据最终以 **HFile** 格式存储在 HDFS 上,默认 3 副本(保障容错性)[^2]。 ##### 2. 写入流程 ```mermaid sequenceDiagram Client->> RegionServer: 写入请求(Put) RegionServer->> WAL: 追加日志(Write-Ahead Log) RegionServer->> MemStore: 写入内存 Note over MemStore: 数据排序(按RowKey+Column+Timestamp) loop 定期刷写 MemStore->> HDFS: 生成HFile end ``` 1. 先写 **WAL**(预写日志)保障持久性 2. 写入 **MemStore**(有序内存缓冲区) 3. MemStore 满时刷写到 HDFS 生成 **HFile** ##### 3. 存储文件结构 HFile 内部采用 **LSM-Tree** 分层存储: | 层级 | 组件 | 作用 | |------|------|------| | L0 | MemStore | 内存中的有序数据 | | L1 | HFile (新) | 最新刷写的文件 | | Ln | HFile (旧) | 历史合并文件 | - **HFile 物理格式**: ```plaintext | Data Blocks | Meta Blocks | FileInfo | Trailer | ────────────────┬───────────────┬──────────┬───────── 键值存储区 布隆过滤器 元数据 索引指针 ``` #### 三、**关键存储机制** ##### 1. 稀疏存储优化 - **空值不占空间**:未定义的列不会存储(区别于 RDBMS 的 NULL) - **列族独立存储**:不同列族数据物理分离(如 `info` 和 `stats` 存储在不同目录) ##### 2. 数据版本管理 - 每个单元格可保留多个版本(通过时间戳区分) - 自动清理策略: $$ \text{保留版本数} = \text{MIN}(V_{\text{max}}, T_{\text{TTL}}) $$ - `V_max`:最大版本数(如 3) - `TTL`:过期时间(如 7 天) ##### 3. 压缩与合并 | 类型 | 触发条件 | 作用 | |------|----------|------| | Minor Compaction | HFile 数量阈值 | 合并相邻小文件 | | Major Compaction | 定期触发 | 跨文件合并+删除标记清理 | ```bash # 手动触发Major Compaction hbase shell> major_compact 'table_name' ``` #### 四、**数据访问原理** ##### 1. 读取路径 ```mermaid graph LR A[Client] --> B[ZooKeeper] B --> C[定位hbase:meta] C --> D[获取Region位置] D --> E[RegionServer] E --> F[合并MemStore+HFile] F --> G[返回数据] ``` - 使用 **布隆过滤器** 快速跳过不含目标数据的 HFile - **块缓存 (BlockCache)** 缓存热数据(LRU 策略) ##### 2. 局部性优化 - **RegionServer 与 DataNode 同置**:减少网络传输 - **行键连续存储**:相邻 RowKey 数据物理邻近(利于范围查询) #### 五、**设计哲学与优势** 1. **稀疏性** 动态列支持灵活 schema(适用于半结构化数据) 2. **多维性** 四维坐标定位:`(RowKey, Column, Timestamp) → Value` 3. **排序性** 行键全局有序 → 高效范围扫描 4. **分布式持久化** 基于 HDFS 的多副本存储保障数据安全[^2] > **典型应用场景**: > - 时序数据(IoT 传感器数据) > - 用户画像(动态属性存储)[^3] > - 实时日志分析 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值