HBase
- HBase全称: Hadoop DataBase
- HBase的思想来源于google的BigTable论文, 适合存放千万级别以上的数据
- Hbase完全依赖于HDFS, 用于存储数据
- Hbase基于列, 而不是基于行
- SELECT * FROM user WHERE id = 888;
- SELECT uname from user WHERE id = 888;
- 适合存放半结构化或者非结构化的数据
- 结构化:
- 我们定义了一个类(结构体), 由类创建的对象都保持着同意的结构
- 非结构化的数据
- 没有强制要求对象与对象之间的属性相同
- 对象可以根据自己的需求定义自己的属性半结构化的数据
- 半结构化的数据
- 介于结构和非结构之间的数据存储方式
- 结构化:
- HBase 是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统, 使用Hbase技术可以在廉价PC Server 上搭建起大规模结构化存储集群。
- 高可靠性: 防止单点故障(Zookeeper, failover机制)
- 高性能: MapReduce计算
- 面向列: 每个对象可以有自己的列。维护的时候直接找某一行数据的某一列
- 可伸缩性: 基于HDFS, 所有可以在保证数据安全的前提下完成存储的扩容
- 目标: 在廉价的PC上搭建出大规模集群
- 它其实就是个数据库(安装, SQL, JDBC, 性能调优, 底层原理)
HBase的数据结构
-
针对于以前的关系型数据库, 只需要二维就可以获取指定的信息
- 行ID
- 列名称
-
对于HBase需要四个维度才能定义一个数据
- RowKey
- 类似关系型数据库的ID
- 用来唯一地表明对应列族的数据
- 列族一般占用64K的数据长度, 但是可以动态分配
- RowKey会默认按照字典序进行排序(待优化)
- Timestamp
- 时间戳, 或者数据的版本
- 不同的列族可以有不同的时间版本
- 默认version使用当前系统时间的毫秒数
- 也可以自定义version, 但是需要考虑版本的设置策略防止出现重复的版本
- HBase的数据存放在HDFS上
- HDFS不支持数据的2修改, so对于修改操作即使新增操作
- 不同的数据上有其对应的时间戳, 数据以时间戳为标准降序排列
- 新插入的数据会优先被查询到, 根据用户设置的版本数据, 保留有效的时间戳
- 数据的清除方式:
- 超过版本树
- 超过存储的时间
- Column Family
- 可以吧它作为有相同意义的列集合体
- 通过列族才能找到对应的列
- 一般项目中很少涉及超过3个列族
- 在创建表的时候必须先给出列族
- Qualifier
- 是属于列族中的一个属性
- 也可以被当做列族中的一个子列
- 查询的时候, 通过rowkey找到列族, 通过列族再查找子列
Cell
- 通过以上四个维度最终定位的数据
- 单元格由四个维度共同决定
- 所有数据存储在Base上都是无数据类型的, 统一为字节数组
HBase的系统架构
- Client
- 访问HBase的入口, 有多种连接方式
- shell
- java
- mapreduce
- 向HBase的服务器发送命令
- DDL(Data Definition Language) - 数据模式定义语言
- DML(Data Manipulation Language) - 数据操纵语言
- DQL(Data Query Language) - 数据查询标准语法
- 在客户端记录服务器的缓存信息, 留待下一次的使用
- 访问HBase的入口, 有多种连接方式
- Zookeeper
- 监控集群中的HMaster的运行情况, 保证集群在任何时候只有一个主Master
- 当我们创建表的时候, 表的结构信息会存放在Zookeeper中, 作用是:
- 防止放在HMaster上后遇到节点故障, 丢失数据
- 让主从master共享数据
- 更快的访问共享数据
- HMaster管理HRegionServer, Zookeeper监听HRegionServer上线或者下线
- Zookeeper保存了Region的地址
- HMaster
- 接受客户端的请求(DDL)
- 监控RegionServer, 了解RegionServer的当前节点状态
- 接受DDL请求之后, 会选择一个空闲(内存, 空间)的节点执行表的创建
- 当发现HRegionServer掉线后, 会将其上的region切换到其他的HRegionServer
- HRegionServer
- 负责管理当前节点的Region
- 一个HRegionServer有可能存在多个Region
- 监控Region的大小, 达到阈值(10G), 将Region进行相对等分
- 切分数据时, 以保证数据完整性为前提
- 新分的Region交给另外的HRegionServer维护
- 负责维护与客户端的IO请求
- HLog(WAL日志)
- WAL(Write Ahead Log) 提前写入日志
- HLog隶属于HRegionServer
- HRegionServer中的所有HRegion共享这个HLog
- 当达到阈值的时候, 会优先写出日志, 然后将内存中的数据写出到Storefile
- 写出之后再Hlog中记录一个检查点, 新增加到内存的时候都在该日志之后
- HLog最终也会被写出到DFS上
- HRegion
- 初始情况下, 一个表对应一个Region, 随着数据增多, region有可能被切分
- Region的预分区: 在建表时就提前创建N个Region
- 这些Region会被分配至不同的HRegionServer
- 即使表的数据2没有达到10G的阈值也会有多个HRegionServer提供服务
- 一个表对应多个Region, 但是一个Region至对应一个表
- 数据存放到表的时候会按照rowkey的字典序排列
- so切分Region的时候, 新的Region也是有序的
- 初始情况下, 一个表对应一个Region, 随着数据增多, region有可能被切分
- Store
- 一个Region由多个Store组成
- 一个Store对应一个列族
- Store由memstore和StoreFile组成
- memstore
- StoreFile: N
- 当数据存放到数据库的时候, 数据应该存放到
- 内存: 快,掉电易失
- 硬盘: 持久化, 慢
- 做任何操作之前, 先存放日志
- 将数据写入到内存中, 然后找准时间将数据持久化到硬盘
- 阈值 (内存的占比) (日志的条数)
- MemStore
- 基于内存的数据存储
- 当新增数据的时候会先写入到日志, 然后写入到内存
- 这样会提高数据插入速度
- StoreFile
- 将MemStore中的数据写出到DFS
- 随着事件的推移, StoreFile的数量越来越多
- 当一个数据被修改的时候, 并不会直接操作原来的StoreFile, 只是对这个记录做一个标识
- 当StoreFile达到一定数量的时候, 会进行合并
- 客户端进行数据检查时, 有限查找MemStore, 然后才去StoreFile
HBase数据存储和读取的流程
DDL语句- 客户端发送请求到HMaster
- HMaster
- 检查创建表的权限等信息是否足够
- 寻找合适的HRegionServer
- 将创建Region的任务下发给HRegionServer
- 当表创建好之后, 在Zookeeper中保存两个信息
- 表的数据结构
- 存放Region与HRegionServer的对应关系
DQL
- 首先客户端发送请求查询数据
- 查询数据对应的表 student rowkey=888
- 查询对应的Region信息, 然后查找888对应的region
- 查找Region对应的HRegionServer
- 在HBase为了快速的定位到Region与HRegionServer
- 于是专门定义了两张表, 他们两个有相同的表结构
- .meta. 存放的都是table与region与regionserver的对应关系
- meta随着表数量增多, region切分增多会导致
- 切分: 去向不知
- 不切: regionserver压力过大
rowkey Info: regioninfo Info: server
student,10,163067 s:10 e:19 family list{info, score} regionserver111
student,20,163066 s:20 e:29 family list{info, score} regionserver222
student,30,163064 s:30 e:39 family list{info, score} regionserver888
- -root-
- 只记录.meta.的位置
- root的数据完全可控, 所以root路径是固定的
rowkey Info: regioninfo Info: server
.meta.,student,10,163067 regionserver111
.meta.,super,10,163067 regionserver222
.meta.,system,10,163067 regionserver888
- .meta. 存放的都是table与region与regionserver的对应关系
- 和Region所在的RegionServer建立连接
- 因为Region中的数据都是有序的, 所以二分查找时间复杂度为O(logN)
- 为了效率尽量将相近属性的列放在一个列族中
DML-插入数据
- 存储的数据最终以HFILE的形式存放在HDFS上
- HFile的数据格式
- 典型的一个三级的索引结构
- trailer
- dataindex
- 357
- 414
- 505
- 4:27
- 4:55
- byte[27]-->key(478)
- byte[55]--<value(521)
- 614
- 717
- ......
- metablock
- fileInfo
- dataindex
- 如果插入数据的时候可以直接生成日志和对应的数据文件
- 我们可以直接将日志写入到HLog, 文件拷贝到指定的位置
- 免除了中间生成, 合并的过程, 效率会提高
- RowKey