SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!

本期与大家分享的是,小北精心整理的Hbase学习笔记,希望对大家能有帮助,喜欢就给点鼓励吧,记得三连哦!欢迎各位大佬评论区指教讨论!
制作不易,各位大佬们给点鼓励!
点赞 ? 收藏? ? 关注?
欢迎各位大佬指教,一键三连走起!
目录 HBase总结图解
一、HBase基础部分
1、HBase简介
2、Hbase的系统架构
3、HBase的数据模型
4、HBase的特点
5、HBase的RowKey
6、HBase的列簇和列
7、HBase的时间戳
8、HBase的Cell单元格
9、HBase的HLog(WAL log)
10、HBase的 Region分裂策略
11、HBase的Compaction操作
12、HBase的读写流程
二、HBase Shell
三、HBase 的过滤器
1、过滤器
2、过滤器的作用
3、比较过滤器
比较运算符
常见的六大比较过滤器
4、专用过滤器
5、Bloom Filter 布隆过滤器
Bloom Filter 工作原理
Bloom Filter 在HBase中的应用
四、HBase的高可用
五、HBase框架及读写流程
六、MapReduce读写HBase
七、HBase调优
1、Pre-Creating Regions(预分区)
2、预分区实现步骤
3、HBase的Rowkey设计
rowkey长度原则
rowkey散列原则
rowkey唯一原则
热点问题,及解决方法
其它的一些调优建议
4、HBase In Memory
5、HBase Max Version
6、HBase Compact & Split
7、HBase BulkLoading
八、HBase Phoenix
HBase总结图解 点我返回目录

一、HBase基础部分 点我返回目录
在学习HBase之前我们要先了解下Hadoop的生态系统,认识HBase在Hadoop生态系统中的职责:
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

1、HBase简介 点我返回目录
  • HBase – 是Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩、实时读写的分布式数据库
  • HBase利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为其分布式协同服务
  • HBase主要用来存储非结构化和半结构化的松散数据(列式存储 NoSQL 数据库)
2、Hbase的系统架构 点我返回目录
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

HMaster的职责:
  1. 为Region server分配region
  2. 负责Region server的负载均衡
  3. 发现失效的Region server并重新分配其上的region
  4. 管理用户对table的增删改操作
HRegionServer的职责:
  1. Region server维护region,处理对这些region的IO请求
  2. Region server负责切分在运行过程中变得过大的region
Region的功能:
HBase会自动地把表水平划分成多个区域(Region),每个Region会保存一个表里面某段连续的数据;每个表一开始只有一个Region,随着数据的不断插入表中,Region会不断地增大,当增大到一个阀值的时候,Region就会等分为两个新的Region(裂变)。这样,当table中的行不断增多,就会有越来越多的Region。这样一张完整的表被保存在多个Regionserver 上。
Memstore 与 storefile的功能:
一个Region由多个store组成,而一个store对应一个CF(列族)store包括位于内存中的memstore和位于磁盘的storefile,写操作会先写入memstore,当memstore中的数据达到某个阈值,HRegionServer会启动flashcache进程写入storefile,每次写入形成单独的一个storefile,当storefile文件的数量增长到一定阈值后,系统会进行合并(minor、major compaction),在合并过程中会进行版本合并和删除工作(majar),形成更大的storefile,当一个region所有storefile的大小和数量超过一定阈值后,会把当前的region分割为两个,并由HMaster分配到相应的regionserver服务器,以实现负载均衡。而客户端检索数据,会先在memstore找,若找不到会再去找storefile。
3、HBase的数据模型 点我返回目录
HRegion是HBase中分布式存储和负载均衡的最小单元。 而,最小单元就表示不同的HRegion可以分布在不同的 HRegion server上。 HRegion由一个或者多个Store组成,每个store保存一个columns family。每个Strore又由一个memStore和0至多个StoreFile组成。如:StoreFile以HFile格式保存在HDFS上。
4、HBase的特点 点我返回目录
  1. 存储的数据量大:一个表可以有上亿行,上百万列。
  2. 面向列:面向列表(簇)的存储和权限控制,列(簇)独立检索。
  3. 稀疏:对于为空(NULL)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
  4. 无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态地增加,同一张表中不同的行可以有截然不同的列。
  5. 数据多版本:每个单元中的数据可以有多个版本,默认情况下,版本号自动分配, 版本号就是单元格插入时的时间戳。
  6. 数据类型单一:HBase中的数据都是字节数组,没有类型。
5、HBase的RowKey 点我返回目录
  • 唯一标识一行数据
  • 可以通过RowKey获取一行数据
  • 按照字典顺序排序的。
  • Rowkey只能存储64k的字节数据 10-100byte
6、HBase的列簇和列 点我返回目录
  • 列簇是属于表的Schema的一部分,在建表的时候必须指定至少一个Columns Family(列簇)
  • HBase中的列归属于某一个列簇
  • HBase在储存、权限控制、版本控制都是在列簇层面上进行
  • 一个列簇对应一个store
  • 列名以列族作为前缀,每个“列族”都可以有多个列成员(column);如course:a, course:b, 新的列族成员(列)可以随后按需、动态加入。
  • HBase把同一列族里面的数据存储在同一目录下,由几个文件保存。
7、HBase的时间戳 点我返回目录
  • HBase的时间戳就是一直提到的版本的概念,每条数据插入的时候都会记录插入时间(时间戳,64位整型)。时间戳可以由HBase(在数据写入时自动)赋值,此时时间戳是精确到毫秒的当前系统时间,时间戳也可以由客户显式赋值,如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。
  • 如果有多个版本,会按照时间戳的倒序(时间戳越大,表示数据越新)储存数据,在获取的时候,如果不指定版本,那么会默认最新一条的数据
  • 如果设置了TTL(Time to Live),那么HBase将会根据TTL以及数据的时间戳去删除过期的数据
8、HBase的Cell单元格 点我返回目录
  • Cell 是由 {row key,column(=< family> + < label>),version} 唯一确定的 单元。
  • Cell 中的数据是没有类型的,全部是字节码形式存储。单元格的内容是未解析的字节数组。
  • Cell 由行和列的坐标交叉决定。
  • 单元格是有版本的。
9、HBase的HLog(WAL log) 点我返回目录
  • HLog文件就是一个普通的Hadoop Sequence File,Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是”写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。
  • HLog SequeceFile的Value是HBase的KeyValue对象,即对应HFile中的KeyValue。
10、HBase的 Region分裂策略 点我返回目录
region中存储的是一张表的数据,当region中的数据条数过多的时候,会直接影响查询效率。当region过大的时候,region会被拆分为两个region,HMaster会将分裂的region分配到不同的regionserver上,这样可以让请求分散到不同的RegionServer上,以达到负载均衡 , 这也是Hbase的一个优点 。
  • ConstantSizeRegionSplitPolicy策略
    0.94版本前,HBase region的默认切分策略
    当region中最大的store大小超过某个阈值(hbase.hregion.max.filesize=10G)之后就会触发切分,一个region等分为2个region。
    但是在生产线上这种切分策略却有相当大的弊端(切分策略对于大表和小表没有明显的区分):
    • 阈值(hbase.hregion.max.filesize)设置较大对大表比较友好,但是小表就有可能不会触发分裂,极端情况下可能就1个,形成热点,这对业务来说并不是什么好事。
    • 如果设置较小则对小表友好,但一个大表就会在整个集群产生大量的region,这对于集群的管理、资源使用、failover来说都不是一件好事。
  • IncreasingToUpperBoundRegionSplitPolicy策略
    0.94版本~2.0版本默认切分策略
    ? 总体看和ConstantSizeRegionSplitPolicy思路相同,一个region中最大的store大小大于设置阈值就会触发切分。
    但是这个阈值并不像ConstantSizeRegionSplitPolicy是一个固定的值,而是会在一定条件下不断调整,调整规则和region所属表在当前regionserver上的region个数有关系.
    region split阈值的计算公式是:
    • 设regioncount:是region所属表在当前regionserver上的region的个数
    • 阈值 = regioncount^3 * 128M * 2,当然阈值并不会无限增长,最大不超过MaxRegionFileSize(10G),当region中最大的store的大小达到该阈值的时候进行region split
    例如:
    • 第一次split阈值 = 1^3 * 256 = 256MB
    • 第二次split阈值 = 2^3 * 256 = 2048MB
    • 第三次split阈值 = 3^3 * 256 = 6912MB
    • 第四次split阈值 = 4^3 * 256 = 16384MB > 10GB,因此取较小的值10GB
    • 后面每次split的size都是10GB了
    特点
    • 相比ConstantSizeRegionSplitPolicy,可以自适应大表、小表;
    • 在集群规模比较大的情况下,对大表的表现比较优秀
    • 对小表不友好,小表可能产生大量的小region,分散在各regionserver上
    • 小表达不到多次切分条件,导致每个split都很小,所以分散在各个regionServer上
  • SteppingSplitPolicy策略
    2.0版本默认切分策略
    ? 相比 IncreasingToUpperBoundRegionSplitPolicy 简单了一些
    ? region切分的阈值依然和待分裂region所属表在当前regionserver上的region个数有关系
    • 如果region个数等于1,切分阈值为flush size 128M * 2
    • 否则为MaxRegionFileSize。
    这种切分策略对于大集群中的大表、小表会比 IncreasingToUpperBoundRegionSplitPolicy 更加友好,小表不会再产生大量的小region,而是适可而止。
  • KeyPrefixRegionSplitPolicy策略
    根据rowKey的前缀对数据进行分区,这里是指定rowKey的前多少位作为前缀,比如rowKey都是16位的,指定前5位是前缀,那么前5位相同的rowKey在相同的region中。
  • DelimitedKeyPrefixRegionSplitPolicy策略
    保证相同前缀的数据在同一个region中,例如rowKey的格式为:userid_eventtype_eventid,指定的delimiter为 _ ,则split的的时候会确保userid相同的数据在同一个region中。
    按照分隔符进行切分,而KeyPrefixRegionSplitPolicy是按照指定位数切分。
  • BusyRegionSplitPolicy策略
    按照一定的策略判断Region是不是Busy状态,如果是即进行切分
    如果你的系统常常会出现热点Region,而你对性能有很高的追求,那么这种策略可能会比较适合你。它会通过拆分热点Region来缓解热点Region的压力,但是根据热点来拆分Region也会带来很多不确定性因素,因为你也不知道下一个被拆分的Region是哪个。
  • DisabledRegionSplitPolicy策略
    不启用自动拆分, 需要指定手动拆分
11、HBase的Compaction操作 点我返回目录
Minor Compaction:
  • 指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的Cell。一次 Minor Compaction 的结果是更少并且更大的StoreFile。
Major Compaction:
  • 指将所有的StoreFile合并成一个StoreFile,这个过程会清理三类没有意义的数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据。另外,一般情况下,major compaction时间会持续比较长,整个过程会消耗大量系统资源,对上层业务有比较大的影响。因此线上业务都会将关闭自动触发major compaction功能,改为手动在业务低峰期触发。
深入理解 HBase Compaction 机制,好文解析:https://cloud.tencent.com/developer/article/1488439
12、HBase的读写流程 点我返回目录
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

二、HBase Shell 点我返回目录
语法1:创建表 create , {NAME => , VERSIONS => } # 创建一个User表,并且有一个info列族 create 'User','info'语法2:查看所有表 list语法3:查看表详情 describe 'User'语法4:表修改 # 删除指定的列族 alter 'User', 'delete' => 'info' #增加新的列族 alter 'User', NAME => 'info'语法5:插入数据 put
,,, #例如: put 'User', 'row1', 'info:name', 'xiaoming' put 'User', 'row2', 'info:age', '18' put 'User', 'row3', 'info:sex', 'man'语法6:根据rowKey查询某个记录 get
,,[,....] #例如: get 'User', 'row2'语法7:查询所有记录 scan
, { COLUMNS => [ ,.... ], LIMIT => num} #扫描所有记录 scan 'User' #扫描前2条 scan 'User', { LIMIT => 2} #范围查询 STARTROW(开始rowkey) ENDROW(结束rowkey) scan 'User', {STARTROW => 'row2'} scan 'User', {STARTROW => 'row2', ENDROW => 'row2'} scan 'User', {STARTROW => 'row2', ENDROW => 'row3'} #另外,还可以添加TIMERANGE和FITLER等高级功能 #STARTROW,ENDROW必须大写,否则报错; 查询结果不包含等于ENDROW的结果集语法8:统计表记录数 count
, { INTERVAL => intervalNum, CACHE => cacheNum} #INTERVAL设置多少行显示一次及对应的rowkey,默认1000; #CACHE每次去取的缓存区大小,默认是10,调整该参数可提高查询速度语法9:删除 #删除列 delete 'User', 'row1', 'info:age' #指定rowkey删除 deleteall 'User', 'row2' #删除表中所有数据 truncate 'User'语法10:表管理 #禁用表 disable 'User' #启用表 enable 'User' #测试表是否存在 exists 'User' #删除表,删除前,必须先disable禁用表 disable 'User' drop 'User'
三、HBase 的过滤器 1、过滤器 点我返回目录
HBase 的基本 API,包括增、删、改、查等。其中的增、删都是相对简单的操作,与传统的 RDBMS 相比,这里的查询操作略显苍白,只能根据特性的行键进行查询(Get)或者根据行键的范围来查询(Scan)。但是HBase 不仅提供了这些简单的查询,同时还提供了更加高级的过滤器(Filter)来查询。
2、过滤器的作用 点我返回目录
  • 过滤器的作用是在服务端判断数据是否满足条件,然后只将满足条件的数据返回给客户端
  • 过滤器的类型很多,但是可以分为两大类:
    • 比较过滤器:可应用于rowkey、列簇、列、列值过滤器
    • 专用过滤器:只能适用于特定的过滤器
3、比较过滤器 点我返回目录
过滤器可以根据列族、列、版本等更多的条件来对数据进行过滤,基于 HBase 本身提供的三维有序(行键,列,版本有序),这些过滤器可以高效地完成查询过滤的任务,带有过滤器条件的 RPC 查询请求会把过滤器分发到各个 RegionServer(这是一个服务端过滤器),这样也可以降低网络传输的压力。而,使用过滤器至少需要两类参数:一类是抽象的操作符,另一类是比较器
比较运算符
HBase 提供了枚举类型的变量来表示这些抽象的操作符:
LESS: 小于 LESS_OR_EQUAL: 小于等于 EQUAL: 等于 NOT_EQUAL:不等于 GREATER_OR_EQUAL : 大于等于 GREATER: 大于 NO_OP ; 不比较,排除所有

常见的六大比较过滤器
点我返回目录
BinaryComparator
二进制比较器,按字节索引顺序比较指定字节数组,采用Bytes.compareTo(byte[])
BinaryPrefixComparator
前缀二进制比较器。与二进制比较器不同的是,只比较前缀是否相同。
NullComparator
判断给定的是否为空
BitComparator
按位比较
RegexStringComparator
提供一个正则的比较器,仅支持 EQUAL 和非EQUAL
SubstringComparator
判断提供的子串是否出现在值中,并且不区分大小写。
列值过滤器:效率较低,需要做全表扫描
SingleColumnValueFilter:用于测试值的情况(相等,不等,范围 、、、)
列簇过滤器:
FamilyFilter:用于过滤列族(通常在 Scan 过程中通过设定某些列族来实现该功能,而不是直接使用该过滤器)。
列名过滤器:
QualifierFilter:用于列名(Qualifier)过滤。
行键过滤器:效率较高,行键前缀过滤效率较高
RowFilter:行键过滤器,一般来讲,执行 Scan 使用 startRow/stopRow 方式比较好,而 RowFilter 过滤器也可以完成对某一行的过滤。
4、专用过滤器 点我返回目录
单列值过滤器:SingleColumnValueFilter
SingleColumnValueFilter会返回满足条件的cell所在行的所有cell的值(即会返回一行数据)
列值排除过滤器:SingleColumnValueExcludeFilter
与SingleColumnValueFilter相反,会排除掉指定的列,其他的列全部返回
rowkey前缀过滤器:PrefixFilter
通过PrefixFilter前缀过滤器查询以150010008开头的所有前缀的rowkey
分页过滤器PageFilter
使用PageFilter分页效率比较低,每次都需要扫描前面的数据,直到扫描到所需要查的数据
可设计一个合理的rowkey来实现分页需求
5、Bloom Filter 布隆过滤器 点我返回目录
Bloom Filter(布隆过滤器)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
在计算机科学中,我们常常会碰到时间换空间或者空间换时间的情况,即为了达到某一个方面的最优而牺牲另一个方面。Bloom Filter在时间空间这两个因素之外又引入了另一个因素:错误率。在使用Bloom Filter判断一个元素是否属于某个集合时,会有一定的错误率。也就是说,有可能把不属于这个集合的元素误认为属于这个集合(False Positive),但不会把属于这个集合的元素误认为不属于这个集合(False Negative)。在增加了错误率这个因素之后,Bloom Filter通过允许少量的错误来节省大量的存储空间。
它的用法其实是很容易理解的,我们拿个HBase中应用的例子来说下,我们已经知道rowKey存放在HFile中,那么为了从一系列的HFile中查询某个rowkey,我们就可以通过 Bloom Filter 快速判断 rowkey 是否在这个HFile中,从而过滤掉大部分的HFile,减少需要扫描的Block。
Bloom Filter 工作原理 点我返回目录
BloomFilter对于HBase的随机读性能至关重要,对于get操作以及部分scan操作可以剔除掉不会用到的HFile文件,以减少实际IO次数,提高随机读性能。简单地介绍一下Bloom Filter的工作原理,Bloom Filter使用位数组来实现过滤,初始状态下位数组每一位都为0,如下图所示:
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

假如此时有一个集合S = {x1, x2, … xn},Bloom Filter使用k个独立的hash函数,分别将集合中的每一个元素映射到{1,…,m}的范围。对于任何一个元素,被映射到的数字作为对应的位数组的索引,该位会被置为1。比如元素x1被hash函数映射到数字8,那么位数组的第8位就会被置为1。下图中集合S只有两个元素x和y,分别被3个hash函数进行映射,映射到的位置分别为(0,3,6)和(4,7,10),对应的位会被置为1:
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

现在假如要判断另一个元素是否是在此集合中,只需要被这3个hash函数进行映射,查看对应的位置是否有0存在,如果有的话,表示此元素肯定不存在于这个集合,否则有可能存在。下图所示就表示z肯定不在集合{x,y}中:
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片
从上面的内容我们可以得知,Bloom Filter有两个很重要的参数
哈希函数个数
位数组的大小
Bloom Filter 在HBase中的应用 点我返回目录
HFile 中和 Bloom Filter 相关的Block,
Scanned Block Section(扫描HFile时被读取):Bloom Block
Load-on-open-section(regionServer启动时加载到内存):BloomFilter Meta Block、Bloom Index Block
Bloom Block:Bloom数据块,存储Bloom的位数组
Bloom Index Block:Bloom数据块的索引
BloomFilter Meta Block:从HFile角度看bloom数据块的一些元数据信息,大小个数等等。
HBase中每个HFile都有对应的位数组,KeyValue在写入HFile时会先经过几个hash函数的映射,映射后将对应的数组位改为1,get请求进来之后再进行hash映射,如果在对应数组位上存在0,说明该get请求查询的数据不在该HFile中。
HFile中的Bloom Block中存储的就是上面说的位数组,当HFile很大时,Data Block 就会很多,同时KeyValue也会很多,需要映射入位数组的rowKey也会很多,所以为了保证准确率,位数组就会相应越大,那Bloom Block也会越大,为了解决这个问题就出现了Bloom Index Block,一个HFile中有多个Bloom Block(位数组),根据rowKey拆分,一部分连续的Key使用一个位数组。这样查询rowKey就要先经过Bloom Index Block(在内存中)定位到Bloom Block,再把Bloom Block加载到内存,进行过滤。
四、HBase的高可用 点我返回目录
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

五、HBase框架及读写流程 点我返回目录
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

六、MapReduce读写HBase 点我返回目录
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

七、HBase调优 点我返回目录
1、Pre-Creating Regions(预分区) 点我返回目录
  • 默认情况下,在创建HBase表的时候会自动创建一个region分区,当导入数据的时候, 所有的HBase客户端都向这一个region写数据,直到这个region足够大了才进行切分。 一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入 HBase时,会按照region分区情况,在集群内做数据的负载均衡。
  • 如果知道hbase数据表的key的分布情况,就可以在建表的时候对hbase进行region的预分区。这样做的好处是防止大数据量插入的热点问题,提高数据插入的效率。
2、预分区实现步骤 点我返回目录
首先就是要想明白数据的key是如何分布的,然后规划一下要分成多少region,每个region的startkey和endkey是多少,然后将规划的key写到一个文件中。比如,key的前几位字符串都是从0001~0010的数字,这样可以分成10个region,划分key的文件如下:注意不要多一行空行
为什么后面会跟着一个"|",是因为在ASCII码中,"|"的值是124,大于所有的数字和字母等符号,当然也可以用“~”(ASCII-126)。分隔文件的第一行为第一个region的stopkey,每行依次类推,最后一行不仅是倒数第二个region的stopkey,同时也是最后一个region的startkey。也就是说分区文件中填的都是key取值范围的分隔点,如下图所示:
SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!
文章图片

3、HBase的Rowkey设计 点我返回目录
HBase是三维有序存储的,通过rowkey(行键),column key(column family和qualifier)和TimeStamp(时间戳)这个三个维度可以对HBase中的数据进行快速定位。
HBase中rowkey可以唯一标识一行记录,在HBase查询的时候,有三种方式:
  1. 通过get方式,指定rowkey获取唯一一条记录
  2. 通过scan方式,设置startRow和stopRow参数进行范围匹配
  3. 全表扫描,即直接扫描整张表中所有行记录
rowkey长度原则
点我返回目录
rowkey是一个二进制码流,可以是任意字符串,最大长度 64kb ,实际应用中一般为10-100bytes,以 byte[] 形式保存,一般设计成定长。建议越短越好,不要超过16个字节,原因如下:数据的持久化文件HFile中是按照KeyValue存储的,如果rowkey过长,比如超过100字节,1000w行数据,光rowkey就要占用100*1000w=10亿个字节,将近1G数据,这样会极大影响HFile的存储效率;MemStore将缓存部分数据到内存,如果rowkey字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。
rowkey散列原则
点我返回目录
如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。
rowkey唯一原则
点我返回目录
必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。
热点问题,及解决方法
点我返回目录
HBase中的行是按照rowkey的字典顺序排序的,这种设计优化了scan操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于scan。然而糟糕的rowkey设计是热点的源头。 热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region,由于主机无法服务其他region的请求。 设计良好的数据访问模式以使集群被充分,均衡的利用。
为了避免写热点,设计rowkey使得不同行在同一个region,但是在更多数据情况下,数据应该被写入集群的多个region,而不是一个。
下面是一些常见的避免热点问题的方法以及它们的优缺点:
加盐 点我返回目录
【SQL数据库|Hbase从入门到精通,精心整理的学习笔记,自学党快来瞅一瞅,赶紧收藏吧!】这里所说的加盐不是密码学中的加盐,而是在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。分配的前缀种类数量应该和你想使用数据分散到不同的region的数量一致。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点。
哈希 点我返回目录
哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据
反转 点我返回目录
第三种防止热点的方法时反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。
反转rowkey的例子以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,这样的就避免了以手机号那样比较固定开头导致热点问题
时间戳反转 点我返回目录
一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用 Long.Max_Value - timestamp 追加到key的末尾,例如[key][reverse_timestamp] , [key] 的最新值可以通过scan [key]获得[key]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。
比如需要保存一个用户的操作记录,按照操作时间倒序排序,在设计rowkey的时候,可以这样设计:
[userId反转][Long.Max_Value - timestamp],在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow是[userId反转][000000000000],stopRow是[userId反转][Long.Max_Value - timestamp]
如果需要查询某段时间的操作记录,startRow是[user反转][Long.Max_Value - 起始时间],stopRow是[userId反转][Long.Max_Value - 结束时间]
其它的一些调优建议
点我返回目录
  • 尽量减少rowkey和列的大小,当具体的值在系统间传输时,它的rowkey,列簇、列名,时间戳也会一起传输。如果你的rowkey、列簇名、列名很大,甚至可以和具体的值相比较,那么将会造成大量的冗余,不利于数据的储存与传输。列族尽可能越短越好,最好是一个字符;列名也尽可能越短越好,冗长的列名虽然可读性好,但是更短的列名存储在HBase中会更好
4、HBase In Memory 点我返回目录
  • 创建表的时候,可以通过HColumnDescriptor.setInMemory(true)将表放到 RegionServer的缓存中,保证在读取的时候被cache命中。
5、HBase Max Version
  • 创建表的时候,可以通过HColumnDescriptor.setMaxVersions(int maxVersions)设置 表中数据的最大版本,如果只需要保存最新版本的数据,那么可以设置 setMaxVersions(1)。
6、HBase Compact & Split 点我返回目录
  • 在HBase中,数据在更新时首先写入WAL 日志(HLog)和内存(MemStore)中, MemStore中的数据是排序的,当MemStore累计到一定阈值时,由单独的线程flush到磁盘上,成为一个StoreFile。与此同时, 系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了
  • StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定的阈值后,就会进行一次合并(major compact),将对同一个key的修改合并到一起,形成一个大的StoreFile,当StoreFile的大小达到一定阈值后,又会对 StoreFile进行分割(split),等分为两个StoreFile。
7、HBase BulkLoading 点我返回目录
优点:
  1. 如果我们一次性入库hbase巨量数据,处理速度慢不说,还特别占用Region资源, 一个比较高效便捷的方法就是使用 “Bulk Loading”方法,即HBase提供的HFileOutputFormat类。
  2. 它是利用hbase的数据信息按照特定格式存储在hdfs内这一原理,直接生成这种hdfs内存储的数据格式文件,然后上传至合适位置,即完成巨量数据快速入库的办法。配合mapreduce完成,高效便捷,而且不占用region资源,增添负载。
限制:
  1. 仅适合初次数据导入,即表内数据为空,或者每次入库表内都无数据的情况。
  2. HBase集群与Hadoop集群为同一集群,即HBase所基于的HDFS为生成HFile的MR的集群
八、HBase Phoenix 点我返回目录
Hbase适合存储大量的对关系运算要求低的NOSQL数据,受Hbase 设计上的限制不能直接使用原生的API执行在关系数据库中普遍使用的条件判断和聚合等操作。Hbase很优秀,一些团队寻求在Hbase之上提供一种更面向普通开发人员的操作方式,Apache Phoenix即是。
Phoenix 基于Hbase给面向业务的开发人员提供了以标准SQL的方式对Hbase进行查询操作,并支持标准SQL中大部分特性:条件运算,分组,分页,等高级查询语法。
有关phoenix的详细介绍,和使用操作,下一期整理!
链接位置先给预留好,嘻嘻

    推荐阅读