hbase如何存储
① hbase 的数据存储及Region变化(flush compaction spilt)和性能调优
1. 对表做预分区处理(即在建表时指定Region数量和拆分边界);
2.配置hbase.hregion.max.filesize为50GB
以fileServer为例,在使用默认的split策略-- 的情况下,16个预分区Region, 则单个Resion容量达到 min(32,50),即32GB时分裂。
3.修改Linux最大文件句柄数
因为hbase是以文件的形式存储数据,最大文件句柄数影响着hbase的并发量。
用root权限修改/etc/security/limits.conf文件,增加以下内容(前面的*不能忽略):
* soft nproc 10240
* hard nproc 10240
* soft nofile 10240
* hard nofile 10240
编辑/etc/pam.d/common-session,加入一行
session required pam_limits.so
编辑/etc/profile,加入
ulimit -SHn 51200
重新登陆,生效
4.HRegionServer挂掉异常和解决:
is not online on......
常规解决方案:
删除zk中hbase的缓存
重启hbase
使用上述解决方案后本次异常依旧存在,并且HMaster和HRegionServer都不断的自动挂掉。
HMaster报错:
解决方案:
新增配置(看情况决定使用不使用,建议在HMaster不能启动时排除错误使用)(让启动hbase时只让HMaster去进行日志split,缺点是恢复数据时候速度慢):
<property>
<name>hbase.master.distributed.log.splitting</name>
<value>false</value>
</property>
删除WAL文件(会丢数据):
6. RPC请求的最大线程数
hbase.regionserver.handler.count 默认是10,在服务器测试时建议设置到50(经测试在单个Region Server时无用,单个RegionServer 最多在6个线程put时保持稳定)
7.日志分割(hbase出错后恢复数据)
MemStore中大量更新丢失时,对数据进行恢复时会做日志分割
hbase.regionserver.hlog.splitlog.writer.threads 日志分割的线程数, 默认为3 ,建议设定为10
8.Region Server频繁掉线
出现Hbase Region Server频繁掉线的情况,表现为在多线程put的情况下,忽然Hbase Region Server掉线
猜测是GC或者split过程中没有及时和ZK通信,导致与ZK连接时间超时,zk返回dead region到master,当Hbase Region恢复正常后,找不到wal,产生如下报错。
zookeeper.session.timeout :默认值是3分钟
但是 hbase regionserver和zookeeper的timeout不是单方面决定的,是取决于hbase的zookeeper.session.timeout和zookeeper的MaxSessionTimeout中的最小值
配置hbase:
zookeeper.session.timeout
600000
配置zookeeper:
tickTime=30000
9.内存及GC优化
在测试的过程中依旧出现Hbase Region Server掉线的情况,报错如下
2021-02-0318:49:14,091INFO[sync.0]wal.FSHLog: Slow sync cost:1955ms, current pipeline: []
2021-02-0318:49:14,091WARN[regionserver/botsc/192.168.0.107:16020.append-pool5-t1]wal.MetricsWAL: regionserver/botsc/192.168.0.107:16020.append-pool5-t1 took1953ms appending an edit to wal; len~=109
2021-02-0318:49:14,106ERROR[sync.3]wal.FSHLog:Errorsyncing, request close of WAL
java.io .IOException:io.grpc.StatusRuntimeException: CANCELLED: Failed to stream message
at seaweed.hdfs.SeaweedOutputStream.(SeaweedOutputStream.java:78)
at seaweed.hdfs.SeaweedOutputStream.(SeaweedOutputStream.java:263)
at seaweed.hdfs.SeaweedOutputStream.flushInternalAsync(SeaweedOutputStream.java:243)
at seaweed.hdfs.SeaweedOutputStream.flush(SeaweedOutputStream.java:129)
at java.io .FilterOutputStream.flush(FilterOutputStream.java:140)
at java.io .DataOutputStream.flush(DataOutputStream.java:123)
at org.apache.hadoop.hbase.regionserver.wal.ProtobufLogWriter.sync(ProtobufLogWriter.java:170)
at org.apache.hadoop.hbase.regionserver.wal.FSHLog$SyncRunner.run(FSHLog.java:1286)
at java.lang.Thread.run(Thread.java:748)
修改hbase的配置文件hbase-env.sh,GC优化如下:
export HBASE_HEAPSIZE=21384
export master_heapsize=8292
export regionserver_heapsize=21384
export HBASE_OPTS="$HBASE_OPTS -XX:+UseConcMarkSweepGC -XX:=60 -XX:+UseParNewGC -XX:ParallelGCThreads=6"
export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS $HBASE_JMX_BASE -Xmx8g -Xms8g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:=70"
export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS $HBASE_JMX_BASE -Xmx20g -Xms20g -Xmn1g -XX:+UseParNewGC
-XX:+UseConcMarkSweepGC -XX:=70"
② hbase与关系型数据库的存储方式有哪些不同
HBase与传统关系数据库的区别主要体现在以下几个方面:1.数据类型。关系数据库采用关系模型,具有丰富的数据类型和储存方式。HBase则采用了更加简单的数据模型,它把数据储存为未经解释的字符串,用户可以把不同格式的结构化数据和非结构化数据都序列化成字符串保存到HBase中,用户需要自己编写程序把字符串解析成不同的数据类型。 2.数据操作。关系数据库中包含了丰富的操作,如插入、删除、更新、查询等,其中会涉及复杂的多表连接,通常是借助多个表之间的主外键关联来实现的。HBase操作则不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等,因为HBase在设计上就避免了复杂的表与表之。
列存储不同于传统的关系型数据库,其数据在表中是按行存储的,列方式所带来的重要好处之一就是,由于查询中的选择规则是通过列来定义的,因此整个数据库是自动索引化的。
按列存储每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量,一个字段的数据聚集存储,那就更容易为这种聚集存储设计更好的压缩/解压算法。
传统的(Oracle)行存储和(Hbase)列存储的区别。
主要体现在以下几个方面:1.数据类型。关系数据库采用关系模型,具有丰富的数据类型和储存方式。HBase则采用了更加简单的数据模型,它把数据储存为未经解释的字符串,用户可以把不同格式的结构化数据和非结构化数据都序列化成字符串保存到HBase中,用户需要自己编写程序把字符串解析成不同的数据类型。 2.数据操作。关系数据库中包含了丰富的操作,如插入、删除、更新、查询等,其中会涉及复杂的多表连接,通常是借助多个表之间的主外键关联来实现的。HBase操作则不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等,因为HBase在设计上就避免了复杂的表与表之间的关系,通常只采用单表的主键查询。
③ hbase 如何存储数据
HBASE中的表示按column family来存储的
建立一个有3个column family的表
create 't1', {NAME => 'f1', VERSIONS => 1}, {NAME => 'f2', VERSIONS => 1}, {NAME => 'f3', VERSIONS => 1}
定义表的时候只需要指定column family的名字,列名在put的时候动态指定
插入数据
下面插入没有指定column的名字
put 't1', 'r1', 'f1', 'v1'
put 't1', 'r2', 'f2', 'v2'
put 't1', 'r3', 'f3', 'v3'
下面插入指定column的名字
put 't1', 'r4', 'f1:c1', 'v1'
put 't1', 'r5', 'f2:c2', 'v2'
put 't1', 'r6', 'f3:c3', 'v3'
hbase(main):245:0> scan 't1'
ROW COLUMN+CELL
r1 column=f1:, timestamp=1335407967324, value=v1
r2 column=f2:, timestamp=1335408004559, value=v2
r4 column=f1:c1, timestamp=1335408640777, value=v1
r5 column=f2:c1, timestamp=1335408640822, value=v2
r6 column=f1:c6, timestamp=1335412392258, value=v3
r6 column=f2:c1, timestamp=1335412384739, value=v3
r6 column=f2:c2, timestamp=1335412374797, value=v3
插入多列的数据
put 't1', 'r7', 'f1:c4', 'v9'
put 't1', 'r7', 'f2:c3', 'v9'
put 't1', 'r7', 'f3:c2', 'v9'
手工把memstore写到Hfile中
flush 't1'
删除所有CF3的数据
deleteall 't1','r7'
flush 't1'
每次flash都会建一个新的hfile
$ ../bin/hadoop dfs -lsr /hbase/t1
数据时直接存到CF目录下的,每个CF目录下有3到4个Hfile
f1
f1/
f1/321c683f48dd91e058179486587e
f1/
f2
f2/
f2/
f2/
f3
f3/
f3/
f3/
f3/
f3都数据虽然都被删除了,由于没有合并文件都存在
手工合并hfile
hbase(main):244:0> compact 't1'
0 row(s) in 0.0550 seconds
$ ../bin/hadoop dfs -lsr /hbase/t1
f1
f1/
f2
f2/
/f3
f1和f2下就只有一个hfile,f3下面没有hfile因为数据都被删除了
一次只能put一个column
一次只能delete一个column
删除整行,用deleteall
deleteall 't1', 'r1'
了解更多开源相关,去LUPA社区看看吧。