声明: 1. 本文为我的个人复习总结, 并非那种从零基础开始普及知识 内容详细全面, 言辞官方的文章
2. 由于是个人总结, 所以用最精简的话语来写文章
3. 若有错误不当之处, 请指出
基础知识:
数据种类:
- 结构化数据 比如MySQL这种关心型数据库里的数据, 操控起来方便
- 半结构化数据 有特定语法格式的数据, 比如json
- 非结构化数据 视频,音频,文本 这种难以处理的数据
关系型数据库 & 非关系型(NoSQL)数据库:
- 数据类型不同: 关系型数据库的数据类型是二维表格, NoSQL数据库的数据类型没有确定形式, 很灵活, 有KV型, 列式, 文档型等等
- 关系型数据库支持SQL语法, 而NoSQL数据库不支持SQL语法
行式数据库 & 列式数据库
-
存储方式不同:
比如有A列和B列, 数据有A1, A2, A3, B1, B2, B3
行式存储为: [A1, B1, A2, B2, A3, B3]; 列式存储为: [A1, A2, A3, B1, B2, B3]
-
擅长领域不同: 行式数据库适用于查询, 列式数据库适用于聚合统计
从存储方式上可以看出, 行式存储的某一行的不同列之间紧挨着, 适合查询一整行数据;
列式存储的某一列的不同行之间紧挨着, 适合查询一整列的数据
而大数据场景, 大多数时都是数据的统计。我们经常只是需要其中某一列进行聚合统计,而不关心其他列的数据
-
压缩效果不同, 列式存储压缩效果更好
OLTP & OLAP
OLTP: 联机事务处理, 一般是那种 后端的关系型数据库(存储数据少, 行式数据库MySQL等)
OLAP: 联机事务分析, 一般是那种 大数据的NoSQL数据库(存储数据多, 列式数据库如HBase/ClickHouse, Presto)
架构:
有RowKey, 列族, 列, Region, StoreFile(HFile), Cell, 命名空间, 表
增改为Put, 删除为Delete(本质也是Put), 关键字段timestap就代表着版本
结构图:
- 一个Region是多行相邻数据, 按列族(对应StoreFile)存储,
自带的命名空间:
- hbase 存放的是HBase内置的表
- default 表是用户默认使用的命名空间
-
HBase定义表时只需要声明列族即可, 不需要声明具体的列, 字段可以动态、按需指定。因此适合应对字段变更的场景。
-
BlockCache是用来优化读操作的缓存, MemCache是为了优化写操作的缓冲(到刷写时机了批量写到磁盘)
WAL预写日志:
-
HBase的WAL只是为了备份数据, flush和compact的时候并不用它(flush用的是内存数据, compact用的是HFile)
-
Hadoop的EditLog除了是用来备份数据, 与FsImage合并时也要用到它
- hbase truncate不要乱用, 它会同时删除元数据信息如分区键规则, 协处理器倒是不会删掉
LSM:
HBase和ClickHouse这种内存+磁盘的架构, 即用的是LSM结构(日志结构的合并树)
思想: 假定内存足够大,因此不需要每次有数据更新就必须将数据写入到磁盘中,而可以先将最新的数据驻留在内存中;
等到积攒到足够多之后,再归并排序将数据合并追加到磁盘
与B+树相比:
- 牺牲读性能(读取时可能需要访问较多的磁盘文件)
- 提高写性能(刷写落盘前有一个内存缓冲区)
补偿读性能的优化:
- Bloom Filter 读HFile时使用布隆过滤器
- compact 小树合并为大树
架构角色:
-
HMaster
负责DDL操作: 对于表结构 create, delete, alter
负责管理调度: 分配regions到每个RegionServer(并做负载均衡和故障转移)
监控每个RegionServer的状态
-
HRegion Server
管理Region, WAL, 负责table数据的实际读写, 执行Flush 和 Compaction
-
ZooKeeper
-
HBase通过ZooKeeper来做Master的
高可用
-
监控RegionServer
-
Client请求ZooKeeper meta表位于哪个RegionServer
-
-
HDFS
读流程:
Client先访问ZooKeeper,获取hbase:meta表位于哪个Region Server
访问对应的Region Server,获取hbase:meta表,
根据namespace:table:rowkey,查询出目标数据位于哪个Region Server中的哪个Region
并将该表的 Region信息&meta表的位置信息 缓存在客户端的meta cache
- 与目标Region Server进行通讯
- 先在MemStore中查询目标数据,
- 再去Block Cache中查询目标数据,如果找不到的话再去查询Store File(HFile)
- 将查询到的新的数据块(HFile的数据存储单元, 默认大小为64KB)缓存到Block Cache
- 返回这两次查到的 最新版本的数据
写流程:
1)Client先访问ZooKeeper,获取hbase:meta表位于哪个Region Server
2)访问对应的Region Server,获取hbase:meta表,
根据namespace:table:rowkey, 查询出目标数据所在表位于哪个Region
并将该表的 Region信息&meta表的位置信息 缓存在客户端的meta cache
3)与目标Region Server进行通讯
4)将数据顺序写入(追加)到HLog(WAL), 做备份
5)将数据写入对应的MemStore,数据会按RowKey在MemStore进行排序, 便于以后的查找缩小范围
6)Region Server向客户端发送ack
7)等达到MemStore的刷写时机后,将数据刷写到HFile
MemStore Flush刷写时机:
-
某个MemStore的大小达到了
hbase.hregion.memstore.flush.size
(默认128M)
-
什么时候阻止继续往某个MemStore写数据?
当MemStore的大小达到了
hbase.hregion.memstore.flush.size
(默认125M) *hbase.hregion.memstore.block.multiplier
(默认4), 即500M时
-
-
某个RegionServer中所有MemStore的总大小达到
堆内存大小
*hbase.regionserver.global.memstore.size
(默认0.4)*
hbase.regionserver.global.memstore.size.lower.limit
(默认0.95), 即0.38倍堆大小时则按照所有MemStore由大到小的顺序依次进行刷写, 直到所有memstore的总大小减小到低于上述临界值
这种情况下可见, HFile里的数据timestap未必是最小的, 那查数据时, 即便MemStore中找到了该数据也仍要去访问HFile文件(但会借助于布隆过滤器), 因为timestap大的才是最新数据
-
什么时候阻止继续往所有MemStore写数据?
当某个RegionServer中MemStore的总大小达到
堆内存大小
*hbase.regionserver.global.memstore.size
(默认值0.4), 即0.4倍堆大小时
-
-
到达自动刷写的时
hbase.regionserver.optionalcacheflushinterval
(默认1小时) -
当WAL文件的数量超过
hbase.regionserver.max.logs
,会按照timestap从小到大顺序依次进行刷写, 直到WAL文件数量减小到低于上述临界值(该属性名已废弃, 现无需手动设置,最大为32)
读写特点:
HBase的读写类似, 即便是写(增删改)数据也要先查找数据所在表位于哪个RegionServer中的哪个Region
而HDFS的写, 既然是写(增加)数据, 就不会提前位于DataNode中
StoreFile Compaction:
StoreFile
底层是HFile
是为了减少HFile的个数,以及清理掉 过期和删除 的老数据
-
Minor Compaction
将临近的若干个较小的HFile合并成一个较大的HFile, 并清理掉 过期和删除 的数据
-
Major Compaction
将一个Store下的所有的HFile合并成一个大HFile, 并清理掉 过期和删除 的数据
Region Split:
起初表只有一个Region(如果不自己预分区的话),
为了更好的负载均衡 以及增加存储利用率,HMaster有可能会将某个Region转移给其他的Region Server
切分规则:
0.94版本之后, 2.0版本之前:
阈值为min(R^3 * initialSize,hbase.hregion.max.filesize”), 即min(R^3 * 256M, 10G)
R为当前Region Server中属于该表的Region个数
示例:
第一次split:1^3 * 256 = 256MB
第二次split:2^3 * 256 = 2048MB
第三次split:3^3 * 256 = 6912MB
第四次split:4^3 * 256 = 16384M > 10GB,因此取较小的值10GB
后面每次split的size都是10GB了
2.0版本新策略:
-
如果当前RegionServer上该表只有1个Region,则按照2 * hbase.hregion.memstore.flush.size切分,
-
否则按照hbase.hregion.max.filesize切分。
预分区:
目的: 自定义分区后, 根据数据的RowKey可以迅速得知它属于哪一个Region
比如按 100,200,300分区键 去预分区, 则有(-∞, 100], (100,200], (200,300],(300,+∞) 这4个分区,
一条数据是拿Rowkey和分区键 按照字典序比较的
设定预分区的方法:
-
手动设定预分区
create ‘staff1’,‘info’,‘partition1’,SPLITS => [‘100’,‘200’,‘300’]
-
生成16进制序列预分区(0-15, 16个分区键)
create ‘staff2’,‘info’,‘partition2’,{NUMREGIONS => 15, SPLITALGO => ‘HexStringSplit’}
-
按照文件中设置的规则预分区(常用):
vim splits.txt
aaaa
bbbb
cccc
dddd
create ‘staff3’,‘partition3’,SPLITS_FILE => ‘splits.txt’
-
使用JavaAPI创建预分区
//自定义算法,产生一系列Hash散列值存储在二维数组中, byte[]相当于String, bytre[][]相当于String[] byte[][] splitKeys = 某个散列值函数 //创建HbaseAdmin实例 HBaseAdmin hAdmin = new HBaseAdmin(HbaseConfiguration.create( )); //创建HTableDescriptor实例 HTableDescriptor tableDesc = new HTableDescriptor(tableName); //通过HTableDescriptor实例和散列值二维数组创建带有预分区的Hbase表 hAdmin.createTable(tableDesc, splitKeys);
RowKey设计:
目的: 让数据均匀的分布, 防止数据倾斜
_小于所有数字
| 是大于很多字符, 只小于}
设计原则:
-
rowkey长度原则
-
rowkey散列原则
-
rowkey唯一原则
方案:
-
生成随机数、hash、加密
例如原本rowKey为1001的,SHA1后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7
-
日期时间反转(个位变化频率低, 高位变化频率低, 所以原数据分布有规律会数据密集, 而反转后就没规律了)
20170524000001转成10000042507102
20170524000002转成20000042507102
-
随机字符串拼接
20170524000001_a12e
20170524000001_93i7
高可用:
vim conf/backup-masters, 里面写上备机ip
内存优化:
不建议分配非常大的堆内存, 一般配16~36G
因为:
-
在(0.4-0.38)*堆大小 这段内存回收时, RegionServer是禁止写数据的, 堆内存过大会增大其值, 导致增加了禁止写数据的时间
-
Linux系统运行和其他软件运行也需要内存, 不能全分给HBase了
参数优化
-
ZooKeeper会话超时时间
ZooKeeper.session.timeout
默认值为90000毫秒(90s)。当某个RegionServer挂掉了, 90s之后Master才能察觉到。可适当减小此值,以加快Master响应,可调整至600000毫秒。
-
设置RPC监听数量
hbase.regionserver.handler.count
默认值为30可以根据客户端的请求数进行调整,读写请求较多时,增加此值。
-
手动控制Major Compaction的周期
hbase.hregion.majorcompaction
默认值:604800000秒(7天)若关闭自动Major Compaction,可将其设为0
-
优化HFile大小
hbase.hregion.max.filesize
默认值10737418240(10GB), 如果一个HFile(列族)的大小达到这个数值, 则这个Region就会被切分为两个Region如果要运行HBase的MR任务, 可以减小此值
因为一个Region对应一个MapTask,如果单个Region过大,会导致MapTask执行时间过长。
-
优化HBase客户端缓存大小
hbase.client.write.buffer
默认值2097152bytes(2M)增大该值可以减少RPC调用次数
-
指定scan.next扫描HBase所获取的行数
hbase.client.scanner.caching
-
BlockCache占用RegionServer堆内存的比例
hfile.block.cache.size
默认0.4读请求比较多的情况下, 可适当调大
-
MemStore占用RegionServer堆内存的比例
hbase.regionserver.global.memstore.size
默认0.4写请求较多的情况下,可适当调大
-
优化数据的写入效率, 开启压缩
mapreduce.map.output.compress
设为truemapreduce.map.output.compress.codec
指定压缩方式
Hive对比HBase:
速度上:
- Hive 查询 和 增加数据 速度缓慢, 因为要走MR等引擎
- HBase 查询 和 增加数据 快, 因为布隆过滤器 & BlockCache & 顺序写操作(按timestap判断是否为最新有效数据) 进行优化
增删改方面:
- 只允许增加数据
- 虽然也是只允许增加数据, 但是通过timestap字段, 可以实现增删改的功能
是否为数据库:
- Hive本质上并不是数据库, 而是将MySQL表的元数据 和 HDFS文件进行映射, 形成了逻辑上的数据库
- HBase是列式数据库
数据分析方面:
-
Hive擅长做数据分析
-
HBase不擅长做数据分析
相同点:都依赖于HDFS进行存数据, 可以用SQL语句去查数据
Hive集成HBase:
目的: 建立Hive表关联HBase表,插入数据到Hive表的同时能够影响HBase表
注意: 不能将数据直接load进Hive(这只会校验存储格式, 合法的法直接剪切, 让HBase感知不到)
步骤: 创建表&关联 –> 创建临时表 –> load进临时表 –> insert into 原表 select 字段 from 临时表
在hive-site.xml里配置ZooKeeper
<property>
<name>hive.ZooKeeper.quorum</name>
<value>hadoop102,hadoop103,hadoop104</value>
</property>
<property>
<name>hive.ZooKeeper.client.port</name>
<value>2181</value>
</property>
建表时通过描述语句进行关联:
CREATE TABLE hive_hbase_emp_table(
empno int,
ename string,
job string,
)
-- 描述语句
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":id, info:ename, info:job")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
Phoenix:
是HBase的SQL皮肤
坑: 注意大小写, 在引号内部才能保持原样, 否则就任务是大写
(一级)索引是对RowKey的索引
二级索引是对非RowKey字段的索引, 先找到这个普通字段数据对应的主键, 再通过主键去查找实际数据
全局 & 本地: (优缺点没搞懂)
-
全局二级索引(默认), 适用于读多写少, 索引 和 数据 不存储在一起
优点: 读数据时 会优先选择索引表来查询
缺点: 写操作时 要更新的索引可能位于不同机器, 加大了网络IO 和 磁盘寻址IO 的损耗, 更占用空间
-
本地二级索引, 适用于写多读少, 索引 和 数据 存放在同一个Region中(且是同一个),
优点: 写操作时 要更新的索引位于同台机器, 减少了网络IO 和 磁盘寻址IO(实际数据在附近, 顺序寻址较快) 的额外开销, 更节省空间
缺点: 无法提前确定数据在哪个Region上
面试题:
-
HBase的批量加载 底层是靠MapReduce实现的
-
协处理器(CoProcessor)
分为:
- Observer: 相当于MySQL的触发器, 监听到一个表变化后 便自动地去同步操作另一个表 (如 偶像表 和 粉丝表 需要同步变化)
- Endpoint: 类似于MySQL地存储过程, 一般用于分布式聚合计算
建立二级索引, 需要同步索引表, 靠的就是Observer协处理器
今天的文章HBase基础知识(个人总结)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/67751.html