曾为梦想仗剑走天涯,如今这个那个得优化。
还想围观群众吃个瓜?赶紧关注我博涨文化!
预分区和RowKey设计是搭配使用的。
预分区的分区键是什么样的,RowKey就得是什么样的,他俩得配合使用才行。比如,都是十六进制。
如果不使用预分区,那么等数据量大了就会进行自动分裂。
自动分裂有什么坏处呢?
每一个Region维护着startKey和endKey,如果加入的数据符合某个Region维护的RowKey范围,则该数据交给这个Region维护。那么依照这个原则,我们可以将数据所要投放的分区提前大致的规划好,以提高HBase性能。
hbase(main):092:0> create 'emp1', 'info', SPLITS => ['1000','2000','3000','4000']
Created table emp1
Took 1.3647 seconds
=> Hbase::Table - emp1
这里,设置了5个分区:(-∞, 1000), [1000, 2000), [2000, 3000), [3000, 4000), [4000, +∞)
hbase(main):094:0> create 'emp2', 'info', {NUMREGIONS => 5, SPLITALGO => 'HexStringSplit'}
Created table emp2
Took 1.3252 seconds
=> Hbase::Table - emp2
因为十六进制最大为FFFFFFFF,那么均分5分,就是这个样子了呢。
创建splits.txt文件:
aaaa
bbbb
cccc
dddd
然后执行:
hbase(main):098:0> create 'emp3', 'info', SPLITS_FILE => 'splits.txt'
public static void preRegion(String nameSpace, String tableName, String... families) throws IOException {
if(families.length <= 0) {
System.out.println("至少有一个列族");
return;
}
Admin admin = connection.getAdmin();
try {
if(admin.tableExists(TableName.valueOf(nameSpace, tableName))) {
System.out.println(nameSpace + ":" + tableName + "已存在");
return;
}
TableDescriptorBuilder builder = TableDescriptorBuilder
.newBuilder(TableName.valueOf(nameSpace, tableName));
for(String family: families) {
ColumnFamilyDescriptorBuilder cfBuilder = ColumnFamilyDescriptorBuilder
.newBuilder(Bytes.toBytes(family));
builder.setColumnFamily(cfBuilder.build());
}
TableDescriptor descriptor = builder.build();
byte[][] splitKeys = new byte[4][];
for(int i = 0; i < 4; i ++) {
splitKeys[i] = Bytes.toBytes(String.valueOf((i + 1) * 1000));
}
admin.createTable(descriptor, splitKeys);
} catch (Exception e) {
e.printStackTrace();
} finally {
admin.close();
}
}
一条数据的唯一标识就是rowkey,那么这条数据存储于哪个分区,取决于rowkey处于哪个预分区的区间内。设计rowkey的主要目的,就是要让数据均匀的分布于所有的Region中,在一定程度上防止数据倾斜。
比如:
原本rowKey为1001的,SHA1后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7
原本rowKey为3001的,SHA1后变成:49042c54de64a1e9bf0b33e00245660ef92dc7bd
原本rowKey为5001的,SHA1后变成:7b61dec07e02c188790670af43e717f0f46e8913
20170524000001转成10000042507102
20170524000002转成20000042507102
20170524000001_a12e
20170524000001_93i7
网站首页访问记录实时存入hbase,统计网站首页每分钟的访问次数
注意:rowkey唯一性 + 读数据的时候数据需要在一块那么写的时候就写在一块
思路:满足业务 -> user_id, timestamp:
rowKey:"yyyyMMddHHmm".hashCode()%5_yyyyMMddHHmmssSSSS_user_id
regionKey:
-∞, 1
1, 2
2, 3
3, 4
4, +∞
hbase-site.xml
属性:zookeeper.session.timeout
解释:默认值为90000毫秒(90s)。当某个RegionServer挂掉,90s之后Master才能觉察到。可适当减小此值,以加快Master响应,可调整至60000毫秒。
hbase-site.xml
属性:hbase.regionserver.handler.count
解释:默认值为30,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。
hbase-site.xml
属性:hbase.hregion.majorcompaction
解释:默认值为604800000秒(7天),Major Compaction的周期,若关闭自动Major Compaction,可将其设为0
hbase-site.xml
属性:hbase.hregion.max.filesize
解释:默认值10737418240(10GB),如果需要运行HBase的MR任务,可以减小此值。因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个HFile。
hbase-site.xml
属性:hbase.client.write.buffer
解释:默认值2097152bytes(2M)用于指定HBase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的。
hbase-site.xml
属性:hbase.client.scanner.caching
解释:用于指定scan.next方法获取的默认行数,值越大,消耗内存越大。
hbase-site.xml
属性:hfile.block.cache.size
解释:默认0.4,读请求比较多的情况下,可适当调大
hbase-site.xml
属性:hbase.regionserver.global.memstore.size
解释:默认0.4,写请求较多的情况下,可适当调大
Log-Structured Merge Tree 存储引擎
lsm tree