Hbase实战处理(一)关于hbase的表设计和集成

一、Hbase的原理讲解

1、hbase介绍
2、hbase集群架构(具体配置见其他文章)

在这里插入图片描述
hbase集群的HA配置

(假如有3台机器(同时是regionserver角色),master、slaver1、slaver2)
stop-hbase.sh
cd /home/hadoop-twq/bigdata/hbase-1.2.6/conf
vi backup-masters 在master机器上文件增加如下的记录:
slave1    ---backup master的节点ip

---把backup的信息同步给其余的slave。
scp backup-masters hadoop-twq@slave1:~/bigdata/hbase-1.2.6/conf/
scp backup-masters hadoop-twq@slave2:~/bigdata/hbase-1.2.6/conf/
start-hbase.sh
jps验证
访问: http://slave1:16010
kill掉master上的HMaster,然后slave1上的HMaster成为master了
3、hbase数据模型

hbase是列式数据库,有列簇、命名空间、版本号、TTL等特性。

  • namespace:表空间namespace就像MySql中的库的概念一样,库里可以创建表,那么namespace里也可以创建表)
  • 列簇:1个列簇是多个列的集合,对应是是不经常变化或者相同类型的列的集合。
创建3个列簇
create 'webtable',{NAME => 'content'},{NAME => 'language'},{NAME => 'link_url'}
  • version:该属性让Hbase表支持存储多个VERSIONS的版本列数据
--创建habse表t1,列簇是f1
create 't1',{NAME => 'f1'}

---给1个列簇修改版本号
alter 't1',{NAME => 'f1', VERSIONS => 3}

---给1个列插入多个版本数据
hbase(main):015:0> put 't1','rowkey1','f1:name','chhliu'
0 row(s) in 0.5890 seconds
hbase(main):016:0> put 't1','rowkey1','f1:name','xyh123'
0 row(s) in 0.1900 seconds
hbase(main):017:0> put 't1','rowkey1','f1:name','chhliuxyh'

----命令行获得多个版本的数据
hbase(main):002:0> get 't1','rowkey1',{COLUMN=>'f1:name',VERSIONS=>3}
COLUMN                             CELL                                                                                               
 f1:name                           timestamp=1482820567560, value=chhliuxyh                                                           
 f1:name                           timestamp=1482820541363, value=xyh123                                                              
 f1:name                           timestamp=1482820503889, value=chhliu    

----命令行获得2个版本(最近2个)的数据
hbase(main):002:0> get 't1','rowkey1',{COLUMN=>'f1:name',VERSIONS=>3}
COLUMN                             CELL                                                                                               
 f1:name                           timestamp=1482820541363, value=xyh123                                                              
 f1:name                           timestamp=1482820503889, value=chhliu 
 
  • TTL(Time To Live):数据的生命周期,TTL参数的单位是秒,默认值是Integer.MAX_VALUE,即2^31-1=2 147 483 647 秒,大约68年。使用TTL默认值的数据可以理解为永久保存。
create 'webtable_ttl',{NAME => 'content'},{NAME => 'language', VERSIONS => 1},{NAME => 'link_url', TTL => 5}
put 'webtable_ttl','http://www.51cto.com/','link_url:sina','http://tech.sina.com.cn/'
get 'webtable_ttl','http://www.51cto.com/',{COLUMN => 'link_url:sina'}
alter 'webtable_ttl',{NAME => 'link_url', TTL => 3}

alter 'test',{NAME => 'cf',TTL => 'FOREVER'}   ---desc "test" 查看设置(FOREVER永不过期)是否成功
 

4、hbase读写流程&特性
5、表组成

在这里插入图片描述
1、Table -> Region 【1对多】
Region都是分布在所有的HRegionServer上的每一个Region负责管理和存储一个Table中的某段数据每一个table的RowKey是按照字符串的自然顺序升序排列的。

2、Region -> Column Family【1对多】
一个Region负责管理和存储一个或者多个Colummn Family的数据

3、Column Family -> Store 【1对多】
一个Column Family对应着一个Store
一个Store中含有一个MemoryStore和若干个HFile

4、HFile ->Block 【1对多】
一个HFile含有若干个不同类型的BlockBlock的大小通常为8K到1MB,默认的大小是64KB的Block的类型有:Data Blocks、Index Blocks、Bloom filter Blocks以及Trailer block。

在这里插入图片描述

5、Block -> KeyValue 【1对多】
一个Block包含一个magic数字和若干个KeyValue的数据。
在这里插入图片描述
HFile在存储每一个Row时,不是把这一条Row的全部Family/Column整合成在一起,保存起来的,如下:

RowKey | Family:Column1 -> value | Family:Column2 -> value   ----我们认为的存储格式

它是把这条Row,根据Column拆分成好几个KeyValue,保存起来的,如下:

RowKey/Family:Column1 -> value
RowKey/Family:Column2 -> value

我们可以看到,RowKey需要重复保存很多次,而且Family:Column这个往往都是非常相似的,它也需要保存很多次.这对磁盘非常不友好.当Family:Column越多时,就需要占用越多不必要的磁盘空间。

Block Encoder&Compressors

  • Compressors压缩:
    block常常以一定压缩格式存储,主要为了节约存储空间,默认支持以下压缩格式 none、Snappy、LZO4、LZ4、GZ。大部分的场景下默认使用Snappy或者LZO就好,因为他们提供了更好的性能

  • Block Encoder:
    在实际中不是简单对其进行压缩就能提高查询效率的。我们知道当读取hbase数据时,是需要先读MemStore,然后再读BlockCache的.那我们的Block越小,能放到BlockCache中的数据就越多,命中率就越高,对Scan就越友好。
    Block Encoder是通过某种算法,对Data Block中的数据进行压缩,这样Block的Size小了,放到Block Cache中的就多了。

这儿提出两个问题:

  • 压缩以后,占的Disk/Memory是少了,但是解压的时候,需要更多的CPU时间.如何均衡呢?
  • 如果我们的业务,偏重的是随机Get,那放到Block Cache中不一定好吧?不仅放到Block Cache中的Block很容易读不到,对性能并没有什么提升,还会产生额外的开销,比如将其它偏重Scan的业务的Block排挤出Block Cache,导致其它业务变慢。

HBase中提供了五种Data Block Encoding Types,具体有:
NONE
PREFIX
DIFF
FAST_DIFF
PREFIX_TREE
PREFIX
一般来说,同一个Block中的Key(KeyValue中的Key,不仅包含RowKey,还包含Family:Column),都很相似.它们往往只是最后的几个字符不同.例如,KeyA是RowKey:Family:Qualifier0,跟它相邻的下一个KeyB可能是RowKey:Family:Qualifier1。

Prefix
在PREFIX中,相对于NONE,会额外添加一列,表示当前key(KeyB)和它前一个key(KeyA),相同的前缀的长度(记为PrefixLength)。
我们有一些Row,当使用NONE这种Block Encoding时,如下图所示:
在这里插入图片描述
而如果采用PREFIX这种Block Encoding,那就是这样子了:
在这里插入图片描述
在上面的例子中,如果KeyA是这个Block中的第一个key,那它的PrefixLength就是0.而KeyB的PrefixLength是23。所以对应样例:原来的2条KeyA且key length是24的记录(对应2个列:Qualifier0、Qualifier1,每个列1行),在PREFIX格式下对应3条记录,第1条记录对应表的第1个记录只是PrefixLength为0,将原表2条数据的话按这条记录为参照,不再重复保存rowkey,而是用PrefixLength=23和列名称1、N标识原来的keylength为24的2条记录。

Diff

DIFF是对PREFIX的一种改良.它把key看成很多个部分,对每部分进行压缩,提高效率.它添加了两个新的字段,timestamp和type.如果KeyB的ColumnFamily、key length、value length、type和KeyA相同,那么它就会在KeyB中被省略(对应key length是24的第1行和第2行,第2行就是第1行的key-value, 对应都是第1列的数据,所以重复数据的部分字段省略了)。

另外,timestamp,存储的是相对于前一个Row的偏移量.

默认情况下,DIFF是不启用的。因为它会导致写数据,以及Scan数据更慢.但是,相对于PREFIX/NONE,它会在Block Cache中缓存更多数据.

用DIFF压缩的block如下图所示:
在这里插入图片描述
Fast Diff
FAST_DIFF跟DIFF非常相似,所不同的是,它额外增加了一个字段,表示RowB是否跟RowA完全一样,如果是的话,那数据就不需要重复保存了(也就是对应key length是24的第1行和第2行,第2行对应是第1列的数据,所以重复数据的只保留1份即可)。
如果你的rowkey很长,并且有很多的Column的话,则推荐使用Fast Diff。

如何选择压缩算法以及Block Encoding Type?

  • 如果Key很长,或者有很多Column,那么推荐使用FAST_DIFF。
  • 如果数据是冷数据,不经常被访问,那么使用GZIP压缩格式.因为虽然它比Snappy/LZO需要占用更多而CPU,但是它的压缩比率更高,更节省磁盘。
  • 如果是热点数据,那么使用Snappy/LZO压缩格式.它们相比GZIP,占用的CPU更少。
  • 在大多数情况下,Snappy/LZO的选择都更好. Snappy比LZO更好。
---建表的属性,考虑表查询效率的提高,可以在java层或者xml下进行调整。

val tableDescriptor = new HTableDescriptor(table)
tableDescriptor.addFamily(new HColumnDescriptor(familyName))
tableDescriptor.setConfiguration("COMPRESSION", "SNAPPY")
tableDescriptor.setConfiguration("VERSIONS", "1")
tableDescriptor.setConfiguration("BLOCKCACHE", "FALSE")
tableDescriptor.setConfiguration("BLOOMFILTER", "ROW")
tableDescriptor.setConfiguration("DATA_BLOCK_ENCODING", "FAST_DIFF")
6、Table Schema的设计和rowkey设计

6.1、建表设计
基于hbase的特性需要对表设计做相关限制。

  • 1、每一个region的大小在10到50G。
<property>
<name>hbase.hregion.max.filesize</name>  #这个参数的配置控制每一个Region的大小。
<value>52428800</value>   #当前设置为50M, 默认是10G
</property>
  • 2、每一个table控制在50-100个regions。
    注意: HBase 可以进行预分区时,但如果创建的 region 太多 ,集群不堪重负,由此带来了 HBase 的意外宕机。
为什么合理分配 region 数量有益于集群稳定?
1、MSLAB: 有助于防止堆内存的碎片化,减轻 Full GC , GC 的问题,默认是开启的。但每个 MemStore 需要 2MB(一个列簇对应一个写缓存 Memstore )。所以如果每个 region 有 2 个列簇,总有 1000 个 region ,就算不存储数据也要 3.95GB 内存空间
2、过多的 region,导致 Memstore 也过多,内存大小触发 Region Server 级别限制导致 flush,这会对用户请求产生较大的影响,可能阻塞该 Region Server 上的更新操作
3、HMaster 要花大量的时间来分配和移动 Region,且过多 Region 会增加 ZooKeeper 的负担
4、从 HBase 读入数据进行处理的 Mapreduce程序,过多 Region 会产生太多Map任务数量,默认情况下一个 region 对应一个map。因此,如果一个 HRegion 中 Memstore 过多,而且大部分都频繁写入数据,每次 flush 的开销必然会很大,因此也建议在进行表设计的时候尽量减少 ColumnFamily 的个数
Region 数量计算的公式:
((RegionServer Xmx) * hbase.regionserver.global.memstore.size) / (hbase.hregion.memstore.flush.size * (列族数量))
 
举例:一个 Region Server 有 16GB 内存,则 16384*0.4 / 128 mb 等于 51 个活跃的 region
  • 3、每一个table控制在1到3个column family,且按更新频率对CF进行分开创建
    比如一张hbase表需要存储每个用户的信息(比如名字、年龄等)和这个用户每天访问网站的信息。分以下两种情况:
    1)对于用户的信息,不经常变,而且量少
    2)对于用户每天访问网站的信息是经常变化且数据量很大的
    如果将这两种信息放在同一个column family中的话,用户每天访问网站的信息数据的增大导致会出现
    memory store的flush,然后会导致compaction,因为compaction是column family级别的,所以会将
    每个用户的信息(比如名字、年龄等)和这个用户每天访问网站的信息都合并到文件中。但是用户的信息不大,且不经常变,没必要每次compaction都要将用户的信息写到磁盘中,导致资源的浪费。
    所以将用户的信息和用户每天访问网站的信息分成两个column family来存。

  • 4、每一个column family的命名最好要短,因为column family是会存储在数据文件中的。

6.2、RowKey的设计
长度原则:rowkey的长度一般被建议在10-100个字节,不过建议是越短越好。

`1、数据持久化文件HFile是按照keyvalue存储的,如果rowkey过长,比如100个字节,
1000万列数据光Rowkey就要占用100*1000万=10亿个字节,将近1G数据,这会极大影响HFile的存储效率
2、MemStore将缓存部分数据到内存,如果Rowkey字段过长内存的有效利用率会降低,
系统将无法缓存更多的数据,这会降低检索效率。因此Rowkey的字节长度越短越好。
3、目前操作系统是都是64位系统,内存8字节对齐。如果rowkey是8字节的整数倍的话,则利用了操作系统的最佳特性。`

存储顺序: rowkey是按照字典顺序进行存储的,相似的rowkey会存储在同一个Region中。如果rowkey没有设计好的话,还会引发Hotspotting:
解决Hotspotting的三个方法:

  1. Salting((撒盐似的)散布、加盐)
create 'test_salt', 'f',SPLITS => ['b','c','d']
原始的rowkey:   salting rowkey:
boo0001			a-boo0001
boo0002 		b-boo0002
boo0003			c-boo0003
boo0004			d-boo0004
boo0005			a-boo0005
boo0006			d-boo0006

2、Hashing

create 'test_hash', 'f', { NUMREGIONS => 4, SPLITALGO => 'HexStringSplit' }
原始的rowkey:			md5 hash rowkey:
boo0001				4b5cdf065e1ada3dbc8fb7a65f6850c4
boo0002				b31e7da79decd47f0372a59dd6418ba4
boo0003				d88bf133cf242e30e1b1ae69335d5812
boo0004				f6f6457b333c93ed1e260dc5e22d8afa

3、反转rowkey

时间戳类型的rowkey:	反转rowkey:
1524536830360		0630386354251
1524536830362		2630386354251
1524536830376		6730386354251

多条件查询
采用 UserID + CreateTime + FileID等多个关键性查询条件组成RowKey,这样既能满足多条件查询,又能有很快的查询速度。
在这里插入图片描述

(1)每条记录的RowKey,每个字段都需要填充到相同长度。假如预期我们最多有10万量级的用户,则userID应该统一填充至6位,如000001,000002…
(2)结尾添加全局唯一的FileID的用意也是使每个文件对应的记录全局唯一。避免当UserID与CreateTime相同时的两个不同文件记录相互覆盖。
rowKey(userID 6位 + time 8位 + fileID 6位) name category ….
00000120120902000001
00000120120904000002
00000120120906000003
00000120120908000004
00000120120910000005
00000120120914000007
00000220120912000006
00000220120916000008
00000320120918000009
00000420120920000010 


create 'sound','f', SPLITS => ['0','1','2','3','4','5','6','7','8','9']       #根据样例数据进行预分区。
怎么用这张表呢?
1)在建立一个scan对象后,我们setStartRow(00000120120901),setStopRow(00000120120914)。
scan时只扫描userID=1的数据,且时间范围限定在这个指定的时间段内,满足了按用户以及按时间
范围对结果的筛选。并且由于记录集中存储,性能很好。
2)然后使用 SingleColumnValueFilter(org.apache.hadoop.hbase.filter.SingleColumnValueFilter),共4
个,分别约束name的上下限,与category的上下限。满足按同时按文件名以及分类名的前缀匹配
3)如果需要分页还可以再加一个PageFilter限制返回记录的个数。

二、Spark On HBase

三、Hbase和Solr构建OLAP平台

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/676622.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

javascript导入excel文件

导入文件用到一个 xlsx.core.js 的包。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><script type"tex…

vfrom二开给左边添加字段或者容器

例如&#xff0c;我在左侧加入一个 我的公司 字段 修改三个文件&#xff0c;这是文件目录 这个文件是当界面选择 简体中文 的时候&#xff0c;显示的 字段组件 或者 容器组件的中文名 这个文件是当界面选择 English 的时候&#xff0c;显示的 字段组件 或者 容器组件的英文名 把…

Java集合基础知识点系统性总结篇

目录 集合一、图解集合的继承体系&#xff1f;&#xff08;[图片来源](https://www.cnblogs.com/mrhgw/p/9728065.html)&#xff09;点击查看大图二、List,Set,Map三者的区别&#xff1f;三、List接口的实现3.1、Arraylist 、 LinkedList、Vector3.2、Arraylist 、 LinkedList、…

Java如何实现pdf转base64以及怎么反转?

问题需求 今天在做发送邮件功能的时候&#xff0c;发现邮件的附件部分&#xff0c;比如pdf文档&#xff0c;要求先把pdf转为base64&#xff0c;邮件才会发送。那接下来就先看看Java 如何把 pdf文档转为base64。 两种方式&#xff0c;一种是通过插件 jar 包的方式引入&#xf…

pyside6安装

目录 1. 安装2. 配置PyCharm环境3. 测试 1. 安装 打开Anaconda Prompt&#xff0c;执行以下命令创建虚拟环境并激活 # 创建名为 myEnv, python版本为3.9 的虚拟环境 conda create -n myEnv python3.9 # 激活创建的虚拟环境 conda avtivate myEnv使用pip安装Pyside6&#xff0…

git拉去代码报错“Failed to connect to 127.0.0.1 port 31181: Connection refused“

最近参与了一个新项目&#xff0c;在使用git clone 克隆代码时遇到了一个报错"fatal: unable to access ‘https://example.git/’: Failed to connect to 127.0.0.1 port 31181: Connection refused",今天就和大家分享下解决过程。 报错详情 在使用git clone 克隆…

回溯算法题模板与实战详解

文章目录 回溯算法模板实战详解全排列问题N皇后问题 组合总和问题子集问题括号生成问题单词搜索问题 回溯算法是一种通过试错的方式来寻找问题解决方案的算法&#xff0c;常用于解决约束满足问题、组合优化问题和排列组合问题。其核心思想是深度优先搜索(DFS)与剪枝策略的结合&…

Apipost IDEA 插件使用说明

Apipost Helper作为IDEA插件&#xff0c;可以快速生成和查询API文档&#xff0c;直观友好地在IDE中调试接口。它简化了开发流程并提升效率&#xff0c;即使新手也能够迅速掌握。Apipost Helper提供了诸多便捷功能&#xff0c;如通过代码查找接口或者通过接口查找代码等&#xf…

第十五届蓝桥杯物联网试题(国赛)

好&#xff0c;很好&#xff0c;国赛直接来个阅读理解&#xff0c;我猛做4个小时40分钟&#xff0c;cpu都干冒烟了&#xff0c;也算是勉强做完吧&#xff0c;做的很仓促&#xff0c;没多检查就交了&#xff0c;方波不会&#xff0c;A板有个指示灯没做&#xff0c;其他应该都还凑…

师彼长技以助己(3)逻辑思维

师彼长技以助己&#xff08;3&#xff09;逻辑思维 前言 上一篇文章进行了工程思维和产品思维的测试&#xff0c;并介绍了几个比较重要的产品思维模型。接下来本篇介绍工程思维。&#xff08;注意产品思维并不代表产品经理思维&#xff0c;工程思维也并不代表工程师思维&…

学习小心意——python的构造方法和析构方法

构造方法和析构方法分别用于初始化对象的属性和释放类占有的资源 构造方法_init_() 语法格式如下&#xff1a; class 类名:def __init__(self, 参数1, 参数2, ...):# 初始化代码self.属性1 参数1self.属性2 参数2# ... 示例代码如下 class Student:def __init__(self):s…

期权的权利金怎么算的

期权权利金的计算涉及多个因素&#xff0c;包括敲定价格、到期时间以及整个期权合约的具体情况。期权的权利金具体的计算公式和因素可能因不同的期权合约和市场条件而有所不同&#xff0c;下文为大家介绍期权的权利金怎么算的 &#xff1f;本文来自&#xff1a;期权酱 一、期权…

实战:Zig 编写高性能 Web 服务(1)

1.1 认识 std.http std.http 是 Zig 标准库中用于处理 HTTP 相关操作的类库。以我学习新的编程语言的经历来看&#xff0c;编写web程序是最常见的技术场景&#xff0c;所以熟练掌握 HTTP server/client 服务相关的编程知识是比较重要的。 std.http 主要包含以下API: Client…

19、matlab信号预处理中的中值滤波(medfilt1()函数)和萨维茨基-戈雷滤波滤(sgolayfilt()函数)

1、中值滤波&#xff1a;medfilt1()函数 说明&#xff1a;一维中值滤波 1&#xff09;语法 语法1&#xff1a;y medfilt1(x) 将输入向量x应用3阶一维中值滤波器。 语法2&#xff1a;y medfilt1(x,n) 将一个n阶一维中值滤波器应用于x。 语法3&#xff1a;y medfilt1(x,n…

Django中使用ModelForm保存数据

相对来说&#xff0c;使用ModelForm保存数据在Django中算是比较简单的。主要原因是ModelForm是建立在Django的模型&#xff08;Model&#xff09;之上的&#xff0c;它可以自动根据模型的定义生成表单&#xff0c;包括字段和验证规则。这样可以大大简化开发人员处理表单数据的工…

低空经济发展报告

低空经济是指利用低空空间进行商业开发和经济活动的概念。随着航空技术的发展和无人机的普及&#xff0c;低空经济逐渐成为一个新兴的经济领域。 低空经济可以涵盖的领域非常广泛&#xff0c;包括但不限于物流配送、农业植保、城市交通、旅游观光等。利用无人机等飞行器进行物…

C\C++内存管理(未完结)

文章目录 一.C\C内存分布二.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三.C内存管理方式3.1.new/delete操作内置类型3.2.new和delete操作自定义类型 四.operator new与operator delete函数&#xff08;重要点进行讲解&#xff09;4.1. operator new与oper…

MySQL—约束—演示(基础)

一、引言 这篇博客主要演示&#xff1a;前面博客在约束概念与分类中讲到的&#xff1a;非空约束、唯一约束、检查约束、默认约束、主键约束、外键约束等等操作。 二、需求 根据下列需求&#xff0c;去完成表结构的创建。 注意&#xff1a;&#xff08;对于一个字段我们可以添…

语言模型解构——Tokenizer

1. 认识Tokenizer 1.1 为什么要有tokenizer&#xff1f; 计算机是无法理解人类语言的&#xff0c;它只会进行0和1的二进制计算。但是呢&#xff0c;大语言模型就是通过二进制计算&#xff0c;让你感觉计算机理解了人类语言。 举个例子&#xff1a;单1&#xff0c;双2&#x…