大白话详解大数据HBase核心知识点,老刘真的很用心(3)

老刘目前为明年校招而努力,写文章主要是想用大白话把自己复习的大数据知识点详细解释出来,拒绝资料上的生搬硬套,做到有自己的理解!

01 HBase知识点(3)

 

第13点:HBase表的热点问题

什么是热点问题?

就是我们检索hbase的数据首先要通过rowkey来定位数据行,但是呢这里面就有一个问题,由于rowkey设计的问题,就会导致表的数据可能只分布在hbase集群中的一个或少数节点。

当大量客户端访问hbase集群这些数据时,就会造成少数RegionServer的读写请求过多,负载过大,而其他的RegionServer负载却很小,就造成了热点现象。

详细说说出现热点问题的原因?

① hbase中的数据是按字典序排序的,当大量连续的rowkey集中写在个别的region,各个region之间数据分布不均衡。

② 创建表时没有提前预分区,创建的表默认只有一个region,大量的数据写入当前的region。

③ 创建表已经提前预分区了,但设计的rowkey没有规律可循,设计的rowkey没有加散列字段。

热点问题的解决方案

预分区

预分区的目的让表的数据可以均衡的分散在集群中,而不是默认只有一个region分布在集群的一个节点上。

加盐

具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。

第14点:rowkey设计

在第13点已经说过rowkey设计不好,会出现热点问题。所有那rowkey到底该如何设计呢?

rowkey设计有三个原则,这个不是我定的,我看资料上这样写的。

首先是rowkey长度原则,它的设计建议尽可能短,又不能太短,否则rowkey之间的前缀重复的概率增大,因为rowkey按照字典序排序,这些数据会尽量的存储在一起。

其次是rowkey散列原则,就是给rowkey增加一些随机前缀,让rowkey尽量不一样,尽量避免出现热点问题。

最后是rowkey唯一原则,就是必须保持它唯一。

第15点:HBase的数据备份

老刘知道的HBase数据备份有两种,第一种是使用HBase提供的类把HBase中某张表的数据导出到HDFS,之后有需要就可以导出到HBase的表中。

① 从HBase表导出到HDFS中

hbase org.apache.hadoop.hbase.mapreduce.Export myuser /hbase_data/myuser_bak

② 有需要了,就在HBase中创建备份的目标表

create 'myuser_bak','f1','f2'

③ 再把HDFS上的数据导入到备份目标表

hbase org.apache.hadoop.hbase.mapreduce.Driver import myuser_bak /hbase_data/myuser_bak/

就这样第一种方法就讲完了,在讲讲第二种方法利用snapshot快照进行表的备份,网上资料说通过snapshot快照的方式实现HBase数据的迁移和拷贝是最为推荐的数据迁移方式,老刘对这个方法不是很懂,等以后在好好讲讲,这一次就先提一提,让大家有个印象。

第16点:HBase二级索引

为什么需要二级索引?

① 对于HBase而言呢,如果想精度定位到某行记录,唯一的方法是通过rowkey来查询,但是你不通过rowkey来查询数据,就必须进行全表扫描。对于较大的表,全表扫描的代价太大了,就需要另寻方法了。

很多情况下,我们需要从多个方面查询数据。例如,在定位某个学生的信息,可以通过姓名、身份证号、学号等不同方面来查询,但是把这么多方面的数据都放到rowkey中几乎不可能(业务的灵活性不允许,对rowkey长度的要求也不允许)。

所以需要secondary index(二级索引)来完成这件事。

② 也是为了让HBase的查询更加高效,比如使用非rowkey字段检索也能做到秒级响应,就可以需要在HBase上面构建二级索引。

那如何构建二级索引?

推荐用phoenix(菲尼克斯)构建二级索引,老刘简单讲讲phoenix的概念。

它创建索引有两种:

① 全局索引,适用于读多写少的业务场景。

使用全局索引在写数据的时候开销很大,因为所有对数据表的更新操作,都会引起索引表的更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。

在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。在默认情况下如果想查询的字段不是索引字段的话,索引表就不会被使用,也就是说不会有查询速度的提升。

② 本地索引,适用于写操作频繁以及空间受限制的场景。

与全局索引一样,Phoenix会自动判定在进行查询的时候是否使用索引。

使用本地索引时,索引数据和数据表的数据存放在相同的服务器中,这样避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。

使用本地索引的时候即使查询的字段不是索引字段,索引表也会被使用,这会带来查询速度的提升,这点跟全局索引不同。

第17点:HBase的namespace

namespace的概念

在HBase中,namespace就相当于关系型数据库中的database,它是指对一组表的逻辑分组,就是同一组中的表有类似用途的意思。那就相当于说我们利用namespace可以很方便对表在业务上进行划分。

namespace基本操作

创建namespace
hbase>create_namespace 'nametest'  

查看namespace
hbase>describe_namespace 'nametest'  

列出所有namespace
hbase>list_namespace

在namespace下创建表
hbase>create 'nametest:testtable', 'fm1' 

查看namespace下的表
hbase>list_namespace_tables 'nametest'  

删除namespace
hbase>drop_namespace 'nametest'

第18点:HBase的数据版本的确界以及TTL

在HBase当中,我们可以为数据设置上界和下界,这个其实就是定义数据的历史版本保留多少个,我们通过自定义历史版本保存的数量,可以实现数据多个历史版本的数据查询

版本的下界

默认的版本下界是0,即禁用。row版本使用的最小数目是与生存时间(TTL Time To Live)相结合的,并且我们根据实际需求可以有0或更多的版本,使用0,即只有1个版本的值写入cell。

版本的上界

之前默认的版本上界是3,也就是一个row保留3个副本,现版本已默认为1。

数据的TTL

在实际工作当中经常会遇到有些数据过了一段时间我们可能就不需要了,那么这时候我们可以使用定时任务去定时的删除这些数据
或者我们也可以使用Hbase的TTL(Time To Live)功能,让我们的数据定期的会进行清除。

下面老刘将写代码来设置数据的确界以及设置数据的TTL:

public class HBaseVersionsAndTTL {
    public static void main(String[] args) throws IOException {
    //获得连接
        Configuration configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.quorum", "node01:2181,node02:2181,node03:2181");
    
    //创建连接对象
        Connection connection = ConnectionFactory.createConnection(configuration);
    
    //建表的时候用Admin
        Admin admin = connection.getAdmin();

        if(!admin.tableExists(TableName.valueOf("version_hbase"))) {
      //添加表名信息
            HTableDescriptor version_hbase = new HTableDescriptor(TableName.valueOf("version_hbase"));
      
            HColumnDescriptor f1 = new HColumnDescriptor("f1");
            //最大版本、最小版本、TTL
            f1.setMinVersions(3);
            f1.setMaxVersions(5);
            f1.setTimeToLive(30);//30s

            version_hbase.addFamily(f1);

            admin.createTable(version_hbase);
        }

        //插入数据
        Table version_hbase = connection.getTable(TableName.valueOf("version_hbase"));
    
        for(int i = 0; i < 6; i++) {
           Put put = new Put("001".getBytes());
            put.addColumn("f1".getBytes(), "name".getBytes(), ("zhangsan" + i).getBytes());
           version_hbase.put(put);
        }

        //查询
        Get get = new Get("001".getBytes());
    //设置最大版本
        get.setMaxVersions();

        Result result = version_hbase.get(get);

        Cell[] cells = result.rawCells();

        for(Cell cell: cells) {
            System.out.println(Bytes.toString(CellUtil.cloneValue(cell)));
        }

        //关闭连接
        admin.close();
        version_hbase.close();
        connection.close();
    }
}

02 HBase总结

好啦,大数据HBase的知识点总结的差不多了,内容比较多,大家需要仔细理解,争取做到用自己的话把这些知识点讲述出来。

最后,如果觉得有哪里写的不好或者有错误的地方,可以联系公众号:努力的老刘,进行交流哦!希望能够对大数据开发感兴趣的同学有帮助,希望能够得到同学们的指导。

 

posted @ 2020-12-05 14:40  大数据老刘  阅读(335)  评论(0编辑  收藏  举报