首页 > 其他分享 >HBase的数据结构原理与使用

HBase的数据结构原理与使用

时间:2023-06-11 21:34:58浏览次数:43  
标签:存储 列族 LSM 磁盘 原理 HBase 数据结构 数据

一、HBase简介

HBase是一个开源的、分布式的、版本化的NoSQL数据库(即非关系型数据库),依托Hadoop分布式文件系统HDFS提供分布式数据存储,利用MapReduce来处理海量数据,用Zookeeper作为其分布式协同服务,一般用于存储海量数据。HDFS和HBase的区别在于,HDFS是文件系统,而HBase是数据库。HBase只是一个NoSQL数据库,把数据存在HDFS上。可以把HBase当做是MySQL,把HDFS当做是硬盘。

 

二、HBase的数据结构

1、索引结构:LSM树

 传统关系型数据普通索引采用B+树。B+树最大的性能问题是会产生大量的随机IO,随着新数据的插入,叶子节点会慢慢分裂,逻辑上连续的叶子节点在磁盘存储上往往不连续,分离得很远,随机读写概率会变大,做范围查询时,会产生大量读随机IO。为了克服B+树的弱点,HBase引入了LSM树的概念,即Log-Structured Merge-Trees,直译为日志结构合并树。基于LSM树实现的HBase的写性能相比Mysql放弃部分磁盘读性能,换取写性能的大幅提升。

 LSM树严格来说不是一个具体的数据结构,更多是一种数据结构的设计思想。LSM树不是一棵树,而是由至少两个存储结构构成。假设这两颗树分别为C0和C1,C0比较小,全部驻于内存之中,具体可以是任何方便健值查找的数据结构。而C1则驻于机械硬盘。一条新的记录先是从C0中插入,如果这一次的插入造成了C0数据量超出了阀值,那么C0中的部分些数据片段则会直接合并到C1树中。如果有多级树,当C1体量越来越大就向C2合并,低级的树在达到大小阈值后也会在磁盘中进行合并,以此类推,一直往上合并Ck。

LSM树的设计思想:

划分不同等级的树。将对数据的修改增量保持在内存中,数据更新只在内存中操作,没有磁盘访问。达到指定的大小限制后将这些修改操作批量写入磁盘。由于内存的读写速率都比磁盘要快非常多,因此数据写入内存的效率很高。随着小树越来越大,达到指定的阀值限制后将这些修改操作批量写入磁盘,磁盘中的树定期做多路归并操作,合并成一棵大树,以优化读性能。随机读写比顺序读写慢很多,为了提升IO性能,需要将随机操作变为顺序操作。LSM树使用日志文件和一个内存存储结构把随机写转化成顺序写,读写独立,数据从内存刷入磁盘时是预排序的,写性能大幅提升。读取的时候稍微麻烦,需要先看是否命中内存,如果读取的是最近访问过的数据则可以命中,否则需要访问较多的磁盘文件。

 

使用LSM树的数据库除了HBase,还有nessDB、levelDB、TiDB、RocksDB等。

(图中MongoDB只有WiredTiger(WT)存储引擎既支持B-树,又支持LSM树存储索引。)

 

2、存储结构

HBase的LSM树中存储的是多个Key-Value结构组成的集合,每一个Key-Value一般都会用一个字节数组来表示。这个字节数组串设计如图所示:

(图源:胡争,范欣欣《HBase原理与实践》第二章《基础数据结构与算法》)

 

字节数组主要分为以下几个字段。其中Rowkey、Family、Qualifier、Timestamp、Type这5个字段组成KeyValue中的key部分。

• keyLen:用来存储KeyValue结构中Key所占用的字节长度。

• valueLen:用来存储KeyValue结构中Value所占用的字节长度。

• rowkeyLen:用来存储rowkey占用的字节长度。

• rowkeyBytes:用来存储rowkey的二进制内容。

• familyLen:用来存储Family占用的字节长度。

• familyBytes:用来存储Family的二进制内容。

• qualif ierBytes:用来存储Qualif ier的二进制内。注意,HBase并没有单独分配字节用来存储qualif ierLen,因为可以通过keyLen和其他字段的长度计算出qualif ierLen。

• timestamp:表示timestamp对应的long值。

• type:表示这个KeyValue操作的类型,HBase内有Put、Delete、Delete Column、DeleteFamily,等等。

 

HBase的LSM树在内存一般采用跳跃表存储,跳跃表的查找、删除、插入的复杂度都是O(logN)。

LSM树在磁盘中的数据结构也不是树结构,而是Key-Value结构组成的序列,称为SSTable(Sorted String Table)有序字符串表。当SSTable太大时,为了加快SSTable的读取,可以将其划分为多个块,通过记录每个块的起始位置,构建每个SSTable的稀疏索引。这样在读SSTable前,通过索引就知道要读取的数据块磁盘位置了。SSTable索引需要永远加载在内存里。写是写内存,因此随机写十分快。读也是读内存里的 SSTable的索引,并且这里每一个SSTable索引如果用二分法查找,算法复杂度大致在O(lg(n))与O(n)之间,因此随机读也不慢。

 

3、表结构

与传统的关系型数据库类似,HBase也以表的形式组织数据,表也由行和列组成,不同的是,HBase采用列式存储。

如上图所示的表,如果采用列式存储,会存成下图的结构:

可以发现,列式存储就是把每列抽出来,然后关联上ID,实际上是用Key-Value结构保存的。这样的优点在于,当表格中有空缺时,可以充分利用存储空间。

对HBase来说,一行数据由一个行键(RowKey)和一个或多个相关的列以及它的值所组成。列的组成都是灵活的,行与行之间的列不需要相同。行键(RowKey)就是SSTable的key。

在HBase里边,先有列族(也叫“列簇”,Column Family),后有列。列族将一列或者多列组织在一起,HBase的每一个列都必须属于某个列族。HBase的列都得归属到列族中,如图所示:

数据写到HBase的时候都会被记录一个时间戳,这个时间戳被我们当做一个版本。比如说,我们修改或者删除某一条的时候,本质上是往里边新增一条数据,记录的版本加一了而已。如图所示:

被更新和删除的数据不会直接从磁盘上删除,而是为数据添加一个删除标记,查找时会跳过被删除的键,DBA运维会定期删除被标记删除的数据。因此,如果存在频繁覆盖删除需要提前向运维报备以免影响数据库性能。

 

三、HBase的使用

1、HBase的读写

HBase提供了多种模式、多种语言的访问接口。目前常用的包括Native Java API,Thrift和MapReduce模式。

(1)Java API是HBase提供的原生接口,具备完善的客户端处理逻辑,直接与HBase Server进行通信,效率最高,但受限于语言限制;

(2)Thrift不受语言限制,但会占用额外的网络带宽和处理时间;

(3)HBase还支持了MapReduce,可以通过编写MapReduce任务进行批量数据操作。

使用GoLang和PHP语言搭建的项目显然得用Thrift接口。

 

常用的HBase的数据操作get、scan和put三种。

(1)get实现随机读取功能,根据指定RowKey获取惟一一条记录。

(2)scan提供批量查询功能,按照指定的条件获取一批记录。通过指定起始和中止的key,即可获取所有包含在内的key对应的数据。可以通过setStartRow与setEndRow来限定范围,也可以通过setFilter方法添加过滤器,这也是分页、多条件查询的基础,用setCaching和setBatch方法能提高速度。

(3)put实现写入,如果要批量导入大规模数据,还可以采用bulkimport的方式。

 

2、行键(RowKey)设计

Rowkey相当于HBase中数据的主键。HBase中的数据是按照RowKey的ASCII字典顺序进行全局排序。可以使相关行彼此靠近存储。如果Rowkey设计不当会引发热点问题,即客户端大量的读写请求都集中在一个或几个节点上。从而导致性能下降。为防止数据写入时出现热点,数据被写入时应写入集群中的多个区域,而不是一次写入一个区域(Hregion)。

 

设计原则:

1、唯一原则,要保证Rowkey的唯一性。若HBase中同一表插入相同Rowkey,则原先的数据会被覆盖掉。设计Rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。

2、长度原则。Rowkey长度越短越好,一般不要超过16字节。因为RowKey是一个二进制码流,可以是任意字符串,最大长度64KB,实际应用中一般为10-100字节,以byte[]形式保存。如果RowKey过长比如500个字节,1000万列数据仅RowKey就要占用5GB空间,非常影响HFile的存储效率。

3、散列原则。用时间戳作为Rowkey的前缀会导致大量数据堆积在一个区域进而导致热点问题。如果Rowkey是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将Rowkey的高位作为散列字段,低位放时间字段。

 

3、列族(Column Family)的设计

设计原则:

1、列族的名称尽可能短,甚至可以是一个字符。例如,“d”表示数据/默认值。

2、HBase当前不能很好地处理超过两个或三个列族的数据,因此请保持列族的数量较少。最好使用一个列族。仅在数据访问通常是列范围的情况下才引入第二和第三列族。即,一次只查询一个列族,通常不会查询两个列族。

3、将相同IO特性的列放入同一列族。

4、多个列族中的数据(行数)分布大致均匀。

5、对于临时性的列族可以设置失效时间。一旦达到到期时间,HBase将自动删除行。

 

4、HBase Shell的安装和使用

HBase自带的操作工具只有HBase Shell这一命令行终端。通过HBase Shell工具,可以交互式地进行数据管理,包括插入数据、删除数据等。虽然也有一些第三方图形界面客户端支持HBase,如DBeaver、BigInsights、HbaseGUI,但系统部的HBase只支持HBase Shell。

安装HBase Shell需要先挑选一台用于安装的虚拟机,为该虚拟机安装Java环境。之后在系统部奇麟大数据的客户端管理页面选择“添加客户端账号”,申请为该虚拟机添加项目账号。申请通过后勾选机器,单击“部署Hadoop环境”在该机器上安装HBase Shell。

安装成功后,到虚拟机上使用sudo -iu命令先切换到项目账号。然后切换到目录cd $HBASE_HOME/bin,运行hbase shell,即可进入HBase Shell程序。

这里列出几个常用的HBase Shell命令:

名称 命令表达式
查看存在哪些表 list
添加数据 put '表名称', '行键', '列族 : 列名', '值'
查看一行数据 get '表名称', '行键'
查看指定列族的一行数据 get '表名称', '行键', '列族'
查看指定列族及列名的数据 get '表名称', '行键', '列族 : 列名',
查看表中的数据总量 count '表名'
删除一个单元格的数据 delete '表名' ,'行键' , '列族 : 列名'
删除一行所有数据 delete '表名' ,'行键'
查看表的所有数据 scan '表名'。注意,一般不应直接使用scan扫描整个表的海量数据。
查看一列数据 scan '表名' , '列族 : 列名'
查看帮助信息 help

 

5、MongoDB数据迁移HBase

使用kettle等工具可以把MongoDB数据库迁移到HBase。也可以使用MapReduce处理,速度远快于Java API和Thrift。

 

参考文献:

胡争,范欣欣.HBase原理与实践M.北京:机械工业出版社,2019

O’Neil, P., Cheng, E., Gawlick, D., & O’Neil, E. (1996). The log-structured merge-tree (LSM-tree). Acta Informatica, 33(4), 351-385.

标签:存储,列族,LSM,磁盘,原理,HBase,数据结构,数据
From: https://www.cnblogs.com/coldjelly/p/17456347.html

相关文章

  • 《数据结构与算法》之树
    导言:我们在前面的学习中认识到了栈还有队列这些线性的数据存储结构,而现在我们要了解的数据结构却不是线性的了,我们试想线性的结构最大的缺点查询不方便,不管你是从前往后开始查找数据,还是从后往前开始查找数据都是一个一个的比对,效率很低,所以不推荐使用,那么我们的树结构来存储的......
  • Hbase
    简介HBase是一个面向列式存储的分布式数据库,其设计思想来源于Google的BigTable论文。HBase底层存储基于HDFS实现,集群的管理基于ZooKeeper实现。HBase良好的分布式架构设计为海量数据的快速存储、随机访问提供了可能,基于数据副本机制和分区机制可以轻松实现在线扩容......
  • 【信息安全】项目实践:基于LSB(最低有效位)原理的图像隐写
    知识分享什么是隐写?隐写术(Steganography)这一名词早在文艺复兴时期就已出现。很多同学小时候玩过的秘密写字(紫外线照射使字迹显现)也可以说是隐写的一种。而现在的数字隐写术在是信息安全杂项门类下的一个小分支,主要研究将信息隐藏在数字载体中(一般是公开媒介)。信息隐写不仅要......
  • Java NIO原理 (Selector、Channel、Buffer、零拷贝、IO多路复用)
    系列文章目录和关于我零丶背景最近有很多想学的,像netty的使用、原理源码,但是苦于自己对于操作系统和nio了解不多,有点无从下手,遂学习之。一丶网络io的过程上图粗略描述了网络io的过程,了解其中的拷贝过程有利于我们理解非阻塞io,以及IO多路复用的必要性。数据从网卡到内核缓......
  • 容器镜像静态扫描原理
    前言有这样一个工具,可以对镜像进行扫描,拿出其中包含的软件包、lib库(pip包等)、危险文件等,并能够识别出哪些包是存在漏洞的.比如trivy工具.那么他们是如何做到这件事情的呢?正好最近在研究这块,索性就简单谈一谈(其实原理很简单).获取包含内容对于镜像的存储,层之间......
  • 【数据结构】查找
    基本概念查找表 由同一类型的数据元素(记录)构成的集合。所谓集合指记录间不存在前驱后继关系,因此查找表是一种应用灵便的结构。静态查找表 只对查找表做查找操作,即只查询某个记录是否在表中,或只检索某个记录的各种属性。或者说:查找表加上不会使该表的内容发生变化的查找操作,称作......
  • 使用ganglia监控hadoop及hbase集群
    一、Ganglia简介Ganglia是UCBerkeley发起的一个开源监视项目,设计用于测量数以千计的节点。每台计算机都运行一个收集和发送度量数据(如处理器速度、内存使用量等)的名为gmond的守护进程。它将从操作系统和指定主机中收集。接收所有度量数据的主机可以显示这些数据并且可以将这......
  • 2.5再探宝可梦、数码宝贝分类器 — 浅谈机器学习原理
    1.引入问题  在之前的课程中,我们对"参数过多就会导致过拟合"这个概念处于提出但没有证明的状态,现在来以宝可梦和数码宝贝的分类例子来说明这个问题.2.分类器定义  我们观察宝可梦和数码宝贝的图片可以发现,宝可梦的图片线条比较少,而数码宝贝的线条比较多.或许可以以边......
  • 计算机网络原理复习
    教材:计算机网络——自顶向下方法(第七版)作者:JamesF.Kurose,KeithW.Ross内容0-2在复述书6.7节0.数据的获得以访问网站为例。现在Bob(人在美国)要访问www.google.com这个网站!他所需要的是:他自己的IP地址、google的IP地址在获取的过程中,他还要用到:DNS服务器地址、本......
  • delphi 调用youtube-dl命令,下载youtube视频,原理及源代码
    一、概要1、Youtube-dl工具 强大的视频下载命令行工具Youtube-dl项目由RicardoGarcia创建于2008年,源代码由Python编写,托管在GitHub上,最初仅支持YouTube,但随着项目的发展,也开始支持其他视频网站,优势在于使用简单、功能齐全、体积小巧,但唯一遗憾的是国内使用需要开启代理。可......