高清思维导图已同步Git:https://github.com/SoWhat1412/xmindfile,关注公众号sowhat1412获取海量资源
2. HBase安装
HBase = Hadoop database
1. Zookeeper正常部署
首先保证Zookeeper集群的正常部署,并启动之:
[atguigu@hadoop102 zookeeper-3.4.10]$ bin/zkServer.sh start
[atguigu@hadoop103 zookeeper-3.4.10]$ bin/zkServer.sh start
[atguigu@hadoop104 zookeeper-3.4.10]$ bin/zkServer.sh start
2 Hadoop正常部署
Hadoop集群的正常部署并启动:
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh
[atguigu@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh
3. HBase的解压
解压HBase到指定目录:
[atguigu@hadoop102 software]$ tar -zxvf hbase-1.3.1-bin.tar.gz -C /opt/module
4. HBase的配置文件
修改HBase对应的配置文件。
- hbase-env.sh修改内容:
export JAVA_HOME=/opt/module/jdk1.8.0_144
export HBASE_MANAGES_ZK=false # 不用HBase自带的zk关联机制
- hbase-site.xml修改内容:
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop102:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 0.98后的新变动,之前版本没有.port,默认端口为60000 -->
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/opt/module/zookeeper-3.4.10/zkData</value>
</property>
</configuration>
- 修改regionservers跟HDFS中slaves类似:
hadoop102
hadoop103
hadoop104
- 软连接hadoop配置文件到hbase:
[atguigu@hadoop102 module]$ ln -s /opt/module/hadoop-2.7.2/etc/hadoop/core-site.xml
/opt/module/hbase/conf/core-site.xml
[atguigu@hadoop102 module]$ ln -s /opt/module/hadoop-2.7.2/etc/hadoop/hdfs-site.xml
/opt/module/hbase/conf/hdfs-site.xml
5. HBase远程发送到其他集群
[atguigu@hadoop102 module]$ xsync hbase/
6 HBase服务的启动
1.启动方式1
[atguigu@hadoop102 hbase]$ bin/hbase-daemon.sh start master
[atguigu@hadoop102 hbase]$ bin/hbase-daemon.sh start regionserver
提示
:如果集群之间的节点时间不同步,会导致regionserver无法启动,抛出ClockOutOfSyncException异常。
修复提示:
a、同步时间服务
请参看帮助文档:《Hadoop入门》
b、属性:hbase.master.maxclockskew设置更大的值
<property>
<name>hbase.master.maxclockskew</name>
<value>180000</value>
<description>Time difference of regionserver from master</description>
</property>
2.启动方式2推荐
[atguigu@hadoop102 hbase]$ bin/start-hbase.sh
对应的停止服务:
[atguigu@hadoop102 hbase]$ bin/stop-hbase.sh
7. 查看HBase页面
启动成功后,可以通过“host:port”的方式来访问HBase管理页面,例如:
http://hadoop102:16010
3. HBase Shell 操作
Shell基本操作 指南
命名 | 描述 | 语法 |
help ‘命名名’ | 查看命令的使用描述 | help ‘命令名’ |
whoami | 我是谁 | whoami |
version | 返回hbase版本信息 | version |
status | 返回hbase集群的状态信息 | status |
table_help | 查看如何操作表 | table_help |
create | 创建表 | create ‘表名’, ‘列族名1’, ‘列族名2’, ‘列族名N’ |
alter | 修改列族 | 添加一个列族:alter ‘表名’, ‘列族名’ ;删除列族:alter ‘表名’, {NAME=> ‘列族名’, METHOD=> ‘delete’} |
describe | 显示表相关的详细信息 | describe ‘表名’ |
list | 列出hbase中存在的所有表 | list |
exists | 测试表是否存在 | exists ‘表名’ |
put | 添加或修改的表的值 | put ‘表名’, ‘行键’, ‘列族名’, ‘列值’ ; put ‘表名’, ‘行键’, ‘列族名:列名’, ‘列值’ |
scan | 通过对表的扫描来获取对用的值 | scan ‘表名’ ; 扫描某个列族: scan ‘表名’, {COLUMN=>‘列族名’} 扫描某个列族的某个列: scan ‘表名’, {COLUMN=>‘列族名:列名’} ; 查询同一个列族的多个列: scan ‘表名’, {COLUMNS => [ ‘列族名1:列名1’, ‘列族名1:列名2’, …]} |
get | 获取行或单元(cell)的值 | get ‘表名’, ‘行键’ get ‘表名’, ‘行键’, ‘列族名’ |
count | 统计表中行的数量 | count ‘表名’ |
incr | 增加指定表行或列的值 | incr ‘表名’, ‘行键’, ‘列族:列名’, 步长值 |
get_counter | 获取计数器 | get_counter ‘表名’, ‘行键’, ‘列族:列名’ |
delete | 删除指定对象的值(可以为表,行,列对应的值,另外也可以指定时间戳的值) | 删除列族的某个列: delete ‘表名’, ‘行键’, ‘列族名:列名’ |
deleteall | 删除指定行的所有元素值 | deleteall ‘表名’, ‘行键’ |
truncate | 重新创建指定表 | truncate ‘表名’ |
enable | 使表有效 | enable ‘表名’ |
is_enabled | 是否启用 | is_enabled ‘表名’ |
disable | 使表无效 | disable ‘表名’ |
is_disabled | 是否无效 | is_disabled ‘表名’ |
drop | 删除表 | drop的表必须是disable的 disable |
shutdown | 关闭hbase集群(与exit不同) | |
tools | 列出hbase所支持的工具 | |
exit | 退出hbase shell |
基本操作
- 进入HBase客户端命令行
[atguigu@hadoop102 hbase]$ bin/hbase shell
- 查看帮助命令
hbase(main):092:0> help 'delete'
Put a delete cell value at specified table/row/column and optionally
timestamp coordinates. Deletes must match the deleted cell's
coordinates exactly. When scanning, a delete cell suppresses older
versions. To delete a cell from 't1' at row 'r1' under column 'c1'
marked with the time 'ts1', do:
hbase> delete 'ns1:t1', 'r1', 'c1', ts1
hbase> delete 't1', 'r1', 'c1', ts1
hbase> delete 't1', 'r1', 'c1', ts1, {VISIBILITY=>'PRIVATE|SECRET'}
The same command can also be run on a table reference. Suppose you had a reference
t to table 't1', the corresponding command would be:
hbase> t.delete 'r1', 'c1', ts1
hbase> t.delete 'r1', 'c1', ts1, {VISIBILITY=>'PRIVATE|SECRET'}
hbase(main):093:0>
hbase(main):001:0> help
COMMAND GROUPS:
Group name: general
Commands: processlist, status, table_help, version, whoami
Group name: ddl 数据库的增删改查操作
Commands: alter, alter_async, alter_status, clone_table_schema, create, describe, disable, disable_all, drop, drop_all, enable, enable_all, exists, get_table, is_disabled, is_enabled, list, list_regions, locate_region, show_filters
Group name: namespace 类似与mysql中的database操作
Commands: alter_namespace, create_namespace, describe_namespace, drop_namespace, list_namespace, list_namespace_tables
Group name: dml 数据库跟表格的一些操作
Commands: append, count, delete, deleteall, get, get_counter, get_splits, incr, put, scan, truncate, truncate_preserve
.......
For more on the HBase Shell, see http://hbase.apache.org/book.html
- 查看当前数据库中有哪些表
hbase(main):002:0> list
TABLE
sowhat
mygraph
user
表的操作
- 创建表
注意:创建表时只需要指定列族名称,不需要指定列名。
# 语法
create '表名', {NAME => '列族名1'}, {NAME => '列族名2'}, {NAME => '列族名3'}
# 此种方式是上上面的简写方式,使用上面方式可以为列族指定更多的属性,如VERSIONS、TTL、BLOCKCACHE、CONFIGURATION等属性
create '表名', '列族名1', '列族名2', '列族名3'
create '表名', {NAME => '列族名1', VERSIONS => 版本号, TTL => 过期时间, BLOCKCACHE => true}
# 示例
create 'tbl_user', 'info', 'detail'
create 't1', {NAME => 'f1', VERSIONS => 1, TTL => 2592000, BLOCKCACHE => true}
create 'sowhat','info'
- 插入数据到表
put 表名,序列号key,列族:列名,字段值
hbase(main):003:0> put 'sowhat','1001','info:sex','male'
hbase(main):004:0> put 'sowhat','1001','info:age','18'
hbase(main):005:0> put 'sowhat','1002','info:name','Janna'
hbase(main):006:0> put 'sowhat','1002','info:sex','female'
hbase(main):007:0> put 'sowhat','1002','info:age','20'
- 扫描查看表数据
hbase(main):008:0> scan 'sowhat'
hbase(main):012:0> scan 'sowhat'
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592444447588, value=18
1001 column=info:sex, timestamp=1592444439067, value=male
1002 column=info:age, timestamp=1592444470614, value=20
1002 column=info:name, timestamp=1592444462987, value=Janna
1002 column=info:sex, timestamp=1592444466848, value=female
---
hbase(main):009:0> scan 'sowhat',{STARTROW => '1001', STOPROW => '1001'} 指定范围 左闭右开[start,end)这样的格式,必须大写!
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592444447588, value=18
1001 column=info:sex, timestamp=1592444439067, value=male
---
hbase(main):010:0> scan 'sowhat',{STARTROW => '1001'}
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592444447588, value=18
1001 column=info:sex, timestamp=1592444439067, value=male
1002 column=info:age, timestamp=1592444470614, value=20
1002 column=info:name, timestamp=1592444462987, value=Janna
1002 column=info:sex, timestamp=1592444466848, value=female
---
- 查看表结构
hbase(main):011:0> describe 'sowhat' desc 'sowhat' 也可以
Table sowhat is ENABLED
sowhat
COLUMN FAMILIES DESCRIPTION
{NAME => 'info', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'fal
se', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_
MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}
- 更新指定字段的数据
hbase(main):012:0> put 'sowhat','1001','info:name','Nick'
hbase(main):013:0> put 'sowhat','1001','info:age','100'
hbase(main):013:0> scan 'sowhat'
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592445694183, value=100
1001 column=info:name, timestamp=1592445681869, value=Nick
1001 column=info:sex, timestamp=1592444439067, value=male
1002 column=info:age, timestamp=1592444470614, value=20
1002 column=info:name, timestamp=1592444462987, value=Janna
1002 column=info:sex, timestamp=1592444466848, value=female
2 row(s)
- 查看“指定行”或“指定列族:列”的数据
hbase(main):025:0> get 'sowhat','1001'
COLUMN CELL
info:age timestamp=1592445694183, value=100
info:name timestamp=1592445681869, value=Nick
info:sex timestamp=1592444439067, value=male
1 row(s)
Took 0.0215 seconds
hbase(main):026:0> get 'sowhat','1001','info:name'
COLUMN CELL
info:name timestamp=1592445681869, value=Nick
1 row(s)
Took 0.0146 seconds
- 统计表数据行数
hbase(main):027:0> count 'sowhat'
2 row(s)
Took 0.0558 seconds
=> 2
- 删除数据
删除某rowkey的全部数据:
hbase(main):016:0> deleteall 'sowhat','1001'
删除某rowkey的某一列数据:
hbase(main):017:0> delete 'sowhat','1002','info:sex'
- 清空表数据
hbase(main):032:0> truncate 'sowhat'
Truncating 'sowhat' table (it may take a while):
Disabling table...
Truncating table...
Took 2.0702 seconds
hbase(main):033:0> scan 'sowhat'
ROW COLUMN+CELL
0 row(s)
提示:清空表的操作顺序为先disable
,然后再truncate,在HBase 2.2版本上操作时候没显示必须disable。
10. 删除表
首先需要先让该表为disable
状态:
hbase(main):019:0> disable 'sowhat'
然后才能drop这个表:
hbase(main):020:0> drop 'sowhat'
提示:如果直接drop表,会报错:ERROR: Table sowhat is enabled. Disable it first
.
11. 变更表信息
默认情况下,列族只存储一个版本的数据
,如果需要存储多个版本的数据,则需要修改列族的属性。修改后可通过desc命令查看。
put 'sowhat','1001','info:name','Nick'
put 'sowhat','1001','info:name','Nick1'
put 'sowhat','1001','info:name','Nick2'
put 'sowhat','1001','info:name','Nick3'
put 'sowhat','1001','info:name','Nick4'
hbase(main):022:0> alter 'sowhat',{NAME=>'info',VERSIONS=>3}
hbase(main):022:0> get 'sowhat','1001',{COLUMN=>'info:name',VERSIONS=>3}
COLUMN CELL
info:name timestamp=1592446266614, value=Nick4
info:name timestamp=1592446264202, value=Nick3
info:name timestamp=1592446262438, value=Nick2
1 row(s)
put 'sowhat','1001','info:name', 'Nick0', 1592446266615 put数据的时候指定时间
- alter 增删列族
# 语法
alter '表名', '列族名'
# 示例
alter 'tbl_user', 'address'
# 语法
alter '表名', {NAME=> '列族名', METHOD=> 'delete'}
# 示例
alter 'tbl_user', {NAME=> 'address', METHOD=> 'delete'}
# 修改f1列族的版本为5
alter 't1', NAME => 'f1', VERSIONS => 5
# 修改多个列族,修改f2为内存,版本号为5
alter 't1', 'f1', {NAME => 'f2', IN_MEMORY => true}, {NAME => 'f3', VERSIONS => 5}
# 也可以修改table-scope属性,例如MAX_FILESIZE, READONLY,MEMSTORE_FLUSHSIZE, DEFERRED_LOG_FLUSH等。
# 例如,修改region的最大大小为128MB:
alter 't1', MAX_FILESIZE => '134217728'
- 查看所有数据类型
scan 'sowhat',{RAW=>TRUE,VERSIONS=>10}
4. HBase数据结构
1. RowKey
跟nosql数据库一样RowKey
就是用来检索记录的主键,访问HBase 表中的行只有如下三种方式。
- 通过单个RowKey访问
get 'sowhat','1001'
- 通过RowKey的range访问
scan 'sowhat',{STARTROW => '1001', STOPROW => '1003'}
- 全表扫描
RowKey行键 (RowKey)可以是任意字符串(最大长度是64KB,实际应用中长度一般为 10-100bytes),在HBASE内部,RowKey保存为字节数组。存储时,数据按照RowKey的字典序(byte order)排序存储。设计RowKey时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。(位置相关性)
scan 'sowhat'
2. Column Family
列族:HBASE表中的每个列,都归属于某个列族
。列族是表的schema的一部分(而列不是),必须在使用表之前定义。列名都以列族作为前缀。例如 courses:history
,courses:math
都属于courses 这个列族。
3. Cell
由{rowkey, column Family:columu, version} 唯一确定的单元。cell中的数据是没有类型
的,全部是字节码
形式存贮。
关键字:无类型
、字节码
。
4. Time Stamp
HBase 中通过rowkey
和columns
确定的为一个存贮单元称为cell。每个 cell都保存 着同一份数据的多个版本
。版本通过时间戳
来索引。时间戳的类型是 64位整型。时间戳可以由HBase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒 的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版 本冲突,就必须自己生成具有唯一性的时间戳。每个 cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
为了避免数据存在过多版本造成的的管理 (包括存贮和索引)负担,HBase提供 了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段 时间内的版本(比如最近七天)。用户可以针对每个列族进行设置。
5. 命名空间
命名空间的结构:
- Table:表,所有的表都是命名空间的成员,即表必属于某个命名空间,如果没有指定,则在default默认的命名空间中。
- RegionServer group:一个命名空间包含了默认的RegionServer Group。
- Permission:权限,命名空间能够让我们来定义访问控制列表ACL(Access Control List)。例如,创建表,读取表,删除,更新等等操作。
- Quota:限额,可以强制一个命名空间可包含的region的数量。
4. HBase 原理
HBase是一个写比读快的 框架
写原理
比如执行给table1里面rowkey=11050的数据插入数据则看如下操作。
- 先跟ZK 询问
/hbase/meta-region-server
里面的 meta数据存储位置。 - 客户1找到的位置到对应的机器上查找regions数据存储概要。一般一行就是存储该数据的
表明,rowkey开始位置,rowkey结束位置
,根据合适的范围查找到对应的 regionServer,然后再根据数据信息 找到对应的region,然后数据写到WAL中,再到MemCache,再到HFile(KV格式存储
)。
写流程:
- Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server。
- 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey,查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以及 meta 表的位置信息
缓存
在客户端的 meta cache,方便下次访问。 - 与目标 Region Server 进行通讯;
- 将数据顺序写入(追加)到 WAL
- 将数据写入对应的 MemStore,数据会在 MemStore 进行排序
- 向客户端发送 ack;
- 等达到 MemStore 的刷写时机后,将数据刷写到 HFile
- 在web页面查看的时候会随机的给每一个region生成一个随机编号。
PS ZK数据查找跟更新的 流程:
zk ==> meta ==> regionserver ==> RegionIP
HBase0.9版本前 meta数据又要被切分 -root-
zk ==> -root- ==> meta ==> regionserver ==> RegionIP
读原理
- Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server。
- 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey, 查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以 及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问。
- 与目标 Region Server 进行通讯;
- 分别在 Block Cache(读缓存),MemStore 和 Store File(HFile)中查询目标数据,并将 查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(time stamp)或者不 同的类型(Put/Delete)。
- 将从文件HFile中查询到的数据块(Block,HFile 数据存储单元,默认大小为 64KB)缓存到 Block Cache。
- 将合并后的最终结果,然后返回时间最新的数据返回给客户端。
- hbase中两种缓存机制 memstore和blockcache详解
重点
:不要理解为读数据先从MemStore中读取,然后读BlockCache中,如果没有再从HFile中读取,然后将数据写入到BlockCache中。因为如果下面这样的操作怎么办?
- 创建表,写入数据,刷新到磁盘中,
create stu ‘info’
put ‘stu’,‘info:name’,‘sowhat’
flush
bin/hbase org.apache.hadoop.hbase.io.hfile.HFile -a -b -e -k -p -f 列族文件在HDFS中路径, 目的确保数据刷新到本地了
- 插入一个比
sowhat
时间早的数据,
put ‘stu’,‘info:name’,‘sowhat1412’,早点的时间戳。
- 直接scan查询可以看到 结果还是
sowhat
,说明数据每次都是把磁盘数据读取了放到BlockCache中,然后跟MemCache数据合并!比较时间戳,返回时间戳最新的数据。也就是每次都要涉及到磁盘到读取。
结论:HBase 把磁盘跟内存数据一起读,然后把磁盘数据放到BlockCache中
,BlockCache是磁盘数据的缓存。读比写慢的工具。
Scanner
查询流程的形象图
Flush
一般情况下一个Region中有多个列族,而整个region中有列族跟store是一 一对应的。对于用户来说数据写到MemStore
中就算完成了,但是对于底层代码来说只有数据刷到硬盘中才算彻底搞定了!因为数据是要写入到WAL(Hlog)中再写入到MemStore
中的,所以刷写的时候,也有WAL个数的配置。配置文件
- WAL 个数 .
当 WAL 文件的数量超过 hbase.regionserver.max.logs,region 会按照时间顺序依次进行刷写,直到 WAL 文件数量减小到 hbase.regionserver.max.log 以下(
该属性名已经废弃
,
现无需手动设置,最大值为 32)。比如我的堆内存0.4= 1T,那么我的Hlog文件可能也是大小1T,这样如果一个HLog文件大小为512M 则可能出现 10242个,所以需合理配置。
- hbase.
regionserver
.global.memstore.size
regionServer的
全局memstore
的大小,超过该大小会触发flush到磁盘的操作,默认是堆大小的40%,而且regionserver级别的 , flush会阻塞客户端读写。
- hbase.
regionserver
.global.memstore.size.lower.limit
可以理解为一个安全的设置,有时候集群的“写负载”非常高,写入量一直超过flush的量,这时,我们就希望memstore不要超过一定的安全设置。 在这种情况下,写操作就要被阻塞一直到memstore恢复到一个“可管理”的大小, 这个大小就是默认值是堆大小 * 0.4 * 0.95,也就是当regionserver级别的flush操作发送后,会阻塞客户端写,一直阻塞到整个regionserver级别的memstore的大小为 堆大小 * 0.4 *0.95为止
- hbase.
regionserver
.optionalcacheflushinterval
内存中的文件在自动刷新之前能够存活的最长时间,默认是1h,表示最后一条数据后的1小时。
- hbase.hregion.memstore.flush.size
单个region里memstore的缓存大小,超过那么整个HRegion就会flush,
默认128M
StoreFile Compaction
由于 memstore 每次刷写都会生成一个新的 HFile,且同一个字段的不同版本(timestamp) 和不同类型(Put/Delete)有可能会分布在不同的 HFile 中,因此查询时需要遍历所有的 HFile。 为了减少 HFile 的个数,以及清理掉过期和删除的数据,会进行 StoreFile Compaction。
Compaction 分为两种,分别是 Minor Compaction
和 Major Compaction
。Minor Compaction会将临近的若干个较小的 HFile 合并成一个较大的 HFile,但不会
清理过期和删除的数据。 Major Compaction 会将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉过期和删除的数据。
数据删除时间
create ‘stu4’,‘info’
put ‘stu4’,‘1001’,‘info:name’,‘xianyi’
put ‘stu4’,‘1001’,‘info:name’,‘yuyang’
flush ‘stu4’ 刷新一个文件
put ‘stu4’,‘1001’,‘info:name’,‘xianyu’ 显示
flush ‘stu4’ 增加个文件
put ‘stu4’,‘1002’,‘info:name’,‘xianyi’ 显示
flush ‘stu4’
compact 三个以上的文件调用小文件合并会自动触发大文件合并,
scan ‘stu4’,{RAW=>TRUE,VERSIONS=>10}
只会显示两个文件
数据删除只有在flush 跟上面的大合并(Major compaction
)的时候执行。
- flush 可以删除在同一个内存中的数据,flush只会操作当前内存。并且写入本地后 内存数据会丢失。
- Major compaction 大合并时候会自动把所以数据排序删除旧数据。
put ‘stu4’,‘1001’,‘info:name’,‘zhangsan’
put ‘stu4’,‘1001’,‘info:name’,‘lisi’
put ‘stu4’,‘1001’,‘info:name’,‘wangwu’
flush ‘stu4’
put ‘stu4’,‘1001’,‘info:name’,‘zhaoliu’ 此时查看可以看到zhaoliu
delete ‘stu4’,‘1001’,‘info:name’ 目的
是删除1001的 name属性!
scan ‘stu4’,{ROW=>TRUE,VERSIONS=>10} 会显示zhaoliu 但显示已经删除了。此时flush ‘stu4’ 再查看数据,会发现Type=DeleteColumn还存在。没有删除掉,因为这个DeleteColumn还要用来删除flush 磁盘里的zhangsan,lisi,wangwu这三个数据。 而删除的标准就是调用大合并的时候!
Region Split
默认情况下,每个 Table 起初只有一个 Region,随着数据的不断写Region 会自动进 行拆分。刚拆分时,两个子 Region 都位于当前的 Region Server,但出于负载均衡的考虑, HMaster 有可能会将某个 Region 转移给其他的 Region Server。
Region Split 时机:
- 当 1 个 region 中的某个 Store 下所有 StoreFile 的总大小超过 hbase.hregion.max.filesize(默认10G), 该 Region 就会进行拆分(0.94 版本
之前
)。 - 当 1 个 region 中的某个 Store 下所有 StoreFile 的总大小超过 Min(R^2 * “hbase.hregion.memstore.flush.size”,hbase.hregion.max.filesize"),该 Region 就会进行拆分,其 中 R 为当前 Region Server 中属于该 Table 的个数(0.94 版本之后)。hbase.hregion.memstore.flush.size=128M
第一次的阈值是128,
切分后结果64 , 64
第二次阈值512M
64,512 ⇒ 54 + 256 + 256
最后会形成一个 64M…10G 的这样Region队列,会产生数据倾斜
问题。
解决方法
:提前做好Region组的规划,0-1k,1k-2k,2k-3k这样的。
官方不建议用多个列族,比如有CF1,CF2,CF3,但是 CF1数据很多而CF2跟CF3数据很少,那么当触发了region切分的时候,会把CF2跟CF3分成若干小份,不利于系统维护。
参考
HBase配置文件