前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >17道题你能秒我?我Hbase八股文反手就甩你一脸

17道题你能秒我?我Hbase八股文反手就甩你一脸

作者头像
王知无-import_bigdata
发布2021-07-12 16:03:24
9630
发布2021-07-12 16:03:24
举报
技术背景

起源于谷歌旧三篇论文中bigtable。

设计目的

为了解决大数据环境中海量结构化数据的实时读写问题。为了弥补hadoop生态中没有实时存储的缺陷。

设计思想

分布式

技术本质
  • 概念:分布式列存储nosql数据库
  • 解释:

列存储:底层数据文件存储格式是列式存储

nosql:非关系型,可以存储结构化和半结构化数据

数据库:符合数据库的特征

核心特性

大表: 为存储海量数据而生,亿级别的行和百万级别的列

分布式:

1.分布式内存:为实现实时读写,将数据放在内存中

2.分布式外存:内存中放置不了的数据,刷写到hdfs上

多版本:一个列簇允许设置版本数,即允许一个数值存储多个版本,通过"ns:tb cf:c ts"唯一缺点一条数据

nosql:

1.RDBMS:关系型数据库,例如"mysql,oracle,postgresql,sqlserver"

2.nosql:非关系型数据库,例如"hbase,redis,mongodb"

随机实时读写

1.数据优先存储在内存中,命中率高数据

2.命中率中等的数据,存在缓存中

3.命中率低的数据,存在hdfs上

代码语言:javascript
复制
依赖于hdfs:将海量的数据存到hdfs上,即保证了数据了安全性,又保证了数据的持久化
不支持join操作,只支持行级事务,复杂join操作需要集成hive
只支持字节数组类型
稀疏:对于空null的列,并不占用存储空间,因此表的设计可以非常稀疏
集群角色

物理架构

client

种类:

  • bin/hbase shell:不支持sql语句,可以使用help 'command',exit,
  • java api:

hue:hbase实现了ThriftServer服务端,用于提供hue客户端连接,thriftserver来实现整个过程的访问以及执行

sql on hbase:底层使用的mapreduce操作hbase

zookeeper

概念:hbase中的zk被称为真·主节点

职责:

  • 辅助集群的主节点选取,实现HA机制
  • 为集群的访问提供入口,存贮所有Region 的寻址入口
  • 负责存储hbase中几乎所有的元数据,如节点信息,master的主备节点,regionserver的节点,表的状态
  • 负责实现系统容错,若发现regionserver注册节点消失,即认为此regionserver故障,需要通知hmaster启动恢复程序
  • 负责存储meta表的region[rootregion]所在的regionserver地址
  • 负责flush,splitWAL的状态等
  • 存储Hbase 的schema,包括有哪些table,每个table 有哪些column family

内容:

每一个节点都会在zookeeper上去注册

zookeeper存储了meta表的region信息,客户端通过访问zookeeper才能请求集群

hdfs:

职责:存储hfile,wal

Hmaster:

概念:辅助主节点

职责:

  • 负责管理所有从节点信息,
  • 负责region在regionserver上的分配,实现regionserver的负载均衡,
  • 负责region的数据迁移,例如分裂场景
  • 负责meta表以及元数据的修改,meta表不等于元数据,可将meta表看做元数据的一部分,meta表只是存储region的信息,而元数据包括regionserver,region,表,namespace等信息
  • 负责接收客户端的DDL请求,用于更改元数据,修改zookeeper中的存储
  • 通过zookeeper监听每个regionserver的状态,如果regionserver故障,就会启动恢复regionserver的进程
  • 发现失效的region server 并重新分配其上的region
  • HDFS 上的垃圾文件回收
  • 处理schema 更新请求

RegionServer:

职责:

  • 负责接收并处理所有客户端的数据的读写请求
  • 负责管理该节点上所有的region,处理对这些region 的IO 请求
  • 负责记录WAL
  • 负责读缓存:memcache,占堆内存40%,并刷新缓存到HDFS
  • 执行压缩
  • 负责处理Region 分片

补充:

  • regionserver就是从节点,有多台
  • 一台regionserver中管理很多个不同的表分区【region】
  • meta表中的数据也存在regionserver中

Hlog:

概念:预写日志,类似于hdfs上的edits文件,也类似于mysql中的binlog文件。

补充:

每个Region Server 维护一个Hlog,而不是每个Region 一个。这样不同region(来自不同table)的日志会混在一起,这样做的目的是不断追加单个文件相对于同时写多个文件而言,可以减少磁盘寻址次数,因此可以提高对table 的写性能。带来的麻烦是,如果一台region server 下线,为了恢复其上的region,需要将regionserver 上的log 进行拆分,然后分发到其它region server 上进行恢复,HLog文件就是一个普通的Hadoop Sequence File。

Region:

概念:

regionserver中的数据存储单元,不是region级别的

补充:

  • 一张表将数据按照rowkey的范围来划分到多个region中,以此来散列表的数据,
  • 默认情况下创建的表只有一个region
  • 同一张表的不同region的范围总和是从负无穷到正无穷
  • 一个region只会被一台regionserver管理
  • region是整个hbase中最小的负载均衡单元,是实现分布式的基本
  • region的分配不均衡会导致数据倾斜及热点问题
  • 用户读写时,会根据rowkey进行判断,从哪个分区读取,从哪个分区写入
  • 每一个分区是一个目录
  • store个数/2 = region个数

Store

意义:设计列簇时将具有相同IO属性的列放在同一个列簇里,因为底层存储是一个列簇存储独占一个store;放在一个storefile中,可以提供快速的读写操作

概念:

region是表的划分,store是列簇的划分,机器内存 * 40% /128M=store个数

MemStore

功能:

补充:

属于Store中的内存存储区域。每个store中都有一个memstore,用于存储刚写入的数据。写内存,占堆内存的40%,

StoreFile /HFile

功能:

解释:

1.memstore满足条件会进行flush,刷写出来的数据文件就是storefile,存储在hdfs上被称为hfile 2.一个store中会有多个storefile文件,但最终会优化合并成一个文件【二进制文件】 3.storefile是hfile的封装,也可认为是同一个文件,不同的称呼

补充:

HFile分为六个部分:

1.Data Block 段–保存表中的数据,这部分可以被压缩

2.Meta Block 段(可选的)–保存用户自定义的kv 对,可以被压缩。

3.File Info 段–Hfile 的元信息,不被压缩,用户也可以在这一部分添加自己的元信息。

4.Data Block Index 段–Data Block 的索引。每条索引的key 是被索引的block的第一条记录的key。

5.Meta Block Index段(可选的)–Meta Block 的索引。

6.Trailer–这一段是定长的。保存了每一段的偏移量

逻辑存储

NameSpace

名称空间,物理存在。默认创建时就已经存在两个名称空间default和hbase。属于表的一部分,用于区分表的存储,每个表必定有自己是名称空间,若不指定,默认属于default

Table

表,访问时通过namespace:table_name来访问这张表,不加默认访问是default下的表

Rowkey

行键,通过rowkey可以唯一指定一行的数据(注意不是一条),在创建表时就已经存在,不需要再次创建。

rowkey的设计,影响了底层region的节点数据分配,会造成热点问题,影响读写性能。

rowkey是整个hbase中的唯一索引,在hbase中不支持自定义索引,处理rowkey之外,没有别的索引,查找数据时,要么通过rowkey进行查找,要么全表扫描,区别于mysql中可以自定义索引。

ColumnFamily

列簇,列的分组,一个列簇下有多个列,每个列必然属于某个列簇,可通过列簇指定这一个列簇中所有列的版本号。一般将具有相同io属性的字段放入同一个列簇。创建表时必须指定至少一个列簇。一张表一般不建议超过两个列簇,一般在一到两个列簇,超过两个之后,hbase的读写性能会降低。

Column

列,列标签,一个列簇下有多个列,一个列必属于某个列簇,两个列簇中的列个数不必相等。两个行同一列簇下运行有不同的列,即半结构化。通过cf:c 唯一指定一列。

Value

值,每一列的值,hbase底层没有数据类型,都是字节存储,允许存储多版本的值

Version

版本数,属于列簇的一个属性,默认版本为1个,可以配置多版本来存储多版本的数据 默认查询时,只显示每一列的最新的那个版本数据 如果每条存储数据超过版本数,旧的版本会被覆盖 设计多版本是为了存储,默认显示最新版本是为了读取

TimeStamp

时间戳,用来区分版本, version版本数是一个设置,timestamp是一个标识 默认值是数据插入的格林尼治时间 查询是需要指定时间戳才能唯一确定一条数据 每一列都有一个时间戳,同行同列簇同版本下的不同列的时间戳相同

列存储

概念:

区别于rdbms的行式存储格式,nosql使用列式存储格式。

优点:

行式存储操作实时行级别的,列式存储操作是列级别的。所以粒度更细 行式存储一行中的列都是一样的(结构化),列式存储每一行中的列可以不一样(半结构化)。所以支持的数据格式更广泛,半结构化可以支持结构化数据,结构化数据不可以支持半结构化数据 性能更优化,读写速度更快

DDL
代码语言:javascript
复制
1. namespace
    list_namespace
    create_namespace
    drop_namespace
    describe_namespace
    list_namespace_tables

2. ddl
备注:只有管理员admin才能操作
    list
    create:创建表时只需要给定表名和列簇名称,两种方式:配置列簇属性和不配置列簇属性
    describe/desc
    drop:hbase中表是enable状态的话,不允许对表结构进行修改和删除,需要先disable禁用
    disable
    enable
DML
代码语言:javascript
复制
1.dml
    put:hbase中没有更新和删除操作,所有的更新都是插入
    scan:用于查询一行或多行,或全表扫描
    get:用于查询某一行,就是某一个rowkey的数据
    delete
热点问题与数据倾斜

概念

热点问题:客户端的请求大量集中在某一个节点,导致该节点上的负载非常高,而其他节点负载过低的-

现象

数据倾斜:由于计算任务大量集中在某一个节点,导致该节点上的负载非常高,而其他节点负载过低的现象

区别

  • 热点问题:请求层面,热点问题可能会造成数据倾斜
  • 数据倾斜:计算层面,数据倾斜不一定由热点问题造成

原因

热点问题在很多场景中都会发生,在hbase中表现造成热点问题的原因是:

1.客户端大量请求的rowkey连续集中在某一个region上 2.表中只有一个分区,所有的请求都集中在这个region上

解决

1.需要设计好表的分区region范围,避免分区范围不均衡,通过分区范围解决 2.需要创建预分区,多分区,通过分区个数解决

预分区

背景:在创建表的时候,默认只有一个分区,此时容易操作服务端热点问题

概念:在创建表的时候,根据rowkey的分布来设计一张表刚开始就有多个分区,分区需要根据rowkey的前缀或者完整的rowkey来设计,因为region的分配就是根据rowkey来划分分区的

意义:

1.增加数据读写效率

2.负载均衡,防止数据倾斜

3.方便集群容灾调度region

4.优化Map 数量

方式:

1.指定分区范围 create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']

2.适用于分区较多场景 指定规则文件 create 'ns1:t2', 'f1', SPLITS_FILE => '/export/datas/splits.txt'

3.通过java API 来划分分区admin.createTable(HtableDescriptor desc,byte splitKeys)

RowKey的设计规则

原因:为什么rowkey设计至关重要?

  • 所有数据在存储时都是根据rowkey来读写对应分区的,即分区是根据rowkey来划分的。
  • rowkey是hbase中的唯一索引。
  • rowkey在查询时是前缀匹配的。

后果:rowkey设计不好会产生什么后果?

  • 会造成热点问题
  • 会造成全表扫描

设计规则:

唯一原则:任何一个rowkey,必须唯一标记一行,类似于主键的唯一性

散列原则:

构建rowkey的随机散列,不允许rowkey是连续的,避免热点问题。

若rowkey前缀是一个固定的字段,且会产生连续,如何解决呢?

  1. 编码,通过md5/crc32等方式来将固定字段进行编码然后作为rowkey
  2. 反转,rowkey是按照ascii码的字典顺序,固定字段反转之后,就不连续
  3. 随机数,将固定字段加随机数,不推荐,因为不便于维护

业务原则:根据业务维度来设计rowkey,例如将经常作为查询条件的维度

组合原则:将各个业务维度组合来设计rowkey

长度原则:一般rowkey的长度不要超过100个字节,可以使用十六进制或三十二进制压缩长度

JavaAPI

代码语言:javascript
复制
介绍:
    1.hbase中 hbase shell 一般用来封装脚本,执行ddl操作,一般用来封装做ddl操作通过hbase shell  xxx.query指定,脚本操作结尾要加exit
    2.javaapi则是实际使用场景,一般用来执行dml操作,和分布式框架使用,做中间件技术,提供程序访问hbase的接口

API方法:
    1.HBaseConfiguration; 创建hbase的初始化对象
    2.HBaseAdmin;hbase的管理员对象,需要进行ddl操作时需要的对象
        1.tableExists
        2.disableTable
        3.deleteTable
        4.deleteNamespace
        5.listNamespaceDescriptors
    3.HTableDescriptor;hbase的表描述对象
        1.addFamily
        2.createTable
        3.getTableName
    4.TableName;表名称对象
        1.getNameAsString
    5.HColumnDescriptor;hbase的列簇描述对象
        1.setMaxVersions
        2.setBlockCacheEnabled
        3.
    6.NamespaceDescriptor;hbase的名称空间描述对象
        1.createNamespace
        2.create
    7.Get;get命令获取数据
    8.Result;一个result代表一个rowkey的所有数据
        1.rawCells
    9.Cell;一个cell就是一列的数据
    10.Table;表对象
        1.get
        2.put
        3.delete
        4.getScanner
    11.Put;
        1.addColumn
    12.Delete;
        1.addColumn
    13.ResultScanner;result对象的集合
读取
代码语言:javascript
复制
1.驱动类,封装了mr程序中的参数集合,调用方法TableMapReduceUtil.inittablemapper(输入和map的参数);
2.mapper类,需要继承TableMapper类,默认input输入的key和value为ImmutableBytesWritable和Result

实现:
    底层通过tableinpputformat实现;sqoop底层通过dbinputformat实现

<解释>
    因为mr读取hbase数据,只是做了数据的读取,并不做数据的聚合,所有不需要reduce
写入
代码语言:javascript
复制
1.驱动类,封装了mr程序中的参数集合,调用方法TableMapReduceUtil.inittablereduce(reduce和输出的参数);
2.reducer类,需要继承TableReducer类,默认output输出的value为put对象

实现:
    底层通过TableOutputFormat实现;sqoop底层通过dboutputformat实现

<解释>
    需要在reduce类中构建put对象,用于存储数据,所以需要reduce
Filter 过滤器

背景知识:

  • 在hbase中,所有数据在存储时按照rowkey的ASCII码表字典顺序进行排序的
  • 在hbase中,rowkey的查询都是前缀匹配
  • rowkey是hbase中的唯一索引,所有数据的读写要么通过rowkey查询,要么就是全表扫描
  • hbase底层没有数据类型,数据全部都是按照字节数组存储,
  • 按照keyvalue对格式存储每一列数据,key=ns+tb+cf+c+ts,value=value
  • 一般搭配scan来使用
代码语言:javascript
复制
 shell过滤器种类:
    1. TimestampsFilter,时间戳过滤器
    2. QualifierFilter,列名过滤器,需要指定比较参数和比较值 QualifierFilter (>=, 'binary:xyz')
    3. ROWPREFIXFILTER,rowkey前缀过滤器

 javaapi过滤器种类:
       第一类:比较过滤器;通过比较的工具类,来实现过滤,返回符合的rowkey所有的数据
            1.RowFilter
            2.FamilyFilter
            3.QualifierFilter
            4.ValueFilter
       第二类:专有过滤器;用的比较多,封装好的方法来实现
             1.prexfixFilter:rowkey前缀过滤器
             2.singleColumnValueFilter/singleColumnValueExcludeFilter:单列值过滤器
             3.MultipleColumnPrefixFilter:多列过滤器
             4.pageFilter:分页过滤器,一般在工作中,必须指定对应的起始位置,一般搭配startrow来使用
      第三类:组合过滤器,就是各种过滤器组合在一起,FilterList


如何使用过滤器:
    1.shell中使用"{列属性}"指定,例如:
        {COLUMNS => ''};{STARTROW => '闭区间',STOPROW => '开区间'}
        {ROWPREFIXFILTER => '',FILTER => ''}
Hbase:ns/Hbase:meta

"hbase:namespace"表,这张表会记录hbase中所有namespace的信息,当用户进行请求时,会读取这张表的信息来判断用户访问的namespace是否存在

"hbase:meta"表,hbase表中的元数据表,meta表中记录了:

meta表中的rowkey包含了regioninfo和server两个部分,其中包含regioninfo的rowkey,记录了region的名称,startkey和stopkey。包含server的rowkey记录了这个region所在的regionserver的地址和端口。

meta表记录了除了自己之外所有的在hbase中的表的region的名称;其中“region名称”的构成:表名称+region的起始范围+region的时间+region的唯一id。

补充:

1.数据读写请求,客户端如何找到对应的region的region的?

A:zk记录了meta表的"region信息","region信息"包括region的名称,startkey和stopkey,还包含了这个region所在的节点地址和端口,通过这些去对应regionserver上找到的meta表的数据,然后meta表中记录了除了自己之外的hbase中所有表的"region信息",这些"region信息"也包括region的名称,startkey和stopkey,还包含了这个region所在的节点地址和端口。然后通过这些信息再去找到对应regionserver上的region

Hbase的存储原理

读写请求概述:

  • 客户端第一次请求时,本地没有记录region信息,先去请求zk,获取meta表的region信息。
  • 然后再跟据region信息请求对应的regionserver,获取meta表的数据,得到要查询表中rowkey对应的region信息。
  • 客户端再次跟据返回的表中rowkey对应的region信息去请求regionserver提交读写请求,并缓存本地请求的地址及region信息,供下次使用,直接请求regionserver获取表数据。
  • regionserver跟据请求来操作region,跟据列簇来判断读写哪个store。

读请求:

请求会优先读取内存中数据,即memstore,若数据没有在内存中,就读缓存,然后读hdfs

写请求:

  • 请求会先写入内存memstore中,当memstore满足条件时,触发flush刷写,将memstore中的数据变成storefile文件
  • 通过hbase底层封装的hdfs客户端,将文件生成在以hfile的文件类型存储在hdfs上
Hbase读写请求流程

写请求流程

  • 客户端提交一条写的命令,根据这个请求的rowkey来获取对应的region信息,来请求对应的regionserver,以此来对rowkey进行操作
  • 将请求提交给对应的regionserver,regionserver根据请求写入的region的名称来操作
  • 根据请求中的列簇来判断要写入该region中的哪个store
  • 将数据以keyvalue形式写入memstore
  • memstore达到一定条件以后,会触发flush,内存中数据会写入hdfs,
  • hdfs中的storefile达到一定条件以后,会触发compaction,将storefile文件归并排序进行合并
  • 当整个region的数据大小达到一定条件以后,会触发split,一个region会分裂成两个region,原来的region被销毁

读请求流程

客户端请求zk,从zk获取meta表的地址

客户端读取meta表的数据,根据读命令中的表名来获取表所有的reigon信息,

找到要读取的region以及对应的regionserver地址

如果是get请求,指定了rowkey,则返回这个rowkey对应的region信息

如果是scan请求,则返回这张表对应的所有的region信息

根据返回的reigon地址,请求对应的regionserver,

regionserver根据region名称来找到对应的region,并进行读操作

若请求中指定了列,则读取列簇对应的store,若请求中没有指定列,则读取所有store的数据

请求在读取store时,优先读取内存中的store,即memstore,若memstore中没有找到,若开启了缓存,则取memcache缓存中找,若没有开启缓存,则直接去hdfs上找storefile,若hdfs上也没有,就是数据不存在,直接返回,若是hdfs上有,就将这条数据返回,若开启了缓存,还需要将数据添加到memcache中,方便下次使用

代码语言:javascript
复制
查询内存:
      有:返回
      没有:缓存:
              有:返回
              没有:hdfs
                   有:返回并添加缓存
                   没有:返回

解释:

  1. 经实践分析,新写入的数据在请求访问是命中率最高,所以保存在内存中
  2. 根据LRU最近最少使用算法,将访问频率高的数据添加到缓存中,提高缓存访问的命中率
LSM-tree模型

概念:Log-Struct-Merge 模型树,即wal,flush,compaction,split等过程;

功能:将随机无序的数据变成有序的数据,通过有序的算法来加快数据的读取,因为写入时需要进行排序,所有牺牲了一定的写入数据的效率,都用内存来实现数据的读写的存储

主要步骤:

  • 请求时现将数据保存到预写日志,然后写入内存
  • 在内存中对数据进行排序
  • 将内存中的数据写入文件,构成一个有序数据文件
  • 合并:将有序的多个数据文件进行合并生成一个新的有序的文件
  • 删除和更新:在模型设计中,本身并没有删除和更新,通过插入来模拟的,一般都是在文件合并时来进行实际的物理删除操作
WAL
  • 概念:预写日志, write-ahead-log
  • 职责:当产生写的请求后,写请求提交给regionserver,regionserver会将这个写的操作记录在WAL中,即Hlog,然后再写入memstore
  • 存储:将WAL存储在hdfs上,每台regionserver维护一份WAL,
  • 场景:用于数据恢复,hfile由hdfs恢复,memstore由WAL恢复

补充:

  • oldwals:不再被需要的Hlog日志文件
Flush
  • 概念:刷写
  • 功能:数据在memstore中先做一次按rowkey的字典顺序排序,然后将memstore中的数据写入持久化到hdfs上,会生成一个有序的storefile文件
  • 场景:由于memstore是使用的内存,内存容量有限,为了提高新数据的命中率,需要将老的数据吸入hdfs进行安全存储
Compaction

概念:合并

功能:将hdfs上的多个storefile文件进行合并,构建统一的有序文件

场景:为提供文件的快速读取,将多个storefile文件合并成一个整体有序的storefile文件,因为读取多个数据源没有读取一个数据源快

过程:

代码语言:javascript
复制
minor compaction:将hdfs上早些生成的一些文件进行合并
major compaction:将所有的文件进行合并,合并的过程中会将标记为删除或过期的数据真正的删除
Split
  • 概念:分裂.
  • 功能:若一个region分区的数据过多,会分裂成两个region.
  • 场景:一个分区的数据过多时,就会容易造成服务端引起的热点问题,无法实现分布式高性能,此时由regionserver将这一个分区均分为两个分区,由master重新将两个分区分配到 不同的regionserver中,分配成功后旧的region下线.
数据加载

概念:将数据导入到hbase中,有两种实现方式。

  • 使用put对象

例如:hbase shell,java api,mr程序封装。缺点:数据流经过WAL,然后经过内存,最后再到hdfs上,当导入海量数据是,容易导致region和hdfs的io过高,增加服务端负载,影响其他应用。

  • Bulkload
代码语言:javascript
复制
原理:hbase底层存储是hdfs上的hfile文件,然后通过meta表关联数据,所以可以先本地将数据转换为hfile文件,然后上传到hdfs上去,同时补充上meta表数据。

场景:适用于导入大量数据的批量hbase场景,要求稳定性能

缺点:

数据第一次读取时都是在hdfs上的,没有存在memstore中,所以第一次会变慢,但是如果数据量特别大的时候,两种方式最终的数据第一次读取都是在hdfs上的,所以没差别
数据直接从传到hdfs上的,没经过WAL,所以当出现数据丢失,没办法恢复数据,需要重新再转换一次

实现:

应用程序实现:

  1. 负责将普通文件转换成为hfile文件
  2. 负责将转换好的hfile文件加载到hbase表中

hbase自带实现:

1.ImportTSV,是hbase-server.jar包中自带的一个命令,可以实现使用put方式将数据导入hbase表中,也实现了将普通文件转换成一个hfile文件的两种方式

2.completebulkload,上面的importtsv命令将普通文件转换成一个hfile文件,但是并没有加载到hbase表中,completebulkload负责将hfile文件加载到hbase表中

代码语言:javascript
复制
<命令>:
     1. yarn jar /export/servers/hbase-1.2.0-cdh5.14.0/lib/hbase-server-1.2.0-cdh5.14.0.jar 
        importtsv  -Dimporttsv.columns=a,b,c <tablename> <inputdir> -Dimporttsv.separator=',' 
         -Dimporttsv.bulk.output=/bulkload/output2
     2. yarn jar export/servers/hbase-1.2.0-cdh5.14.0/lib/hbase-server-1.2.0-cdh5.14.0.jar 
          completebulkload /bulkload/output2  mrhbase

<解释>:
    -Dimporttsv.columns 指定文件中列映射的列簇及列         
        Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:age,info:sex mrhbase /bulkload/input
    -Dimporttsv.separator 指定读取文件中的列分隔符,默认以制表符分隔
    -Dimporttsv.bulk.output 指定生成的HFILE文件所在的hdfs的位置
SQL on Hbase

背景:

hbase是nosql数据库,有自己的api实现,不支持sql语言,不利于开发和数据分析人员,sql on hbase 解决了这一场景,在hbase上使用sql/jdbc操作

原理:

  • 基于java api/mapreduce 实现
  • 基于hbase shell 实现
  • 搭桥通过hdfs实现

实现:

hive集成hbase:

原理:通过hive中的hql语句,底层转换为mapreduce操作,在mapreduce操作的同时,也用mapreduce操作hbase表 实现:在hive中创建一张与hbase关联的表,操作hive中关联表,实际上是对hbase在操作

phoenix第三方工具:

原理:基于hbase构建了二级索引,直接调用hbase的api实现,因此在于hbase集成度和性能是最优选

sqoop第三方工具:

原理:底层也是使用mapreduce程序导入数据,从关系型数据库中导入到hdfs,然后使用importtsv命令和completebulkload命令来完成从hdfs上的导入,sqoop可以导入,但是不能导出,因为半结构化数据支持结构化数据存储,结构化数据不支持半结构化数据存储

补充:

  • 若hbase表已经存在,hive中只能创建外部表,使用key来表示rowkey
  • 若hbase表不存在,默认以hive表的第一列作为hbase的rowkey
  • hbase与hive关联,hive中的关联表加载数据时不能使用load加载,因为load命令底层没有使用mapreduce,因为load命令是使用hdfs的put命令,只能用insert命令
二级索引

概念:基于rowkey再构建一个索引,称为二级索引。

意义:rowkey是唯一索引,而且rowkey是前缀匹配,若我们不知道前缀,但知道rowkey部分字段,只能全部扫描吗?二级索引就是解决了rowkey唯一索引这个问题。

解决:构建二级索引。

方式:

代码语言:javascript
复制
创建索引表,将原表中的查询条件作为索引表的rowkey,将原表中的rowkey作为索引表中的value;
查询是若不指定原表的前缀,就先根据查询条件去查询索引表,找到原表的rowkey,再根据获得的rowkey去查原表
协处理器
  • 背景:构建二级索引,因为索引表和原表是两张不同的表,如何保证两张表的数据同步?
  • 同步方式:手动进行两次插入,在插入原表的同时,也插入索引表
  • 缺点:性能较差,操作繁琐,请求数加倍,对服务器负载过高
  • 构建协处理器,构建类似于mysql中的触发器
  • 依靠第三方工具,让他们来实现二级索引:例如:solr,ES 构建索引类型丰富,可以实现自动同步,Phoenix用sql构建索引
  • 概念:Coprocessor,协助开发者构建自定义的二级索引
  • 本质:自定义实现hbase提供对应接口的一段程序

分类:

  1. observer:观察者的协处理器,类似于监听功能,类似于触发器,一般用于二级索引同步 功能:监听原表,只看客户端往原表中插入一条数据,协处理器自动往索引表中插入一条数据
  2. endpoint:终端者协处理器,类似于存储过程,或java中达到一个方法,一般用来做分布式聚合统计 功能:监听一张表,这张表的每个region都会计算自己的rowkey个数,当客户端调用时,就会返回每个region的个数
  3. 补充:如何快速统计一张表的rowkey个数
  4. 通过编写mapreduce方法,最慢的最蠢的方式
  5. 使用hbase自带的count命令
  6. 开发endpoint协处理,最快最有效的方式
Hbase优化

概念:hbase优化可通过以下几个方面,flush,compaction,split和列簇属性来实现

Flush
  • 意义:用于将memstore中的数据写入HDFS,变成storefile文件,空出内存,用于存储新数据
  • 自动触发规则:
代码语言:javascript
复制
默认单个memstore的存储达到128M,就会触发。

默认整个region的memstore的数据达到128M * 4,就会触发。

默认整个regionserver中的memstore的使用率达到堆内存的40%,就会触发。

缺点:

自动触发,会导致磁盘IO的负载过高,会影响业务,一般会关闭自动触发,根据实际情况定期的在业务比较少的时候,手动触发

手动触发:

关闭自动触发:将所有自动触发的条件调高,定期的在没有达到自动触发的条件之前通过flush命令手动触发

总结:

将自动触发条件调高,以此来关闭自动触发flush,并在业务量较少时通过手动触发flush,以此来达到优化目的

Compaction
  • 意义:用于实现将多个storefile文件,合并成一个storefile文件,变成一个整体有序的文件,加快读的效率

自动触发规则:

代码语言:javascript
复制
minor compaction:轻量级的合并,合并部分storefile成一个文件,smart算法,将最早生成的三个文件合并,不定期执行,占用IO比较小
major compaction:重量级的合并,合并所有的storefile文件成一个文件
默认七天会触发一次compaction

缺点:

总结:

关闭自动触发major compaction,并在业务量较少时通过手动触发major_compact

Split

意义:将一个region分裂成两个region,分摊region的负载

自动触发规则:

缺点:

代码语言:javascript
复制
自动触发,会导致磁盘IO的负载过高,会影响业务,一般会关闭自动触发,根据实际情况定期的在业务比较少的时候,手动触发
手动触发:
关闭自动触发:hbase.client.keyvalue.maxsize=100GB,不可能达到这个值,根据集群region的数据量,来定期手动触发
  • 总结:

关闭自动触发,并在业务量较少时通过手动触发split

列簇属性
  • BLOOMFILTER:布隆过滤器
代码语言:javascript
复制
用于在检索storefile文件时,根据索引判断该storefile文件中是否有想要的数据,若没有直接跳过。

级别:none 不开启。

row 判断是否有需要的rowkey,没有就跳过。

rowcol 判断是否有需要的rowkey和cf:c,没有就跳过。
  • Versions:MaxVersions,最大版本数,该列族中的列最多允许存储多少个版本。
  • TTL:版本存活时间,从该版本的timestamp进行计算,一旦到达这个时间,就表示该数据过期,用户hbase自动清理数据。
  • MIN_VERSIONS:最小版本数,该列族中的数据当达到TTL时间以后,最小保留几个版本。
  • BLOCKCACHE:读缓存,是否将这个列簇的数据读到memcache缓存中,默认开启,建议将不经常读取的列簇关闭。
  • IN_MEMORY:代表BLOCKCACHE中的一种缓存的最高级别,默认是关闭的,IN_MEMORY是最高级别的缓存,缓存会定期的进行LRU清理,缓存级别越低,优先会被清理,不要随便开启IN_MEMORY,因为meta表就在IN_MEMORY级别的缓存中
  • BLOCKSIZE:storefile文件块的大小,默认64k,数据块越小,数据块越多,维护索引越多,内存占用越多,读快写慢,数据块越大,数据块越少,维护索引越少,内存占用越少,读慢写快
  • COMPRESSION:Hbase中的压缩其实就是hadoop的压缩,本身就是压缩storefile的存储
Hbase和RDBMS对比

Hbase

代码语言:javascript
复制
支持向外扩展
使用API 和MapReduce 来访问HBase 表数据
面向列,即每一列都是一个连续的单元
数据总量不依赖具体某台机器,而取决于机器数量
HBase 不支持ACID(Atomicity、Consistency、Isolation、Durability)
适合结构化数据和非结构化数据
一般都是分布式的
HBase 不支持事务
不支持Join

rdbms

代码语言:javascript
复制
支持向上扩展
使用SQL 查询
面向行,即每一行都是一个连续单元
数据总量依赖于服务器配置
具有ACID 支持
适合结构化数据
传统关系型数据库一般都是中心化的
支持事务
支持Join
Hbase的增删改查
  • 功能:hbase中实际没有更新和删除操作,hbase中只有增加和查询操作;更新是将新数据插入内存,,删除是将数据逻辑删除,等后续合并时再做覆盖旧版本数据和物理删除数据
  • 意义:为了快速返回处理读写请求,数据只要写入就里面返回结果
  • get与scan的区别:
代码语言:javascript
复制
get命令是hbase中最快的查询方式,因为指定了索引rowkey,但是只能查询一条数据。
scan命令可以返回多条数据,一般结合过滤器使用。
put和delete没有返回结果。
hbase/hive/hdfs/rdbms的区别

hbase

  • 概念:实时读写的数据库
  • 用途:存储数据
  • 场景:用于实现实现大量数据的实时读写文件,例如搜素引擎,一般用于高性能计算架构中,能存储半结构或结构化数据

hive

  • 概念:结构化数据仓库
  • 用途:存储数据
  • 场景:只能用于存储结构化数据,用来构建数据仓库的工具

hdfs

  • 概念:文件存储系统
  • 用途:存储数据
  • 场景:可以用于存储结构化,半结构化,非结构化的数据,适用于一次存入多次读取,例如网盘,用于做数据归档

rdbms

  • 概念:关系型数据库
  • 用途:存储数据
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-06-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据技术与架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 技术背景
  • 设计目的
  • 设计思想
  • 技术本质
  • 核心特性
  • 集群角色
    • client
      • zookeeper
      • 逻辑存储
      • 列存储
      • DDL
      • DML
      • 热点问题与数据倾斜
      • 预分区
      • 读取
      • 写入
      • Filter 过滤器
      • Hbase:ns/Hbase:meta
      • Hbase的存储原理
      • Hbase读写请求流程
      • LSM-tree模型
      • WAL
      • Flush
      • Compaction
      • Split
      • 数据加载
      • SQL on Hbase
      • 二级索引
      • 协处理器
      • Hbase优化
      • Flush
      • Compaction
      • Split
      • 列簇属性
      • Hbase和RDBMS对比
      • Hbase的增删改查
      • hbase/hive/hdfs/rdbms的区别
      相关产品与服务
      TDSQL MySQL 版
      TDSQL MySQL 版(TDSQL for MySQL)是腾讯打造的一款分布式数据库产品,具备强一致高可用、全球部署架构、分布式水平扩展、高性能、企业级安全等特性,同时提供智能 DBA、自动化运营、监控告警等配套设施,为客户提供完整的分布式数据库解决方案。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档