(1)高可用
Hbase支持对Hmaster的高可用配置,在哪个启动哪个就是Hmaster,挂了之后就会争抢资源zookeeper,争Hmaster
(2)预分区
每一个region维护着startRow与endRowKey,如果加入的数据符合某个region维护的rowKey范围,则该数据交给这个region维护。那么依照这个原则,我们可以将数据所要投放的分区提前大致的规划好,以提高Hbase性能(如果不规划,128溢出,256溢出,512溢出可能会数据倾斜)
1)手动设定预分区
create ‘test’,‘info’,‘partition1’,splits =>['1000','2000','3000','4000'] //切了4刀,分为5个区
2)生成16进制序列预分区
create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
3)按照文件中设置的规则预分区
新建文件splits.txt,上传,设置好分区:
1500100100|
1500100200|
然后执行:
create 'staff3','partition3',{SPLITS_FILE => '/usr/local/data/splits.txt'}
4)使用JavaAPI创建预分区
分区键的设计:(startrow、endrow,分区的切分位置)//10个分区,分students.txt数据 1500100100| //都加上一个 |,因为 | 的ASCII值最大,可以快速确定在哪个区,便于数据的判断存储 1500100200| ... 1500100900| row key的设计: 000_ //都加上一个_,由于_的ASCII值最小 001_ 152_ 298_
(3)row key 设计—先设计分区
一条数据的唯一标识就是rowkey,那么这条数据存储于哪个分区,取决于rowkey处于哪个一个预分区的区间内,设计rowkey的主要目的 ,就是让数据均匀的分布于所有的region中,在一定程度上防止数据倾斜 (生产环境row key 为70-100位)
① 数据获取方式:get,scan全表扫描,scan加条件扫描
② 设计原则:
1)散列性:由于row key是有序的,相似的数据都在一起,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。 2)唯一性:唯一的row key 3)长度性:rowkey是一个二进制码流,可以是任意字符串,最大长度 64kb ,实际应用中一般为10-100bytes,以 byte[] 形式保存,一般设计成定长,越短越好,长的话占用内存,只row key就需要占用大量的资源,影响HFile存储效率
③热点问题
Hbase中的行是按照rowkey的字典顺序排序的,这种设计优化了scan操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于scan。然而这样的rowkey设计是热点的源头。 热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region
为了避免写热点,设计rowkey使得不同行在同一个region,但是在更多数据情况下,数据应该被写入集群的多个region,而不是一个。
下面是一些常见的避免热点的方法以及它们的优缺点:
④row key设计:
生成随机数、hash、散列值,考虑散列的同时,还需要考虑集中性(得到a,d数据。那么中间b,c也会得到)
1)加盐:在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点。
2)哈希:哈希和加盐类似,row key–>hash(随机数)+row key,一个 数根据某种hash算法计算+原row key
3)反转:将row key反转,这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。
4)时间戳反转:主要是拿一个大数字减去时间戳作为row key,可以使最新的数据在上面,这样在scan
storefile的时候,可以优先火区最新的数据 ⑤其他一些建议
尽量减少rowkey和列的大小,当具体的值在系统间传输时,它的rowkey,列簇、列名,时间戳也会一起传输。如果你的rowkey、列簇名、列名很大,甚至可以和具体的值相比较,那么将会造成大量的冗余,不利于数据的储存与传输
列族尽可能越短越好,最好是一个字符 列名也尽可能越短越好,冗长的列名虽然可读性好,但是更短的列名存储在Hbase中会更好
(4)内存优化
Hbase操作过程中需要大量的内存开销,毕竟Table是可以缓存在内存中的,一般会分配整个可用内存的70%给Hbase的Java堆。但是不建议分配非常大的堆内存,因为GC过程持续太久会导致RegionServer处于长期不可用状态,一般16~48G内存就可以了,如果因为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死。
(5)基础优化
1)允许在HDFS的文件中追加内容
hdfs-site.xml、hbase-site.xml
属性:dfs.support.append解释:开启HDFS追加同步,可以优秀的配合Hbase的数据同步和持久化。默认值为true。
2)优化DataNode允许的最大文件打开数
hdfs-site.xml
属性:dfs.datanode.max.transfer.threads解释:Hbase一般都会同一时间操作大量的文件,根据集群的数量和规模以及数据动作,设置为4096或者更高。默认值:4096
3)优化延迟高的数据操作的等待时间
hdfs-site.xml
属性:dfs.image.transfer.timeout解释:如果对于某一次数据操作来讲,延迟非常高,socket需要等待更长的时间,建议把该值设置为更大的值(默认60000毫秒),以确保socket不会被timeout掉。
4)优化数据的写入效率
mapred-site.xml 属性:mapreduce.map.output.compress
//开启压缩mapreduce.map.output.compress.codec解释:开启这两个数据可以大大提高文件的写入效率,减少写入时间。第一个属性值修改为true,第二个属性值修改为:org.apache.hadoop.io.compress.GzipCodec或者其他压缩方式。
5)设置RPC监听数量
hbase-site.xml
属性:hbase.regionserver.handler.count解释:默认值为30,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。
6)优化HStore文件大小
hbase-site.xml
属性:hbase.hregion.max.filesize解释:默认值10737418240(10GB),如果需要运行Hbase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个Hfile。
7)优化hbase客户端缓存
hbase-site.xml
属性:hbase.client.write.buffer解释:用于指定Hbase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的。
8)指定scan.next扫描Hbase所获取的行数
hbase-site.xml
属性:hbase.client.scanner.caching解释:用于指定scan.next方法获取的默认行数,值越大,消耗内存越大。
9)flush、compact、split机制
当MemStore达到阈值,将Memstore中的数据Flush进Storefile;compact机制则是把flush出来的小文件合并成大的Storefile文件。split则是当Region达到阈值,会把过大的Region一分为二。
涉及属性: 即:128M就是Memstore的默认阈值
hbase.hregion.memstore.flush.size:134217728
即:这个参数的作用是当单个HRegion内所有的Memstore大小总和超过指定值时,flush该HRegion的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模型来异步处理的。那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存陡增,最坏的情况是触发OOM。
hbase.regionserver.global.memstore.upperLimit:0.4hbase.regionserver.global.memstore.lowerLimit:0.38
即:当MemStore使用内存总量达到hbase.regionserver.global.memstore.upperLimit指定值时,将会有多个MemStores
flush到文件中,MemStore flush 顺序是按照大小降序执行的,直到刷新到MemStore使用内存略小于lowerLimit



