hbase 创建表结构示例·
create 'car_gb_binary',{NAME=>'carnet',COMPRESSION=>'snappy',BLOOMFILTER=>'ROW'},{NUMREGIONS=>100,SPLITALGO=>'HexStringSplit'}
解释:
BLOOMFILTER=布隆过滤器,默认为ROW,有三个选项NONE、ROW、ROWCOL
NUMREGIONS=>10:默认region数
SPLITALGO=>分裂规则,十六进制
VERSIONS=>版本号--如果没有必要,设置为1
COMPRESSION=>压缩方式,默认为NONE,有snappy、zip等
DFS_REPLICATION=>1 hdfs中备份数量为1--经测试,该配置有效。如果是在表已存在情况下,修改了表属性。只对后续的写入、split、merge等操作有效,之前的数据如果不操作的话,还是按照原来的备份数量
CONFIGURATION =>configuration中设置split策略,禁用自动split
create 'carnet:gb_binary',{NAME=>'a',COMPRESSION=>'snappy',BLOOMFILTER=>'ROW', VERSIONS=>1, DFS_REPLICATION => '1'},{NUMREGIONS=>10,SPLITALGO=>'HexStringSplit',CONFIGURATION => {'hbase.regionserver.region.split.policy'=>'org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy'}}
#alter 为修改表结构指令
alter 'carnet:gb_binary',{NAME=>'a',COMPRESSION=>'snappy',BLOOMFILTER=>'ROW',DFS_REPLICATION => '3'}
hbase性能调优
主要是针对于服务端的配置优化
地方大幅度发 | 默认值 | 建议值 | 说明 | 调优 | |
zookeeper.session.timeout | 3分钟 | 1分钟 | RegionServer与Zookeeper间的连接超时时间。当超时时间到后,ReigonServer会被Zookeeper从RS集群清单中移除,HMaster收到移除通知后,会对这台server负责的regions重新balance,让其他存活的RegionServer接管 | 设置成1分钟,减少hmaster感知时间 | |
hbase.regionserver.handler.count | 30 | 100 | rpc handler,handler太少无法处理高并发 | 增加这个值,提高rpc并发数 | |
hbase.hregion.max.filesize | 10G | 30G | region下hfile大小 | 经验值为20~30G,也不是越大越好,越大索引层次越深,对查询稍有影响,越小容易造成split,region个数太多 | |
hbase.hregion.memstore.flush.size | 128M | 128M/256M | memstore达到多大时flush到磁盘 | regionserver 分配16G内存时,分配128M,分配32G时,分配256M, 机器内存大时建议将memstore调整到256M , | |
hbase.regionserver.global.memstore.upperLimit | 0.4 | 0.45 | 单台regionserver上所有region的memstore内存达到regionserver内存乘以这个值后,会flush memstore到磁盘,生成hfile | 这个值根据实际情况调整,如果写多读少,可以调大这个值,注意hbase.regionserver.global.memstore.upperLimit + hfile.block.cache.size不能超过0.8,否则会有OOM风险 | |
hfile.block.cache.size | 0.4 | 0.35 | blockcache占用的百分比 | 这个值根据实际情况调整,如果读多写少,可以调大这个值,注意hbase.regionserver.global.memstore.upperLimit + hfile.block.cache.size不能超过0.8,否则会有OOM风险 | |
hbase.hstore.blockingStoreFiles | 10 | 1000 | 当一个region下hfile超过10个时,block住所有写请求直到compaction完成 | 设置一个较大值,减少block住写请求 | |
hbase.hregion.memstore.mslab.enabled | TRUE | TRUE | 减少内存碎片造成的full gc | ||
hbase.hregion.majorcompaction | 604800000 | 0 | major_compact触发周期 | 禁用majorcompaction,每天晚上定时通过contab执行compaction动作。 脚本,实施部门有。 | |
hbase.regionserver.regionSplitLimit | 2147483647 | 2147483647 | 超过这个值后region将会停止自动split | 分裂时会造成对性能上的抖动,需要消耗cpu和io,对性能要求很高可以关闭自动分裂,把值设为0,在集群负载不大的时候下手动或定时脚本去split。对性能要求不高自动split就可以 | |
hbase.client.scanner.caching | 1000 | 1000 | 每次scan rpc返回记录条数 | 查询返回的数据太大会造成客户端长时间等待,造成超时,每次rpc小批量返回即可 | |
hbase.regionserver.thread.compaction.large | 1 | 10 | large compaction线程个数 | major compact时需要把region下所有hfile合并成一个大hfile,需要把线程数设置大一些 | |
hbase.regionserver.thread.compaction.small | 1 | 5 | small compaction线程个数 | minor compact把几个小hfile合并成一个hfile,1个线程太少 | |
GC优化 | 4G | 机器内存充足,建议给32G | “-Xms16g -Xmx16g -Xmn1g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=15 -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/data1/hbase-logs/gc-$(hostname)-hbase.log | “-Xms16g -Xmx16g -Xmn1g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=15 -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/data1/hbase-logs/gc-$(hostname)-hbase.log | 配置方位: 在cdh hbase 配置界面==> 高级 ==》HBase RegionServer 的 Java 配置选项 |
建表 | 1. table要预分区,分区个数=表总大小(估算)/HFile大小 2. 设置压缩格式,推荐使用snappy压缩 3.开启row boolean filter 4.列族名、字段名尽量要短,列族比如用f |
hbase split触发规则
1、admin手动分裂
2、memory中数据flush至hfile之前,会去校验是否需要split。如果当前region中hfile的数量超过了hbase.hstore.blockingStoreFiles 设置的数量。如果超过,且没有等待超时,就会触发split。flush之后,还会再去校验一次,是否需要split
3、单个region存储大小超过hbase.hregion.max.filesize设定的文件大小,不再触发split
hbase merge触发规则
merge的触发由后台周期性检查,如果发现满足以下条件,则开启merge:
1、参与合并的文件个数 >= hbase.hstore.compaction.min (default is 3), 但最多不超过hbase.hstore.compaction.max(default is 10)
2、参与合并的文件需满足的条件:
文件大小 < hbase.hstore.compaction.max.size (default is Long.MAX_VALUE)
且,文件大小 < 所有创建日期比该文件大(新)的文件大小之和*1.2
文件大小 < hbase.hstore.compactoin.min.size(memstore flush size)
3、文件选择的优先级
优先考虑老文件。
hbase 批量迁移数据
1、hive插入数据至hbase
hive插入数据至hbase参数优化--数据量不大的情况可以使用,数据量大还是要采用bulkload方式
set hive.exec.dynamic.partition.mode=nonstrict;
#设置map并发数量
set mapreduce.job.running.map.limit=2;
#关闭hbase的WAL,有点事提高了写入速度,缺点是如果出现错误无法查找日志
set hive.hbase.wal.enabled=false;
#开启大量导入配置
set hive.hbase.bulk=true;
2、bulkload
#hbase中创建一张新表,用于存储迁移后的数据
create 'log_new',{NAME=>'a',COMPRESSION=>'snappy', BLOOMFILTER=>'ROW', VERSIONS=>1, DFS_REPLICATION => '1'},{NUMREGIONS=>24,SPLITALGO=>'HexStringSplit',CONFIGURATION => {'hbase.regionserver.region.split.policy'=>'org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy'}}
#删除临时表
hadoop fs -rm -r -skipTrash /tmp/hbase/car_log_new
#执行MR,使用bulkload方式,将hbase数据存储至临时文件
hadoop jar statistic-job-0.0.1.jar /tmp/me/2020-05-25 /user/me/data-report.result
#将临时文件用ulkLoad方法能够将数据快速的load到HBase log_new表中
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /tmp/hbase/log_new log_new
2、spark hbase context
该方式利用spark,全盘scan hbase 表,来达到获取数据并写入新的表。相比前两种方式,速度更快
引用的相关jar包
<!--版本号 -->
<hadoop.version>3.0.0</hadoop.version>
<hbase.version>2.0.0</hbase.version>
<spark.version>2.2.0</spark.version>
<!-- hbase-spark -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-spark</artifactId>
<version>2.1.0-cdh6.1.1</version>
<exclusions>
<exclusion>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
</exclusion>
<exclusion>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
</exclusion>
</exclusions>
</dependency>
package xxx.spark;
import lombok.SneakyThrows;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.spark.JavaHBaseContext;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;
import scala.Tuple2;
import scala.Tuple3;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
/**
* spark:迁移hbase表
* args[0] 迁移表
* args[1] 新表
*/
public class HbaseToHbase {
public static void main(String[] args) {
String tableName = args[0];
String targetTableName = args[1];
SparkConf sparkConf = new SparkConf().setAppName("hbase to hbase");//.setMaster("local");
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
//jsc.addJar("spark.jar");
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "hdp-master01.leapmotor.com,hdp-master02.leapmotor.com,hdp-node01.leapmotor.com");
conf.setInt("hbase.zookeeper.property.clientPort", 2181);
/*conf.addResource(new Path("/etc/hbase/conf/core-site.xml"));
conf.addResource(new Path("/etc/hbase/conf/hbase-site.xml"));*/
JavaHBaseContext hbaseContext = new JavaHBaseContext(jsc, conf);
Scan scan = new Scan();
scan.setCaching(1000);
JavaRDD<Tuple2<ImmutableBytesWritable, Result>> javaRdd = hbaseContext.hbaseRDD(TableName.valueOf(tableName), scan);
hbaseContext.foreachPartition(javaRdd, new VoidFunction<Tuple2<Iterator<Tuple2<ImmutableBytesWritable, Result>>, Connection>>() {
@Override
public void call(Tuple2<Iterator<Tuple2<ImmutableBytesWritable, Result>>, Connection> t) throws Exception {
Connection connection = t._2;
BufferedMutator m = connection.getBufferedMutator(TableName.valueOf(targetTableName));
Iterator<Tuple2<ImmutableBytesWritable, Result>> it = t._1;
int count = 0;
while (it.hasNext()) {
count++;
Tuple2<ImmutableBytesWritable, Result> data = it.next();
List<Cell> list = data._2.listCells();
Put put = new Put(data._2.getRow());
list.forEach(new Consumer<Cell>() {
@SneakyThrows
@Override
public void accept(Cell cell) {
put.add(cell);
}
});
m.mutate(put);
}
System.out.println(count);
m.flush();
m.close();
}
});
}
}
表重命名方式
disable 'carnet:gb_binary_2024'
snapshot 'carnet:gb_binary_2024', 'gb_binary_2024_snapshot'
clone_snapshot 'gb_binary_2024_snapshot', 'carnet:gb_binary_2023'
-- delete_snapshot 'gb_binary_2024_snapshot'
-- drop 'carnet:gb_binary_2024'
enable 'carnet:gb_binary_2023'
enable 'carnet:gb_binary_2024'