rowkey划分splitkey为9eaz 该表中有几个region

rowkey划分splitkey为9eaz 该表中有几个region,第1张

1取样,先随机生成一定数量的rowkey,将取样数据按升序排序放到一个集合里

2根据预分区的region个数,对整个集合平均分割,即是相关的splitKeys

3HBaseAdmincreateTable(HTableDescriptor tableDescriptor,byte[][] splitkeys)可以指定预分区的splitKey,即是指定region间的rowkey临界值

原因是antd在样式中将该组件设置为 float: right

由以上我们得知内联样式的优先级最高,因此我们采用内联样式的写法进行css定义,在pagination属性中定义style属性:

record 为每一条数据, index 索引

一.工具开发背景:

业务上目前主要计算逻辑的数据源是hbase,但是我们没有工具对hbase的数据进行单条更改造数据来验证逻辑,之前的做法是把hbase的数据都导出来,改完再重新载入回去,或使用hbase shell接口进行更改(有一个限制就是hbase shell get 出来的数据汉字是看不出来的),效率低,也不便于自动化的回归。测试非常的被动。

于是在师姐的建议下期望有 *** 作hbase数据的工具来提高我们的效率,及大数据的验证。

二.工具简介:

工具使用java编写的jar包,在ihbasesh进行简单数据处理对jar包进行调用。主要功能为数据的增删改查,支持gbk,utf8编码。通过配置一个xml格式的配置文件 (也可以不配置)。

三.使用方法:

1propertiessh:在里面配置hbase,hadoop等环境变量,里面目前默认是我们测试集群的配置作为参考。注意一些基础的jar包一定要有。

2config:xml格式的配置hbase导出数据的信息。在海量导出数据或根据rowkey到处数据的时候使用。

3ihbasesh工具的使用接口。

四.简要使用介绍:

*** 作均在bin目录下。

一.查询数据功能

1 /ihbase –t table_name -rowkey rowkey -enc encoding -s

-enc encoding这个的目的是指定以什么编码读出hbase数据,目前支持utf8,gbk。如果不加该参数则默认以utf读出。

查看表名为table_name,rowkey为rowkey的数据。

2 /ihbase –t 表名 –k CF:COLUMN=value –k CF:COLUMN=value –w column -s

/ihbasesh –t "test" –k "a:name=jkfs" –k "a:id=111" -w "nid" -s

查询满足a:name=jkfs且a:id=111的记录,若加上-w参数,则只显示 -w 传进去的列。若不加-w 显示所有列。

(这个命令一般很少用,因为使用这个=的filer需要扫hbase全表,因为这种方式很少使用,所以暂时没考虑如何优化)

二.删除数据功能

1 /ihbase –t table_name –rowkey rowkey –delete

根据rowkey进行删除。

2 /ihbase –t table_name –k CF:COLUMN=value –k CF:COLUMN=value –delete

/ihbase –t test –k "a:id=jaks" -k "name=a:jkasj" -delete

删除满足a:id=jaks且a:name=jkasf的数据(目前支持and进行删除,不支持or,原理同该方式的查询)

三.添加数据功能

/ihbase –t table_name –rowkey rowkey –v CF:COLUMN=value –v CF:COLUMN=value -a

/ihbasesh –t "a:test" -rowkey "111" –v "a:name=jkfs" –v "id=111" -a

添加rowkey为111的数据,后面key,value可以任意指定。如果rowkey已经存在,则报错不进行添加。

添加数据要求必须指定rowkey

四.修改数据功能

1 /ihbase –t table_name –rowkey rowkey –v key=value -v key=value -u

/ihbasesh -t "test" -rowkey "1111" –v "name=jkasjd" -u

根据rowkey进行修改一条记录的列数据

2 /ihbase –t table_name –k key=value –k CF:COLUMN=value -v CF:COLUMN=value -u

/ihbasesh –t test –k "a:name=jksdj" –k "mge=kjdk" –v "a:name=huanyu" -u

根据非rowkey进行修改,-k 提供修改的条件,-u 提供要修改的列的数数据。(原理同查询,scan全表)

五.导出hbase指定列的数据(所有数据)

/ihbase -f config 此处有一个限制:就是导出表的配置文件必须放在bin的目录下。如果不喜欢这样也可以修改ihbase脚本进行调整。

config为配置导出表信息的xml配置

<xml version="10">

<configuration>

<table>

<in_enc>gbk</in_enc>

<out_enc>utf8</out_enc>

<tablename>test</tablename>

<field_separator>\001</field_separator>

<record_separator>\002</record_separator>

<column>

bmw_shops:title

</column>

<outpath>/test/huanyu/hbase</outpath>

</table>

</configuration>

in_enc:hbase中的编码,以解析hbase中数据使用的编码。

out_enc:输出到hdfs路径上的编码。

tablename: *** 作的表名。

field_separator:如果导出多个字段则作为多个字段间的分隔符。

record_separator:导出数据的行分隔符。(除了\n的字符,因为默认会分行)。

column:导出的字段。如果不存在该字段则导出''。

outpath:导出数据的路径。(其实应在代码中把这个路径先删除的,但是怕用户忘记修改路径误删除,所以没有这么做)

有多少个region 启动多少个map。

六.导出hbase指定行的指定列的数据

/ihbase -f config -rf rfile

config里面配置导出的列,字符编码表名等信息。

rfile 配置导出哪些rowkey的数据。(一个rowkey一行)

类似上面。

七.帮助信息

/ihbase –h

显示帮助信息

hbase客户端通过rpc调用将put、delete数据请求提交到对应的regionserver,regionserver对请求进行处理,并将数据最终写入hfile中,进行持久化保存。

hbase为了保证随机读取的性能,所以hfile里面的rowkey是有序的。当客户端的请求在到达regionserver之后,为了保证写入rowkey的有序性,所以不能将数据立刻写入到hfile中,而是将每个变更 *** 作保存在内存中,也就是metastore中。metastore能够很方便的支持 *** 作的随机插入,并保证所有的 *** 作在内存中是有序的。当metastore达到一定的量之后,会将metastore里面的数据flush到hfile中,这样能充分利用hadoop写入大文件的性能优势,提高写入性能。

由于metastore是存放在内存中,如果regionserver因为某种原因死了,会导致内存中数据丢失。所有为了保证数据不丢失,hbase将更新 *** 作在写入metastore之前会写入到一个write ahead log(WAL)中。WAL文件是追加、顺序写入的,WAL每个regionserver只有一个,同一个regionserver上所有region写入同一个的WAL文件。这样当某个regionserver失败时,可以通过WAL文件,将所有的 *** 作顺序重新加载到metastore中。

2流程

整个写入顺序图流程如下:

1

客户端查找对应region

客户端根据要 *** 作rowkey,查找rowkey对应的region。查找region的过程为通过zk获取到hbase:meta表所在region。通过查找hbase:meta可以找到要更新的表每个region的startkey、endkey以及所处机器。由于hbase的rowkey有序分布在region上,所以通过每个region的startkey、endkey可以确定当前要 *** 作rowkey的region信息。

由于通过zk、hbase:meta查找region信息比较耗时,所以客户端会缓存表的region信息。在请求region失效时,会重新加载表的region信息。

regionserver写入WAL文件

在将 *** 作写入metastore之前,会将 *** 作先写入到WAL文件中。WAL文件的是顺序保存 *** 作记录的,所有每次新 *** 作直接。

我们来仔细分析一下这个结构,每条Row记录了一个Region的信息。

首先是RowKey,RowKey由三部分组成:TableName, StartKey 和 TimeStamp。RowKey存储的内容我们又称之为Region的Name。哦,还记得吗?我们在前面的文章中提到的,用来存放Region的文件夹的名字是RegionName的Hash值,因为RegionName可能包含某些非法字符。现在你应该知道为什么RegionName会包含非法字符了吧,因为StartKey是被允许包含任何值的。将组成RowKey的三个部分用逗号连接就构成了整个RowKey,这里TimeStamp使用十进制的数字字符串来表示的。这里有一个RowKey的例子:

Table1,RK10000,12345678

然后是表中最主要的Family:info,info里面包含三个Column:regioninfo, server, serverstartcode。其中regioninfo就是Region的详细信息,包括StartKey, EndKey 以及每个Family的信息等等。server存储的就是管理这个Region的RegionServer的地址。

所以当Region被拆分、合并或者重新分配的时候,都需要来修改这张表的内容。

到目前为止我们已经学习了必须的背景知识,下面我们要正式开始介绍Client端寻找RegionServer的整个过程。我打算用一个假想的例子来学习这个过程,因此我先构建了假想的-ROOT-表和META表。

我们先来看META表,假设HBase中只有两张用户表:Table1和Table2,Table1非常大,被划分成了很多Region,因此在META表中有很多条Row用来记录这些Region。而Table2很小,只是被划分成了两个Region,因此在META中只有两条Row用来记录。这个表的内容看上去是这个样子的:

META

现在假设我们要从Table2里面插寻一条RowKey是RK10000的数据。那么我们应该遵循以下步骤:

1 从META表里面查询哪个Region包含这条数据。

2 获取管理这个Region的RegionServer地址。

3 连接这个RegionServer, 查到这条数据。

好,我们先来第一步。问题是META也是一张普通的表,我们需要先知道哪个RegionServer管理了META表,怎么办?有一个方法,我们把管理META表的RegionServer的地址放到ZooKeeper上面不久行了,这样大家都知道了谁在管理META。

貌似问题解决了,但对于这个例子我们遇到了一个新问题。因为Table1实在太大了,它的Region实在太多了,META为了存储这些Region信息,花费了大量的空间,自己也需要划分成多个Region。这就意味着可能有多个RegionServer在管理META。怎么办?在ZooKeeper里面存储所有管理META的RegionServer地址让Client自己去遍历?HBase并不是这么做的。

HBase的做法是用另外一个表来记录META的Region信息,就和META记录用户表的Region信息一模一样。这个表就是-ROOT-表。这也解释了为什么-ROOT-和META拥有相同的表结构,因为他们的原理是一模一样的。

Kylin作为一个OLAP引擎,需要Cube模型支撑,在我们的工作过程中,在和用户以及相关的开发人员、测试、产品等介绍Kylin的过程中,他们总是会对Cube的模型有一些疑惑,作为经常接触这个概念的我来说这是再明了不过的了,而他们还是会在我讲解多次之后表示还在云里雾里,所以就希望通过一篇关于Cube和Kylin创建Cube的过程来聊一下Cube是什么,以及Kylin的一些高级设置。

一个Cube(多维立方体)其实就是一个多维数组,例如定义一个三维数组int array[M][N][K],每一个维度分别有M、N和K个成员,同样对于一个Cube而言,也可以有三个维度,假设分别为time、location和product,每一个维度的distinct值(称为维度的cardinality)分别是M、N和K个,而数组中的每一个值则是每一个维度取一个值对应的聚合结果,例如array[0][1][2],它就相当于time取第一个值(假设为2016-01-01),location取第二个值(假设为HangZhou)、product取第三个值(假设为Food)对应的一个聚合结果,假设这里的聚合函数为COUNT(1),那么求得的值相当于执行了SELECT COUNT(1) from table where time = ‘2016-01-01’ and location = ‘HangZhou’ and product = ‘Food’,这样当我们有多个聚合函数呢,那么就相当于数组中的每一个元素是一个包含多个值的结构体:

#

如上图,每一个data cell就保存了一个类似的结构体,因此只要能够计算和保存这样的一个多维数组,我们所有的查询就都可以直接定位到多维数组中的一个或者一批值,然后进行过滤得到结果。

但是一个多维数组和Cube模型还是有一些区别,例如在多维数组中我们必须在每一维指定一个值(下标)才能对应得到一个确定的值,但是在Cube中,虽然定义了三个维度,但是我可以只指定两个维度,甚至一个维度都不指定而进行查询,例如执行SELECT COUNT(1) from table where time = ‘2016-01-01’ and location = ‘HangZhou’,这就相当于求数组中array[0][1]的值,但这个返回的是一个数组,而SQL返回的是一个值,因此需要将这个数组中的每一个data cell取出来再进行聚合运算(例如计数、相加等)得到的值才是真正的结果。好了,到这里可以看出有两种方案计算上面的SQL:

       那么在这个二维数组上指定time和location就能够对应一个data cell值了。由于可以通过方案1进行再聚合计算,所以理论上如果保存了所有维度的组合(假设N个维度,那么就是一个N为的数组),那么所有的N-1、N-2、…、0维的任何值都是可以通过这个N维数组进行再聚合计算出来的,但是这势必就影响查询的性能。所以这其实就是时间和空间的一个博弈,那么在实践中到底应该如何进行权衡呢,答案是:看需求!也就是建立哪些数组(N个维度,第K层有C(N,K)个K维数组)就要看你真正要执行的查询有哪些了,对经常在一块进行组合查询的维度简历一个数组是再适合不过的了,例如time和location这两个维度老是在一个SQL中出现,那么建立一个这样的二维数组是需要的,而product和location这两个不会在一个SQL中出现,那么这个二维数组就不需要预计算了。那么在Kylin里面是如何决定预计算哪些数组呢?

这里的一切就要从Kylin创建Cube开始说起,在Kylin中创建一个Cube需要以下几步:

1、设置Cube名、描述信息等

2、设置Cube依赖的表模型(星状模型,一个事实表和可选的多个维度表)

3、设置维度(维度有几种类型这里不再讨论,创建完之后就可以暂时性的忽略这几种不同的类型,都把它当做普通的维度就可以了)

4、设置度量(每一个度量包括列和聚合函数,列只能是事实表上的列)

5、设置filter条件(用于对表中的数据进行过滤)

6、设置增量更新的信息(设置增量列和起始时间,该列必须是时间格式列)

7、高级设置(设置维度组、RowKey等)

前面6步的设置比较浅显易懂,那么对于Cube的优化主要通过“高级设置”这一步实现的,这里设置的主要有以下几种:

1、设置Rowkey

2、设置维度组

3、设置Cube Size

在进入到设置RowKey的时候会看到每一个维度的设置(Derived维度看到的是外键列而不是Derived的列),每一个维度可以设置ID(通过拖拽可以改变每一个维度的ID)、Mandatory、Dictionary和Length。

#Mandatory维度

首先看一下Mandatory维度,需要设置为Mandatory的维度是哪些在大多数SQL中都会出现的维度,例如time这个维度,如果每次查询都需要带上它进行过滤或者group by,那么就可以把它设置为mandatory。

#维度顺序

其次,ID决定了这个维度在数组中执行查找时该维度对应的第一个维度,例如在上例中time的ID就是1,location对应的ID就是2,product对应的ID为3,这个顺序是非常重要的,一般情况我们会将mandatory维度放置在rowkey的最前面,而其它的维度需要将经常出现在过滤条件中的维度放置在靠前的位置,假设在上例的三维数组中,我们经常使用time进行过滤,但是我把time的ID设置为3(location的ID=1,product的ID=2),这时候如果从数组中查找time大于’2016-01-01’并且小于’2016-01-31’,这样的查询就需要从这样的最小的key=<min(location)、min(product)、‘2016-01-01’>扫描到最大的key=<max(location)、max(product)、‘2016-01-31’>,但是如果把time的ID设置为1,扫描的区间就会变成key=<‘2016-01-01’、min(location)、min(product)>到key=<‘2016-01-31’、max(location)、max(product)>,Kylin在实现时需要将Cube的数组存储在Hbase中,然后按照hbase中的rowkey进行扫描,假设min(location)=’BeiJing’、max(location)=’ZhengZhou’, min(product)=’aaaa’,max(product)=’zzzz’,这样在第一种情况下hbase中需要扫描的rowkey范围是[BeiJing-aaaa-2016-01-01, ZhengZhou-zzzz-2016-01-31],而第二种情况需要扫描的rowkey范围是[2016-01-01-BeiJing-aaaa, 2016-01-31-ZhengZhou-zzzz]可以看出第二种情况可以减少扫面的rowkey,查询的性能也就更好了。但是在kylin中并不会存储原始的成员值(例如HangZhou、2016-01-01这样的值),而是需要对它们进行编码,是否需要编码则有后面两个设置项决定。

#维度字典

Dictionary可以设置为true和false,设置为true表示需要为这个维度建立字典树,如果设置为false则表示不需要设置,而需要设置Length,而Length则意味着在实际存储到hbase的rowkey时使用该维度的前Length个字符作为它的值(剪切每一个成员值只保留前Length个字符),一般情况下是不建议设置Length的,而是设置Dcitionary为true,只有当cardinality比较大时并且只需要取前N个字节就可以表示这个维度时才建议设置Length=N,因为每一个维度的dictionary都会保存在内存中,如果字典树占用很大的内存会影响kylin的使用甚至导致OOM,对于dictionary的编码使用的是字典树,它的原理实际上是为每一个维度成员赋予一个整数的id,实际存储的时候存储的是这个id的二进制值(使用int最多占用4个字节),并且保证每一个id的顺序和维度成员的顺序相同的,例如aaa的id=1,aab的id=2,aac的id=3,这样在查询的时候就可以直接根据column>aaa转换成id>1,方便hbase coprocessor的处理。

#维度组

设置完了RowKey接下来要设置维度组,维度组的设置主要是为了让不出现在一个查询中的两个维度不计算cuboid(通过划分到两个不同的维度组中),这其实相当于把一个cube的树结构划分成多个不同的树,可以在不降低查询性能的情况下减少cuboid的计算量,目前在Kylin-1x版本中cuboid的算法有一点的问题,可以参考我对这个算法的改进那篇博文。

#Cube Size

最后设置CubeSize,该项的设置会对cuboid转换成hfile这一步的计算产生影响,并且影响hbase中表的分区大小,可选值为SMALL、MEDIUM和LARGE,在kylin-11版本之后可以在配置文件可以设置这三个配置的分区大小,默认情况下SMALL=10GB,MEDIUM=20GB,LARGE=100GB,在计算完全部的cuboid之后会统计所有cuboid文件中key和value的大小,然后根据这个大小和用户的CubeSize配置决定划分多少region,然后执行一个MR任务计算每一个region的hfile,由于kylin在创建hfile的时候都是通过预分区的方式(通过计算出每一个分区临界值的key),然后批量load到htable的,所以不会导致region的分裂和合并,所以我们还是建议将CubeSize设置为SMALL,并且配置中将small的配置设置为5GB,这样可以提高生成hfile这一步的速度(每一个region负责一个region,减小分区的大小会增加reducer的个数)。

好了,本文主要介绍了kylin中创建cube的过程,其中还主要介绍了cube模型的概念,最后详细介绍了kylin在创建cube中的高级设置的优化方案,如果有什么错误的地方,还希望多多指正。

以上就是关于rowkey划分splitkey为9eaz 该表中有几个region全部的内容,包括:rowkey划分splitkey为9eaz 该表中有几个region、antd之pagination分页居中和rowKey无理取闹、如何加快hbase读取数据的效率等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/9457532.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存