hbase复习和压缩算法

问题:
    存储在HDFS上的一个大文件有100T,怎么在实时的要求下,快速找出对应的record
    实时的增删改查  hbase   根据key 查找value  底层二进制编码 序列化和反序列化
    主键  列簇1 列簇2 。。。
    设计核心:跳表 + 布隆过滤器
    HBase : 数据库 ,底层数据存储在HDFS

    Hive只要支持 select   查询延迟很高   底层的执行引擎,其实就是一个分布式的计算引擎
    hbase的最大特性就是解决根据key进行实时查询的需求,一般来说,不适合做关联查询

怎么解决大量数据集中的单条记录的实时增删改查?

     1、第一,数据要排序, 二分查找

     2、第二,因为数据集特别大,所以,需要分片。   分而治之

以上这两个特点结合起来,就是一个数据结构:  跳表

        表的所有数据按照rowkey进行字典排序的。

        如果按照rowkey进行查询,快速的定位到用户要查询的rowkey到底在最底层的那个小文件中,最后再去扫描这个小文件

配合使用布隆过滤器    怎么实现的?

提前在每一个小文件(region)设置好了一个布隆过滤器,那么根据布隆过滤器的特点。它能快速的判断,某个value是否在这个集合中。

    优点:快速判断一个元素是否在这个集合(region)中
    缺点:存在误判: 如果返回true,有可能是假的。 如果返回false,那么一定是不存在

    布隆过滤器会占用额外的磁盘空间,底层数据文件,肯定不止1G 

hbase的表结构:

    1、表    和普通的mysql中的表的概念是一样的

    2、rowkey   所有的数据,在进行查询的时候,一般来说,都是根据rowkey
                但是也可以使用过滤器,去扫描整张表的数据

            1、hbase的表数据的查询方式:

                直接根据rowkey
                根据rowkey的范围range
                全表扫描
        
            2、rowkey的长度限制问题

            不能超过64KB, 最好在10-100byte之间  最好16,最好是8的倍数

    3、列簇

        一组key组成一个列簇: 具有相同IO特性

        查询其中一个key1的时候一般来说,都会查询另外一个key2
        所以说key1和key2具有相同的IO特性

        经验推荐: 虽然说在部分场景中,有可能存储的数据,就具有多个不同的IO特性,应该要存储成为多个不同的列簇
        但是根据经验来判断,最好使用一个列簇

    4、列

        真正的key-value中的key就是列
        插入的key-value到底应该存储在哪个列簇中,是在插入的时候,一定要指定的

    5、时间戳

        作用:就相当于一个key_value中的value的多个版本的版本号

        两种管理方式:

        1、保存最近的最新的N个版本
        2、保存一定时间范围内的所有数据, 如果某个版本数据超过时限要求,那么会被hbase的服务器自动删除的。

hbase的架构:
    首先hbase集群有三种角色:
        client
        server : 主从架构
              主节点:hmaster
              从节点:hregionserver    
    hbase依赖于:

        1、hdfs做数据存储
        2、zookeeper做协调(解决SPOF, 存储寻址入口)

        hmaster没有参与真正的数据的查询和插入的处理(主要用来管理hregionserver的状态,和所有的region的负载均衡)
    
    单点故障的问题,但是不迫切

        表示:hbase的主节点,可以在宕机了以后,整个hbase集群依然可以对外提供服务

        当前hbase中的每个region都会增长。增长到10G的大小的时候就会进行分裂

        分裂的标准:在hbase1.x以前,是256M
                    在hbase1.x开始,是10G
    
    分裂出来的两个region一般来说,hregionserver会汇报给hmaster,hmaster一般来说,都会寻找
    一个新的hregionserver来进行存储这分裂出来的两个region当中的一个


    原始数据表raw:所有hbase表都会有多个region
        .meta.:所有的这些region的映射信息都存储在第二级表中。映射信息过多,造成第二级表也会进行分裂,形成多个region
        -root-:第二级表的多个region也被映射起来,存储在第一级表-root-中

    最终的核心要点: -root-这个表中的数据量不管多大,都不会进行分裂

    找到-root-这个表的那个唯一region在哪里,就能找到数据是哪些region

    zookeeper给hbase存储寻址入口:
        其实就是存储了-root-表的唯一region在哪个hregionserver中  但是会经常有迁移操作

    hbase的寻址机制

        region就是一张hbase表的逻辑抽象单位

        一个region并不是一个单独的文件, 在HDFS上的目录树中体现为一个文件夹

        regionserver:

            1、一个regionserver中的所有region都是来自于一个表么?    不是的。

            2、一个表的所有region都存储在一个表中么?     不是的。

            所有表的所有region是进行负载均衡的处理之后存储在整个hbase集群

hbase的启动前提:

    启动zk
    启动hdfs
        hdfs dfsadmin -safemode 
        hdfs haadmin -getServiceState nn1/nn2

HBase的shell操作:

    1、进入客户端:hbase shell

    2、查看当前hbase的shell命令有那些:help

    3、通过查看帮助文档可以得知;
        
        a、如果哪个命令不会使用: help "command"
        b、如果不知道具体有那些组或者组中的命令的名称:  help "command_group"

2、关于库

   关于表(创建create,查看表列表list。查看表的详细信息desc,删除表drop,清空表truncate,修改表的定义alter)

   关于数据的操作(增put,删delete,查get + scan,  改==变相的增加

    drop  ==   清空数据truncate + 删除表定义

    hbase的表一经创建之后。那么列簇的名字就不能更改了。

    可以通过先删除列簇,然后添加回来,但是你必须要承受  损失这个列簇 

修改:alter

    get :  rowkey

    scan :  不用指定rowkey

    hbase的java api操作:

HDFS当中的核心API :2 个

HBase当中的核心API :13个

    HBaseConfiguration   配置信息
    Connection
    HBaseAdmin/Admin     管理员
    
    HTable    整个表的抽象信息
    HColumnDescriptor  列的描述信息
    HTableDescriptor   列簇的描述信息

    Put
    Delete
    Get
    Scan

    KeyValue
    Cell

    Result
    ResultScanner
    Filter

过滤器
分页操作

分享的面试的问题总结:

1、hbase的调优。 MR的调优,  Hive的调优,  Spark调优。

    负载不均衡的问题/数据倾斜的问题

2、集群架构和节点数,数据量的问题

    推导公式: 方便你们自己去模拟和构造数据量

    30TB

    每条记录的长度
    总记录数
    数据记录的总天数

3、数据仓库   Hive  数据仓库

    hive的执行引擎:MR,  Hive2推荐使用Spark
    数据支撑:HDFS
    也有可能来自于HBase    Hive和HBase的整合
    ZooKeeper
    Hive的使用简单: 就是编写SQL 

4、Spark中的一个面试题
    跟kafka做整合的问题
    Spark Streaming + kafka 
    消费数据有三种模式:
        1、至少一次
        2、最多一次
        3、有且仅有一次   必须依赖 zookeeper 

往hbase中插入数据的五种方式:

    1、table.put(put)
    2、table.put(puts)    
    3、MR
    4、多线程多客户端并发写入
    5、bulkload

    其实是使用MR程序提前生成好HFile

    最基本的数据插入:

        1、首先往WAL Log中记录日志数据

        2、把数据更新到内存

        3、内存达到一定的阈值之后,就会flush数据到磁盘HFile

        4、HfILE达到一定数量之后,就会进行合并。 StoreFile


hbase的底层原理:

    1、hbase的各种核心概念(表)

        key-value数据库(rowkey,  hashmap)
        一张四维表格
        rowkey        行健(全局字典排序,  不能超过64KB, 最好10-100字节)
        列簇            就是包含了一组具有相同IO特性的一组key
        列        面向列,等同的任务是mysql表中的列
        值        hbase表中的所有数据,都是按照字节数组存储
        时间戳        控制hbase中的真正的key-valeu中的vlaue的版本的

        get 'student','rk01','cf1:age',ts
    
    2、hbase的组织架构

        hbase的集群特点:  主从架构

        1、hmaster        管理节点   主节点
        2、hregionserver    工作节点   从节点
        3、zookeeper       服务协调(选举master,  存储寻址入口:-root-这个表的那个唯一的region的唯一region在哪个regionserver)
        4、hdfs           分布式的文件系统,用来给hbase做底层的数据存储支撑的。
            /hbase126/data/default/user_info/846ce4c6701699c71bf4711a9a88e8d8/base_info/55378f109cbd4092bc59bd5b34c3afb7
            55378f109cbd4092bc59bd5b34c3afb7: storefile    hfile

        5、mapreduce        非必须组件
        6、client           给用户提供一个终端工具可以操作hbase(发送请求读写hbase库)

    
    3、hbase的shell操作

        hbase shell
        help
        help 'get'  || help 'ddl'

    4、api
        con.getAdmin()
        con.getTable()
        Put Delete Get Scan 

        get :  Result
        Scan : ResultScanner

        Cell   由  rowkey + cf + key + ts 唯一确定的一个格子 value   KeyValue
        分页过滤器
        整合mapreduce : TableMapRedcueUtil  (initTableMapperJob  initTableReducerJob)
        bulkload方式往hbase表中插入数据 (没有记录 HLog)

habse的底层原理:
    
    在hbase的文件组织形式上,一定要记住:
        一个集群会有多个regionserver
        每一个regionserver就是用来去管理master分配给它的region
        每一个regionserver中管理的所有的region是有可能来自于多个不同的table的
        每一个regionserver中的所有region在进行数据插入的时候是会被记录日志的。

    client:
        存储了-root-这张表的那个唯一的region的所有数据会被缓存在当前这个resgionserver中的内存中

        client会缓存第一次查询到的  -root- 这张表的那个唯一的region是存储在哪个regoinserver中的位置信息

            client第一次请求,没有办法,只能通过请求zookeepr得到-root-的位置
            client第N次请求的时候,直接从缓冲中保存的-root-的位置地址,直接请求即可    
            有可能会出现缓存失效, 再次重新请求zk即可

    hbase的regionserver构造:
        1、client发送的 put  delete  其实在底层的数据文件中,都是  追加的形式
        2、一个store就是就是一个region中的一个列簇
        一个store由 一个memestore和多个storeFile(HFile)
        为什么这么构造?
           1、解决效率问题,如果都是在内存中进行查询和插入,效率高
           2、解决安全问题,因为内存存在着掉电丢失数据的情况,数据存磁盘就不害怕数据的丢失
        WAL 

            1、首先记录日志
            2、然后更新请求数据到内存
            3、当内存上涨到一定限制时,所以需要溢写数据到磁盘
            4、溢出到磁盘的文件有可能会有很多,会进行合并

                1、为了删除无效数据
                2、为了保证全局有序

合并:

    简单的说,就是把rowkey相同的所有KeyValue对象收集到一起,进行合并,按照key Type进行操作
    首先判断是否有相同的key(行健,列簇,列,ts)对象,判断key type 同时也会判断事件戳
    add  delete   ==== 最终抵消    delete add   ===== 不会不出现
    只有刚溢写出来的文件才会由 delete的keytype出现

hbase的数值组织形式:

    1、表
    2、region
    3、store
    4、hfile
    5、data block    ---->   data
    6、keyvalue
    7、kv(rowkey, cf, qualifier, value, ts)

缓存淘汰算法:
    FIFO
    LRU   least  recently used
    LFU : least frequently used
    memcached  redis
    每一个列簇中的属性信息有很多。其中有一项叫做;
    BloomFilter = Row

    如果溢写出来一个HFile之后,触发了 compact 操作:
    这个 compact 一定是  minor compact:
     compact : 小合并   大合并
major_compact 和 minor_compact 的区别:
minor_compact 仅仅合并小文件(HFile)    count(HFile) >= 3 就会触发  不会进行Put Delete数据的合并
                         清理的数据就是  设置了 TTL(time to live) 过期了的数据

major_compact 合并一个 region 内的所有文件
        把所有的小文件都合并成一个大文件:StoreFile  --- HDFS  ---- HFile

小合并自动执行
大合并必须手动执行  --  默认的配置是 --- 七天   ---- 一天

分裂  : 一个  region  一分为二

RS : 
    1、管理   master 分配给它的   region

    2、管理  region的  分裂

    3、管理  region 中的  storefile的合并

    4、其实每一个regionserver都是一个  HDFS 客户端

    RS  上线  和  下线


master:

    1、管理所有的  regionserver

    2、接收所有的regionserver的汇报,然后进行region的负载均衡

    3、维护hbase的元数据信息(namespace, table,column family)

    master可以宕机一段时间:

    1、受影响: 所有 master该做的事都没有机器做,所以,   元数据的修改操作统统不能做

    2、不受影响: 插入 和 查询不受影响。

    master的上线 和 下线


压缩算法的比较
以下是Google几年前发布的一组测试数据(数据有些老了,有人近期做过测试的话希望能共享出来):

Algorithm    % remaining    Encoding    Decoding
GZIP    13.4%    21 MB/s    118 MB/s
LZO    20.5%    135 MB/s    410 MB/s
Zippy/Snappy    22.2%    172 MB/s    409 MB/s

其中:

1)GZIP的压缩率最高,但是其实CPU密集型的,对CPU的消耗比其他算法要多,压缩和解压速度也慢;

2)LZO的压缩率居中,比GZIP要低一些,但是压缩和解压速度明显要比GZIP快很多,其中解压速度快的更多;

3)Zippy/Snappy的压缩率最低,而压缩和解压速度要稍微比LZO要快一些。

BigTable和HBase中压缩算法的选择
BigTable中采用的是Zippy算法,目标是达到尽可能快的压缩和解压速度,同时减少对CPU的消耗。

HBase中,在Snappy发布之前(Google 2011年对外发布Snappy),采用的LZO算法,目标和BigTable类似;在Snappy发布之后,建议采用Snappy算法(参考《HBase: The Definitive Guide》),具体可以根据实际情况对LZO和Snappy做过更详细的对比测试后再做选择。

实际项目中的实践经验
项目中使用clearspring公司开源的基数估计的概率算法:stream-lib,用于解决去重计算问题,如UV计算等,它的特点在于:

1)一个UV的计算,可以限制在一个固定大小的位图空间内完成(不同大小,对应不同的误差率),如8K,64K;

2)不同的位图可以进行合并操作,得到合并后的UV。

当系统中维护的位图越多的时候,不管是在内存中,还是在存储系统(MySQL、HBase等)中,都会占用相当大的存储空间。因此,需要考虑采取合适的算法来压缩位图。这里分为以下两类情况:

1)当位图在内存中时,此时压缩算法的选择,必须有尽可能快的压缩和解压速度,同时不能消耗过多CPU资源,因此,适合使用LZO或Snappy这样的压缩算法,做到快速的压缩和解压;

2)当位图存储到DB中时,更关注的是存储空间的节省,要有尽可能高的压缩率,因此,适合使用GZIP这样的压缩算法,同时在从内存Dump到DB的过程也可以减少网络IO的传输开销。
 

猜你喜欢

转载自blog.csdn.net/u014156013/article/details/81298562