介绍
Google BigTable
的开源实现- 分布式
NoSQL
数据库 - 列存储
- 基于
HDFS
和Zookeeper
适用场景
NoSQL = Not Only SQL
- 适用
- 存储格式: 半结构化数据, 结构化数据存储,
Key-Value
存储 - 数据版本: 固定集合(多版本) , 定时删除(
TTL
) - 更新: 列族结构经常调整
- 写
Pattern
: 重写轻读
- 存储格式: 半结构化数据, 结构化数据存储,
- 不适用 -
SQL
擅长的NoSQL
都不擅长- 事务
- 复杂查询
Operator
:Join, Union, Group By
- 索引支持:
- 读
Pattern
: 高并发随机读
特点
- 生产环境检验
- 理论与实践: 理论(
Google BigTable
) 经过生产环境检验 - 社区: 社区成熟, 丰富工具支持
- 理论与实践: 理论(
- 高效
- 读写
Pattern
: 将随机读写转化为顺序读写, 适应高并发写入 - 数据存储格式: 列存储节省空间
- 数据倾斜: 数据均衡效果好
- 读写
- 分布式特性
CAP
:一致性, 可用性, 分区容忍性- 扩展性: 利用
HDFS
线性扩展 - 高可用: 利用
HDFS
和Zookeeper
架构
Zookeeper
:- HMaster HA (机制类似 Hadoop)
- 节点状态监控
- 储存元数据
HMaster
:- client 的
DDL
操作 - 管理集群的负载均衡, 调整
HRegion
分布
- client 的
Region Server
:- client 的
DML
操作 HRegion
管理- 向
ZK
汇报节点状态 - 数据路由、读写和持久化
- client 的
HRegion
:管理表数据,包含Store
- 表有几个列簇就有几个Store
Store
:表数据MemStore
:一个列簇数据在内存中存储有且仅有一个,超过阈值落盘成StoreFile
StoreaFile
:一个列簇数据在磁盘中存储,看数据量容量可能会有多个;也叫做HFile
存储在HDFS
上的文件
数据模型
HBase
中的数据如下展示
一条数据的构成
RowKey
:每条数据的主键,不能重复,设计表结构时需要重点考虑,字典排序Column Family
:列簇简称CF
,包含一或多列,存储时依据列簇数将表分割成多个Store
Column
:列名Version
:时间戳类型为 LongValue
:以 (rowkey + column Family + column) 为key 的值
在设计表时, CF 个数最好不超过3个
一条数据的结构清楚了,下面来看看一张表的数据模型
逻辑视图
依据 Region
划分, rowkey
按字典排序划分为不同 Region,相当于是分表。上图row1-row4 划到 region 1;row5-row6 划到region 2;row7-row8 划到 region 3。当某个region 的数据不断增大超过阈值则会被再次分割(HMaster 负责)。
物理视图
依据列簇(CF) 划分表数据的物理存储,上图左右两侧各表示一个列簇(不同颜色是不同region),同个region下相同的列簇就会存储在一块( Store
)。
多版本
HBase
中有多版本的概念即同 rowkey
下的某列存在多个多个值,上图中 row1-SkuSum 值。在说明多版本之前先说一个机制:HBase 里的修改并不是直接覆盖,而是新增一条数据,只是 TimeStamp
不同,此时存在两条数;类似的删除数据也不是立即删除而是对该数据打上 delete
标签。由于这个机制的存在,数据自然存在多版本(TimeStamp)。在读取数据时(若没有指定版本),会读取所有数据然后选取最新数据返回。由此可见 ,HBase
是重写轻读:只管写,但读取时缺要做判断。
update、delete 的数据在大合并才真正执行,但生产中应避免打合并,GC 有可能会导致HBase 请求卡顿。
实战
有理论基础后,我们操作 HBase 来验证下上面的知识。
hbase shell
进行交互界面,
ctrl+back
可以在交互界面删除help
列出所有命令帮助help 'cmd'
列出对应 cmd 的帮助
创建表
# 先创建命名空间,类似库的概念
hbase(main):068:0> create_namespace 'rz'
0 row(s) in 0.1020 seconds
# 在 rz 下创建表 orderinfo,表有两个列簇 SKU ORDER
# create 'ns1:t1', 'f1'
hbase(main):069:0> create 'rz:orderinfo','SKU','ORDER'
0 row(s) in 2.4890 seconds
=> Hbase::Table - rz:orderinfo
hbase(main):001:0> describe 'rz:orderinfo'
Table rz:orderinfo is ENABLED # table 使能
rz:orderinfo # 表名
COLUMN FAMILIES DESCRIPTION # ORDER 列簇信息 VERSIONS 默认为1,只能获取1个版本
{NAME => 'ORDER', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'N
ONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0
'} # SKU 列簇信息
{NAME => 'SKU', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NON
E', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
2 row(s) in 0.3260 seconds
添加数据
# put 'ns1:t1', 'r1', 'c1', 'value'
hbase(main):001:0> put 'rz:orderinfo','row1','SKU:SKUName','apple'
0 row(s) in 0.3390 seconds
hbase(main):002:0> put 'rz:orderinfo','row2','SKU:SKUName','banana'
0 row(s) in 0.0170 seconds
hbase(main):003:0> put 'rz:orderinfo','row3','SKU:SKUName','orange'
0 row(s) in 0.0160 seconds
查看数据
hbase(main):004:0> scan 'rz:orderinfo'
ROW COLUMN+CELL
row1 column=SKU:SKUName, timestamp=1574696800783, value=apple
row2 column=SKU:SKUName, timestamp=1574696805573, value=banana
row3 column=SKU:SKUName, timestamp=1574696810623, value=orange
3 row(s) in 0.0750 seconds
# 单条数据
hbase(main):005:0> get 'rz:orderinfo','row3'
COLUMN CELL
SKU:SKUName timestamp=1574696810623, value=orange
1 row(s) in 0.0320 seconds
多版本
# 每个数据获取2个版本
hbase(main):015:0> scan 'rz:orderinfo', {RAW => true, VERSIONS => 2}
ROW COLUMN+CELL
row1 column=SKU:SKUName, timestamp=1574696800783, value=apple
# 存在两个版本,时间戳不一样
row2 column=SKU:SKUName, timestamp=1574697023615, value=banana02 row2 column=SKU:SKUName, timestamp=1574696805573, value=banana row3 column=SKU:SKUName, timestamp=1574696810623, value=orange
3 row(s) in 0.0130 seconds
# get 多版本需要列簇支持多版本,但默认创建表是不支持
# VERSIONS => '3' 最多存储三个版本
hbase(main):027:0> alter 'rz:orderinfo',{NAME => 'SKU', VERSIONS => '3'}
Updating all regions with the new schema...
0/1 regions updated.
1/1 regions updated.
Done.
0 row(s) in 3.0100 seconds
hbase(main):028:0> describe 'rz:orderinfo'
Table rz:orderinfo is ENABLED rz:orderinfo
COLUMN FAMILIES DESCRIPTION {NAME => 'ORDER', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'N
ONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0
'} # VERSIONS => '3' 已修改
{NAME => 'SKU', BLOOMFILTER => 'ROW', VERSIONS => '3', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NON
E', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
2 row(s) in 0.0280 seconds
hbase(main):031:0> put 'rz:orderinfo','row2','SKU:SKUName','banana03'
0 row(s) in 0.0130 seconds
hbase(main):032:0> get 'rz:orderinfo','row2',{COLUMN=>'SKU:SKUName',VERSIONS=>4}
COLUMN CELL
SKU:SKUName timestamp=1574698344934, value=banana03 SKU:SKUName timestamp=1574697023615, value=banana02
2 row(s) in 0.0100 seconds
删除
# 删除数据
hbase(main):033:0> delete 'rz:orderinfo','row3'
0 row(s) in 0.0330 seconds
hbase(main):034:0> scan 'rz:orderinfo', {RAW => true, VERSIONS => 2}
ROW COLUMN+CELL
row1 column=SKU:SKUName, timestamp=1574696800783, value=apple row2 column=SKU:SKUName, timestamp=1574698344934, value=banana03 row2 column=SKU:SKUName, timestamp=1574697023615, value=banana02
# 已被标识删除
row3 column=ORDER:, timestamp=1574698545510, type=DeleteFamily row3 column=SKU:, timestamp=1574698545510, type=DeleteFamily row3 column=SKU:SKUName, timestamp=1574696810623, value=orange
3 row(s) in 0.0170 seconds
# 删除表
hbase(main):035:0> drop 'rz:orderinfo'
ERROR: Table rz:orderinfo is enabled. Disable it first.
# 提示先 disbale 表
hbase(main):036:0> disable 'rz:orderinfo'
0 row(s) in 2.2710 seconds
hbase(main):038:0> describe 'rz:orderinfo'
Table rz:orderinfo is DISABLED #
rz:orderinfo
...
hbase(main):039:0> drop 'rz:orderinfo'
0 row(s) in 1.2550 seconds