摘要:慕课网存储原理剖析学习总结时间年月日星期一说明本文部分内容均来自慕课网。每一列簇包含多个列列标识符。每一列数据包含了版本和值版本。
慕课网《HBase 存储原理剖析》学习总结
时间:2018年06月11日星期一
说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com
教学源码:无
学习源码:https://github.com/zccodere/s...
第一章:课程介绍 1-1 课程介绍课程目标
HBase的存储模式
HBase数据表解析
HBase存储设计
HBase数据存取解析
第二章:存储模式 2-1 存储模式行式存储与列式存储介绍
行式存储与列式存储特点
行式存储
维护大量的索引
存储成本高
不能够做到线性扩展
随机读取效率非常高
对事务的支持非常好
列式存储
根据同一列数据的相似性原理,利于对数据进行压缩
存储成本低
由于每列数据分开存储,可以并行查找多列的数据
行式存储与列式存储场景
行式存储
表与表之间有关联关系,数据量不大(小于千万量级)
强事务关联的特性
列式存储
对于单列或者相对比较少的列获取频率较高
针对多列查询,使用并行处理的查询
利于数据压缩和线性扩展的存储
事务使用率不高,读取的场景频率不高,同时数据量非常大
随机更新某一行的频率不高
列簇式存储:概念
列簇(多个数据列的组合),HBase表中的每个列都归属于某个列簇
列簇是表的schame的一部分,但是列并不是
创建表时,需要给出列簇的名称,不需要给出列的名称
列名都是以列簇作为前缀
访问控制磁盘和内存的使用统计都是在列簇层面进行
HBase准确的说是列簇数据库,而不是列数据库
列簇数据库将列组织为列簇,每列都必须是某个列簇的一部分
访问数据的单元也是列
HBase表的组成
Table = RowKey + Family + Column + Timestamp + Value
RowKey :HBase中用RowKey去标识唯一的一行数据,一行数据中包含多个列簇
Family:多个列簇。每一列簇包含多个列
Column:列标识符。每一列数据包含了版本和值
Timestamp:版本。可以理解为时间戳,也可以理解为一个数据的版本
Value:数据值。数据本身的值
HBase数据存储的模式
(Table, RowKey, Family, Column, Timestamp)-> Value
其实就是HBase表反过来看的样子
【重点】更抽象一点,其实HBase表数据就是Key-Value结构的
图解
列簇式存储:列数据属性
HBase重要特性:列数据版本的概念,默认一列数据可以保存三个版本
列簇式存储:数据存储原型
2-2 存储示例示例表定义
示例表数据
第三章 表的解析 3-1 建表语句示例表语句定义
压缩算法
算法 | 压缩率 | 编码速度 | 解码速度 |
---|---|---|---|
GZip | 13.4% | 21MB/s | 118MB/s |
LZO | 20.5% | 135MB/s | 410MB/s |
Snappy | 22.2% | 172MB/s | 409MB/s |
在hbase-site.xml文件中配置或查看存储目录的节点
hbase.rootdir /home/hbase_data
进入到HBase系统目录
.tmp
当对表做创建或删除操作时,将表移动到tmp目录下,然后再进行处理
临时交换的表,临时存储一些当前需要修改的数据结构
WALs
预写日志,被HLog实例管理的WAL文件
可以理解为存储HBase的日志,HBase分布式数据库系统的操作日志
archive
存储表的归档和快照
HBase在做分割或合并操作完成后,会将Hfile文件移动到该目录中,然后将之前的Hfile删除掉
是由Master上的定时任务定期去处理,这个目录的作用可以简单理解为去管理HBase的数据
corrupt
用于存放损坏的日志文件,一般是空的
data
HBase存储数据的核心目录
系统表和用户表数据都存储在这里
hbase.id
HBase启动运行后,是集群中的唯一ID,用来标识HBase进程用的
hbase.version
表明了集群的文件格式版本信息
其实就是表明了Hfile的版本信息
oldWALs
备份WALs中的日志文件
data目录解析
HBase元信息表
Row Key | Value |
---|---|
table、key、time | region server |
HBase中的LSM存储思想
什么是LSM树
LSM日志结构合并树,有两个或两个以上存储数据的结构组成的,每一个数据结构各自对应自己的存储介质
LSM树的简易模型描述
LSM思想在HBase中的思想
4-2 存储模块HBase数据存储模块简介
RegionServer = Region + Store + MemStore + StoreFile + HFile + HLog
HBase Region解析
什么是Region
每一个Region都会存储于确定的RegionServer上
Region的特点
是HBase中分布式存储和负载均衡的最小单元
Region的数据不能低于集群中节点的数量
RegionServer对Region进行拆分
尽量让Row key分散到不同的Region
HBase HFile解析
Store + MemStore + StoreFile
Store与列簇是一对一的关系
MemStore是一个内存数据结构,保存修改的数据
StoreFile是由内存数据写入到文件后形成的
> ![image](https://note.youdao.com/yws/api/personal/file/BC358BAF87A44E01AC1E29C9742DF6F2?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HFile 文件
是HBase存储数据文件的最基本的组织形式
底层是Hadoop的二进制格式文件
是用户数据的实际载体,存储Key-Value的数据
Scanned block section:会被读取,主要是存储用户数据
Nonscanned block section:不会被读取,主要包含元数据块
Load-on-open section:RegionServer启动时加载,主要是HFile的元数据
Trailer:HFile的基本信息,HFile元数据的一部分
> ![image](https://note.youdao.com/yws/api/personal/file/27F88E086AC5419F83F5BC9473060F52?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
Data Block
HBase中数据的最基本的存储单元
是实际存储用户数据的数据结构
包含很多Key-Value
> ![image](https://note.youdao.com/yws/api/personal/file/6C175A6EF8D546FCB02CED9E10B364DE?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HBase WAL解析
简介介绍WAL(预写日志)
WAL最重要的功能就是灾难恢复
WAL解决了什么问题:HA(高可用)问题
怎么解决:远程备份
> ![image](https://note.youdao.com/yws/api/personal/file/993E28018DCA4AD7AABDDF494154F91B?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HLog
WAL是通过HLog模块实现的
HLog是什么:HLog是实现WAL的类,一个RegionServer对应一个HLog实例
> ![image](https://note.youdao.com/yws/api/personal/file/C7E652C51E564E0A811C1F23FFBB2F0E?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HLogKey
WAL使用Hadoop的序列化文件将记录存储为Key-Value的数据集,Key就是HLog的Key
> ![image](https://note.youdao.com/yws/api/personal/file/3F4EADB35EB74A66B9CBD736C7989B07?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HLogSyncer
是日志同步刷写类
> ![image](https://note.youdao.com/yws/api/personal/file/A9A568573E9042C3BFE4F33042F7DB2B?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HLogRoller
特点的时间去滚动日志,形成新的日志,避免单个日志文件过大
根据HLog的序列化的number对比已经持久化的HFile的序列号,删除旧的,不需要的日志
> ![image](https://note.youdao.com/yws/api/personal/file/F1AB5E58BBAE435FA5F35957EE3276C3?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HBase Compaction解析
什么是Compaction
Compaction会从一个Region的Store中选择一些HFile文件进行合并
为什么要Compaction
随着系统不停的刷写,会导致存储目录中有过多的数据文件
Compaction分类
MinorCompaction:小合并
MajorCompaction:大合并
> ![image](https://note.youdao.com/yws/api/personal/file/053CA3350B764F60B0A2DB01D841FAEA?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
Compaction触发时机
MemStore 内存数据写入到硬盘上
> ![image](https://note.youdao.com/yws/api/personal/file/C9D3EA024E1848178E3879F80C1536A0?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)4-3 存取解析
HBase数据存储流程解析
HBase Client
请求Zookeeper,确定 MetaTable所在RegionServer的地址
在根据RowKey找到归属的RegionServer
HBase Client Put(Delete)数据,提交到RegionServer
> ![image](https://note.youdao.com/yws/api/personal/file/FCE4E73CC9774EFEA2C0A060C142CD61?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HBase Server
Region Server 去获取行锁,Region更新共享锁
写HLog,WAL
写缓存,MemStore
将日志同步到HDFS
写满缓存后,启动异步线程将数据写入到硬盘上
可能触发Compaction或拆分
> ![image](https://note.youdao.com/yws/api/personal/file/C6724DFE164448E694FF61FE657CE68F?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HBase数据获取流程解析
HBase Client
请求Zookeeper,确定 MetaTable所在RegionServer的地址
去对应的RegionServer地址拿到对应数据
> ![image](https://note.youdao.com/yws/api/personal/file/31D60278867C4C27BDCA35AEBD57436E?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)
HBase Server
Region Server 构建RegionScanner准备进行检索
有多少个列簇就构建多少个StoreScanner,用于对确定的列簇数据检索
> ![image](https://note.youdao.com/yws/api/personal/file/8840F5554C354B39A14D00E2B39CBF5C?method=download&shareKey=416cc5492bf4a2243d657a2c6999b735)4-4 数据存取
HBase数据存取api介绍
新增api void put(Put put)throws IOException Put构造方法 Put(byte[] row) Put(byte[] row,long ts) 填充值 Put add(byte[] family,byte[] qualifier,byte[] value) Put add(byte[] family,byte[] qualifier,long timestamp,byte[] value) Put add(KeyValue kv)throws IOException 原子检查写 boolean checkAndPut(add(byte[] row,byte[] family,byte[] qualifier,byte[] value,put)) 删除api void delete(Delete delete)throws IOException 构造方法 Delete(byte[] row) 填充值 Delete deleteFamily(byte[] family) Delete deleteColumns(byte[] family,byte[] qualifier) Delete deleteColumns(byte[] family,byte[] qualifier,long timestamp) 原子检查删除 boolean checkAndDelete(byte[] row,byte[] family,byte[] qualifier,byte[] value,Delete delete)throws IOException 获取api Result get(Get get)throws IOException 构造方法 Get(byte[] row) 填充值 Get addFamily(byte[] family) Get addColumn(byte[] family,byte[] qualifier) Get setTimeRange(long minStamp,long maxStamp)throws IOException Get setTimeStamp(long timestamp) Get setMaxVersions() Get setMaxVersions(int maxVersions)throws IOException第五章:案例演示 5-1 案列演示
创建名为hbase-demo的maven工程pom如下
4.0.0 com.myimooc hbase-demo 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.1.RELEASE UTF-8 UTF-8 1.8 org.springframework.boot spring-boot-starter org.yaml snakeyaml 1.10 org.springframework.boot spring-boot-configuration-processor true jdk.tools jdk.tools 1.7 system ${JAVA_HOME}/lib/tools.jar com.spring4all spring-boot-starter-hbase 1.0.0.RELEASE com.alibaba fastjson 1.2.45 org.springframework.boot spring-boot-starter-test test
1.编写User类
package com.myimooc.hbase.demo.dto; /** *
* 标题: 用户表
* 描述: 用户表
* * @author zc * @date 2018/06/21 */ public class User { /** * 行键 */ private String row; /** * 基础信息 */ private BaseInfo baseInfo; /** * 其他信息 */ private OtherInfo otherInfo; public User() { } public User(String row, BaseInfo baseInfo, OtherInfo otherInfo) { this.row = row; this.baseInfo = baseInfo; this.otherInfo = otherInfo; } @Override public String toString() { return "User{" + "row="" + row + """ + ", baseInfo=" + baseInfo + ", otherInfo=" + otherInfo + "}"; } public String getRow() { return row; } public void setRow(String row) { this.row = row; } public BaseInfo getBaseInfo() { return baseInfo; } public void setBaseInfo(BaseInfo baseInfo) { this.baseInfo = baseInfo; } public OtherInfo getOtherInfo() { return otherInfo; } public void setOtherInfo(OtherInfo otherInfo) { this.otherInfo = otherInfo; } /** * 使用内部类表示 b 列簇 基础信息 */ public static class BaseInfo { /** * 名称 */ private String name; /** * 年龄 */ private Integer age; /** * 性别 */ private String sex; public BaseInfo() { } public BaseInfo(String name, Integer age, String sex) { this.name = name; this.age = age; this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } } /** * 使用内部类表示 o 列簇 其他信息 */ public static class OtherInfo { /** * 电话 */ private String phone; /** * 地址 */ private String address; public OtherInfo() { } public OtherInfo(String phone, String address) { this.phone = phone; this.address = address; } @Override public String toString() { return "OtherInfo{" + "phone="" + phone + """ + ", address="" + address + """ + "}"; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } }
2.编写UserRowMapper类
package com.myimooc.hbase.demo.mapper; import com.myimooc.hbase.demo.dto.User; import com.spring4all.spring.boot.starter.hbase.api.RowMapper; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.util.Bytes; /** *
* 标题: 用户表ORM
* 描述: 用户表ORM
* * @author zc * @date 2018/06/21 */ public class UserRowMapper implements RowMapper{ private static byte[] FAMILY_B = "b".getBytes(); private static byte[] FAMILY_B_NAME = "name".getBytes(); private static byte[] FAMILY_B_AGE = "age".getBytes(); private static byte[] FAMILY_B_SEX = "sex".getBytes(); private static byte[] FAMILY_O = "o".getBytes(); private static byte[] FAMILY_O_PHONE = "phone".getBytes(); private static byte[] FAMILY_ADDRESS = "address".getBytes(); @Override public User mapRow(Result result, int i) throws Exception { User.BaseInfo baseInfo = new User.BaseInfo( Bytes.toString(result.getValue(FAMILY_B, FAMILY_B_NAME)), Bytes.toInt(result.getValue(FAMILY_B, FAMILY_B_AGE)), Bytes.toString(result.getValue(FAMILY_B, FAMILY_B_SEX))); User.OtherInfo otherInfo = new User.OtherInfo( Bytes.toString(result.getValue(FAMILY_O, FAMILY_O_PHONE)), Bytes.toString(result.getValue(FAMILY_O, FAMILY_ADDRESS))); return new User(Bytes.toString(result.getRow()),baseInfo,otherInfo); } }
3.编写HbaseService类
package com.myimooc.hbase.demo.service; import org.apache.hadoop.hbase.client.Mutation; import java.util.List; /** *
* 标题: HBase服务
* 描述: HBase服务
* * @author zc * @date 2018/06/21 */ public interface HbaseService{ /** * 查询指定行键的表数据 * @param tableName 表名 * @param row 行键 * @return 数据 */ T findByRow(String tableName,String row); /** * 查询指定行键之间的表数据 * @param tableName 表名 * @param startRow 开始行键 * @param endRow 结束行键 * @return 数据集合 */ List findByStartEndRow(String tableName,String startRow,String endRow); /** * 保存或修改数据 * @param tableName 表名 * @param datas 数据集合 * @return 数据集合 */ List saveOrUpdate(String tableName,List datas); }
4.编写UserHbaseServiceImpl类
package com.myimooc.hbase.demo.service.impl; import com.myimooc.hbase.demo.dto.User; import com.myimooc.hbase.demo.mapper.UserRowMapper; import com.myimooc.hbase.demo.service.HbaseService; import com.spring4all.spring.boot.starter.hbase.api.HbaseTemplate; import org.apache.hadoop.hbase.client.Mutation; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.util.Bytes; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** *
* 标题: 用户服务
* 描述: 用户服务
* * @author zc * @date 2018/06/22 */ @Service public class UserHbaseServiceImpl implements HbaseService{ @Autowired private HbaseTemplate hbaseTemplate; @Override public User findByRow(String tableName, String row) { return hbaseTemplate.get(tableName, row, new UserRowMapper()); } @Override public List findByStartEndRow(String tableName, String startRow, String endRow) { Scan scan = new Scan(Bytes.toBytes(startRow), Bytes.toBytes(endRow)); return hbaseTemplate.find(tableName, scan, new UserRowMapper()); } @Override public List saveOrUpdate(String tableName, List datas) { hbaseTemplate.saveOrUpdates(tableName, datas); return datas; } }
5.编写application.properties
# Zookeeper 地址 spring.data.hbase.quorum=192.168.0.104:2181 # HBase 存储路径 spring.data.hbase.rootDir=hdfs://zccoder.com:9000/hbase/ # HBase 在 Zookeeper上的根节点名称 spring.data.hbase.nodeParent=/hbase
6.编写Application类
package com.myimooc.hbase.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } }
7.编写UserHbaseServiceImplTest类
package com.myimooc.hbase.demo.service; import com.alibaba.fastjson.JSON; import com.myimooc.hbase.demo.Application; import com.myimooc.hbase.demo.dto.User; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Mutation; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.util.Bytes; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.List; /** *
* 标题: 单元测试类
* 描述: 单元测试类
* * @author zc * @date 2018/06/22 */ @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,classes = Application.class) public class UserHbaseServiceImplTest { @Autowired private HbaseServiceservice; /** * 数据表名称 */ private String tableName; @Before public void init(){ tableName = "demo:user"; } @Test public void testFindByRow(){ System.out.println(JSON.toJSONString(service.findByRow(tableName,"root"))); } @Test public void testFindByStartEndRow(){ System.out.println(JSON.toJSONString(service.findByStartEndRow(tableName,"r","z"))); } @Test public void testSaveOrUpdate(){ List datas = new ArrayList<>(); Put put= new Put(Bytes.toBytes("root")); put.addColumn(Bytes.toBytes("b"),Bytes.toBytes("name"),Bytes.toBytes("imooc")); put.addColumn(Bytes.toBytes("b"),Bytes.toBytes("age"),Bytes.toBytes("18")); put.addColumn(Bytes.toBytes("b"),Bytes.toBytes("sex"),Bytes.toBytes("m")); put.addColumn(Bytes.toBytes("o"),Bytes.toBytes("phone"),Bytes.toBytes("123456789")); put.addColumn(Bytes.toBytes("o"),Bytes.toBytes("address"),Bytes.toBytes("北京市朝阳区")); datas.add(put); // Delete delete = new Delete(Bytes.toBytes("root")); // datas.add(delete); List results = service.saveOrUpdate(tableName,datas); System.out.println(results); } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71392.html
摘要:时间年月日星期二说明本文部分内容均来自慕课网。返回对象不同返回持久化实体类对象返回代理对象。与缓存的关系不同只缓存,但不使用缓存查询缓存除外会使用缓存。 时间:2017年07月11日星期二说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:无 第一章:概述 1-1 概述 课程内容 了解缓存 掌握Hibernate一级缓存的使用 掌握H...
摘要:拦截器学习总结时间年月日星期六说明本文部分内容均来自慕课网。慕课网教学示例源码暂无。拦截器不依赖与容器,过滤器依赖与容器。拦截器只能对请求起作用,而过滤器则可以对几乎所有的请求起作用。共性问题在拦截器中处理,可以减少重复代码,便于维护。 《SpringMVC拦截器》学习总结 时间:2017年2月18日星期六说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.co...
摘要:时间年月日星期日说明本文部分内容均来自慕课网。当对应的链表存在时,从左侧插入数据。从右侧插入数据。当系统在定时持久化之前出现宕机,还未来得及往硬盘写入数据,那数据就丢失了。当数据集过大时,可能会导致服务器停止几百毫秒甚至是秒钟。 时间:2017年05月21日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:无个人学习源码:https:...
阅读 985·2021-11-22 13:52
阅读 1430·2021-11-19 09:40
阅读 3072·2021-11-16 11:44
阅读 1227·2021-11-15 11:39
阅读 3843·2021-10-08 10:04
阅读 5279·2021-09-22 14:57
阅读 3085·2021-09-10 10:50
阅读 3156·2021-08-17 10:13