技术背景
起源于谷歌旧三篇论文中bigtable
设计目的
- 为了解决大数据环境中海量结构化数据的实时读写问题
- 为了弥补hadoop生态中没有实时存储的缺陷
设计思想
分布式
技术本质
概念:分布式列存储nosql数据库
解释:
列存储:底层数据文件存储格式是列式存储
nosql: 非关系型,可以存储结构化和半结构化数据
数据库: 符合数据库的特征
核心特性
大表: 为存储海量数据而生,亿级别的行和百万级别的列
分布式:
1.分布式内存: 为实现实时读写,将数据放在内存中
2.分布式外存: 内存中放置不了的数据,刷写到hdfs上多版本: 一个列簇允许设置版本数,即允许一个数值存储多个版本,通过"ns:tb cf:c ts"唯一缺点一条数据
nosql:
1.RDBMS: 关系型数据库,例如"mysql,oracle,postgresql,sqlserver"
2.nosql: 非关系型数据库,例如"hbase,redis,mongodb"随机实时读写
1.数据优先存储在内存中,命中率高数据
2.命中率中等的数据,存在缓存中
3.命中率低的数据,存在hdfs上依赖于hdfs: 将海量的数据存到hdfs上,即保证了数据了安全性,又保证了数据的持久化
不支持join操作,只支持行级事务,复杂join操作需要集成hive
只支持字节数组类型
稀疏: 对于空null的列,并不占用存储空间,因此表的设计可以非常稀疏
集群角色
物理架构
-
client
- 种类:
- bin/hbase shell: 不支持sql语句,可以使用help 'command',exit,
- java api:
- hue: hbase实现了ThriftServer服务端,用于提供hue客户端连接,thriftserver来实现整个过程的访问以及执行
- sql on hbase: 底层使用的mapreduce操作hbase
- 种类:
-
zookeeper
概念: hbase中的zk被称为真·主节点
-
职责:
- 辅助集群的主节点选取,实现HA机制
- 为集群的访问提供入口,存贮所有Region 的寻址入口
- 负责存储hbase中几乎所有的元数据,如节点信息,master的主备节点,regionserver的节点,表的状态
- 负责实现系统容错,若发现regionserver注册节点消失,即认为此regionserver故障,需要通知hmaster启动恢复程序
- 负责存储meta表的region[rootregion]所在的regionserver地址
- 负责flush,splitWAL的状态等
- 存储Hbase 的schema,包括有哪些table,每个table 有哪些column family
-
内容:
- 每一个节点都会在zookeeper上去注册
- zookeeper存储了meta表的region信息,客户端通过访问zookeeper才能请求集群
-
hdfs
- 职责: 存储hfile,wal
-
Hmaster
- 概念: 辅助主节点
- 职责:
- 负责管理所有从节点信息,
- 负责region在regionserver上的分配,实现regionserver的负载均衡,
- 负责region的数据迁移,例如分裂场景
- 负责meta表以及元数据的修改,meta表不等于元数据,可将meta表看做元数据的一部分,meta表只是存储region的信息,而元数据包括regionserver,region,表,namespace等信息
- 负责接收客户端的DDL请求,用于更改元数据,修改zookeeper中的存储
- 通过zookeeper监听每个regionserver的状态,如果regionserver故障,就会启动恢复regionserver的进程
- 发现失效的region server 并重新分配其上的region
- HDFS 上的垃圾文件回收
- 处理schema 更新请求
-
RegionServer
- 职责:
- 负责接收并处理所有客户端的数据的读写请求
- 负责管理该节点上所有的region,处理对这些region 的IO 请求
- 负责记录WAL
- 负责读缓存:memcache,占堆内存40%,并刷新缓存到HDFS
- 执行压缩
- 负责处理Region 分片
- 补充:
- regionserver就是从节点,有多台
- 一台regionserver中管理很多个不同的表分区【region】
- meta表中的数据也存在regionserver中
- 职责:
-
Hlog
- 概念:预写日志,类似于hdfs上的edits文件,也类似于mysql中的binlog文件
- 补充:
每个Region Server 维护一个Hlog,而不是每个Region 一个。这样不同region(来自不同table)的日志会混在一起,这样做的目的是不断追加单个文件相对于同时写多个文件而言,可以减少磁盘寻址次数,因此可以提高对table 的写性能。带来的麻烦是,如果一台region server 下线,为了恢复其上的region,需要将regionserver 上的log 进行拆分,然后分发到其它region server 上进行恢复,HLog文件就是一个普通的Hadoop Sequence File
Region
-
概念:
- regionserver中的数据存储单元,不是region级别的
-
补充:
- 一张表将数据按照rowkey的范围来划分到多个region中,以此来散列表的数据,
- 默认情况下创建的表只有一个region
- 同一张表的不同region的范围总和是从负无穷到正无穷
- 一个region只会被一台regionserver管理
- region是整个hbase中最小的负载均衡单元,是实现分布式的基本
- region的分配不均衡会导致数据倾斜及热点问题
- 用户读写时,会根据rowkey进行判断,从哪个分区读取,从哪个分区写入
- 每一个分区是一个目录
- store个数/2 = region个数
-
Store
意义: 设计列簇时将具有相同IO属性的列放在同一个列簇里,因为底层存储是一个列簇存储独占一个store;放在一个storefile中,可以提供快速的读写操作
概念:
-
内容:
- region是表的划分,store是列簇的划分,
- 机器内存*40%/128M=store个数
-
MemStore
功能:
-
补充:
- 属于Store中的内存存储区域
- 每个store中都有一个memstore,用于存储刚写入的数据,
- 写内存,占堆内存的40%,
-
StoreFile /HFile
功能:
解释:
1.memstore满足条件会进行flush,刷写出来的数据文件就是storefile,存储在hdfs上被称为hfile
2.一个store中会有多个storefile文件,但最终会优化合并成一个文件【二进制文件】
3.storefile是hfile的封装,也可认为是同一个文件,不同的称呼补充:
HFile分为六个部分:
1.Data Block 段–保存表中的数据,这部分可以被压缩
2.Meta Block 段(可选的)–保存用户自定义的kv 对,可以被压缩。
3.File Info 段–Hfile 的元信息,不被压缩,用户也可以在这一部分添加自己的元信息。
4.Data Block Index 段–Data Block 的索引。每条索引的key 是被索引的block的第一条记录的key。
5.Meta Block Index段(可选的)–Meta Block 的索引。
6.Trailer–这一段是定长的。保存了每一段的偏移量
逻辑存储
- NameSpace
名称空间,物理存在
默认创建时就已经存在两个名称空间default和hbase
属于表的一部分,用于区分表的存储,每个表必定有自己是名称空间,若不指定,默认属于default - Table
表,访问时通过namespace:table_name来访问这张表,不加默认访问是default下的表 - Rowkey
行键,通过rowkey可以唯一指定一行的数据(注意不是一条),在创建表时就已经存在,不需要再次创建
rowkey的设计,影响了底层region的节点数据分配,会造成热点问题,影响读写性能
rowkey是整个hbase中的唯一索引,在hbase中不支持自定义索引,处理rowkey之外,没有别的索引,查找数据时,要么通过rowkey进行查找,要么全表扫描,区别于mysql中可以自定义索引 - ColumnFamily
列簇,列的分组,一个列簇下有多个列,每个列必然属于某个列簇,可通过列簇指定这一个列簇中所有列的版本号
一般将具有相同io属性的字段放入同一个列簇,
创建表时必须指定至少一个列簇,
一张表一般不建议超过两个列簇,一般在一到两个列簇,超过两个之后,hbase的读写性能会降低 - Column
列,列标签,一个列簇下有多个列,一个列必属于某个列簇,两个列簇中的列个数不必相等,
两个行同一列簇下运行有不同的列,即半结构化
通过cf:c 唯一指定一列 - Value
值,每一列的值,hbase底层没有数据类型,都是字节存储,允许存储多版本的值 - Version
版本数,属于列簇的一个属性,默认版本为1个,可以配置多版本来存储多版本的数据
默认查询时,只显示每一列的最新的那个版本数据
如果每条存储数据超过版本数,旧的版本会被覆盖
设计多版本是为了存储,默认显示最新版本是为了读取 - TimeStamp
时间戳,用来区分版本,
version版本数是一个设置,timestamp是一个标识
默认值是数据插入的格林尼治时间
查询是需要指定时间戳才能唯一确定一条数据
每一列都有一个时间戳,同行同列簇同版本下的不同列的时间戳相同