资讯专栏INFORMATION COLUMN

慕课网_《HBase 存储原理剖析》学习总结

trigkit4 / 405人阅读

摘要:慕课网存储原理剖析学习总结时间年月日星期一说明本文部分内容均来自慕课网。每一列簇包含多个列列标识符。每一列数据包含了版本和值版本。

慕课网《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
3-2 存储目录

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
第四章:存储设计 4-1 存储思想

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 HbaseService service; /** * 数据表名称 */ 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

相关文章

  • 课网_《Hibernate缓存策略》学习总结

    摘要:时间年月日星期二说明本文部分内容均来自慕课网。返回对象不同返回持久化实体类对象返回代理对象。与缓存的关系不同只缓存,但不使用缓存查询缓存除外会使用缓存。 时间:2017年07月11日星期二说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:无 第一章:概述 1-1 概述 课程内容 了解缓存 掌握Hibernate一级缓存的使用 掌握H...

    codergarden 评论0 收藏0
  • 课网_《SpringMVC拦截器》学习总结

    摘要:拦截器学习总结时间年月日星期六说明本文部分内容均来自慕课网。慕课网教学示例源码暂无。拦截器不依赖与容器,过滤器依赖与容器。拦截器只能对请求起作用,而过滤器则可以对几乎所有的请求起作用。共性问题在拦截器中处理,可以减少重复代码,便于维护。 《SpringMVC拦截器》学习总结 时间:2017年2月18日星期六说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.co...

    calx 评论0 收藏0
  • 课网_《Redis入门》学习总结

    摘要:时间年月日星期日说明本文部分内容均来自慕课网。当对应的链表存在时,从左侧插入数据。从右侧插入数据。当系统在定时持久化之前出现宕机,还未来得及往硬盘写入数据,那数据就丢失了。当数据集过大时,可能会导致服务器停止几百毫秒甚至是秒钟。 时间:2017年05月21日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:无个人学习源码:https:...

    leanxi 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<