HBase详细解读之一

1、HBase简介

1、Hbase是什么?
	Hbase是分布式存储海量数据的Nosql数据库
2、Hbase的应用场景: 实时 
3、数据模型
	1、Table: 数据存储形式
	2、Region: table的一个分段,region保存在regionserver上面
	3、Store: store的个数与列簇的个数一致
	4、rowkey: hbase的数据的主键。
		数据在hbase中是有序的,按照rowkey的字典序进行排序
	5、列簇: hbase的表结构的一部分[相当于mysql的字段]
	6、列限定符: hbase数据的一部分
	7、Column: 列簇:列限定符
	8、Cell: rowkey+列簇+列限定符+时间戳
	9、Namespace: 命名空间,相当于mysql的库
4、架构
	1、Master
		职责:
			1、负责监控Regionserver,一旦regionserver宕机,会迁移数据到其他活着的regionserver上面
			2、负责表结构的变更
	2、RegionServer
		职责:
			1、负责数据的操作[增删改查]
			2、负责region的split、compact
		Region: 表的一个分段
			Store: store的个数与列簇的个数一致
				memstore: 是一块内存区域,数据在写入hbase的时候是写入memstore中,memstore达到一定的阈值之后会进行flush,每次flush都会生成一个storeFile
				storeFile: memstore flush生成
					storeFile最终是以Hfile这种文件格式保存在HDFS
		HLOG: 每个regionserver只有一个HLOG,数据在写入memstore之前会先写入HLOG,当memstore进行flush的时候,HLOG会删除预写日志中该memstore的数据
	3、zookeeper: 保存元数据的位置,master监听regionserver也是借助zookeeper

2、Hbase安装以及shell使用

1、Namespace相关
	1、创建Namespace: create_namespace '命名空间名称'
	2、删除Namespace: drop_namespace '命名空间名称'
		删除命名空间的时候,必须先删除命名空间下所有表
	3、查看命名空间下所有表: list_namespace_tables '命名空间名称'
	4、查看所有的命名空间: list_namespace
2、Table相关
	1、创建表: create '表名','列簇名1',...
	2、删除表:
		1、禁用表: disable '表名'
		2、删除表: drop '表名'
	3、查看所有表: list
	4、查看表的详情信息: describe '表名'
	5、创建表的时候指定VERSION:
		create '表名',{NAME=>'列簇名',VERSIONS=>'版本数'}
3、数据相关
	1、插入数据: put '表名',rowkey,'列簇:列限定符','值'
	2、查看数据
		1、根据rowkey查询数据
			1、查询整行数据:get '表名',rowkey
			2、查询某个列簇的数据: get '表名',rowkey,'列簇'
			3、查询某个列的数据: get '表名',rowkey,'列簇:列限定符'
		2、扫描
			1、查询整表数据: scan '表名'
			2、查询某个列簇的数据: scan '表名',{COLUMNS=>'列簇'}
			3、查询某个列的数据: scan '表名',{COLUMNS=>'列簇:列限定符'}
			4、查询某几个版本的数据: scan '表名',{COLUMNS=>'列簇:列限定符',VERSIONS=>'版本数'}
	3、清空表数据: truncate '表名'
	4、统计表条数: count '表名'

3,HBase API

package com.atguigu;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.ColumnRangeFilter;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.filter.SubstringComparator;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class HBaseDemo {
    private Configuration configuration;
    private Connection connection;
    private Admin admin;
// ================================================资源的创建和释放===========================================

    /**
     * 初始化 配置信息
     */
    @Before
    public void init() {
        configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.quorum", "hadoop102:2181,hadoop103:2181,hadoop104:2181");
        try {
            connection = ConnectionFactory.createConnection(configuration);
            admin = connection.getAdmin();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 关闭资源
     */
    @After
    public void close() {
        if (admin != null) {
            try {
                admin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    //================================================================命名空间有关的操作=================================

    /**
     * 创建命名空间
     */
    @Test
    public void createNameSpace() throws Exception {
        // 获取HBase的连接
        final Configuration configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.quorum", "hadoop102:2181,hadoop103:2181,hadoop104:2181");
        final Connection connection = ConnectionFactory.createConnection(configuration);
        // 创建Admin
        final Admin admin = connection.getAdmin();
        // 创建命名空间
        final NamespaceDescriptor bigHBase = NamespaceDescriptor.create("bigHBase5").build();
        admin.createNamespace(bigHBase);
        // 关闭连接
        admin.close();
        connection.close();
    }

    /**
     * 显示所有的命名空间
     *
     * @throws Exception
     */
    @Test
    public void listNameSpace() throws Exception {
        // 获取hbase的连接
        final Configuration configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.quorum", "hadoop102:2181,hadoop103:2181,hadoop104:2181");
        final Connection connection = ConnectionFactory.createConnection(configuration);
        // 创建admin
        final Admin admin = connection.getAdmin();
        //显示所有的命名空间
        final NamespaceDescriptor[] namespaceDescriptors = admin.listNamespaceDescriptors();
        for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
            System.out.println(namespaceDescriptor.getName());
        }
        // 关闭连接
        admin.close();
        connection.close();
    }

    /**
     * 查看某个命名空间所有表
     *
     * @throws Exception
     */
    @Test
    public void listNameSpaceTablesByNameSpace() throws Exception {
        // 获取HBase的连接
        final Configuration configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.quorum", "hadoop102:2181,hadoop103:2181,hadoop104:2181");
        final Connection connection = ConnectionFactory.createConnection(configuration);
        // 创建admin
        final Admin admin = connection.getAdmin();
        // 获取指定命名空间下的表信息
        final List<TableDescriptor> tableDescriptors = admin.listTableDescriptorsByNamespace("bigHBase".getBytes());
        for (TableDescriptor tableDescriptor : tableDescriptors) {
            final TableName tableName = tableDescriptor.getTableName();
            System.out.println(new String(tableName.getName()));
            System.out.println(tableName.getQualifierAsString());

        }
        // 关闭资源
        admin.close();
        connection.close();
    }

    /**
     * 删除命名空间 要求该命名空间没有表,
     * 有的话 先删除所有的表,然后再删除表
     *
     * @throws IOException
     */
    @Test
    public void dropNameSpace() throws IOException {
        // 获取 命名空间所有的表
        final List<TableDescriptor> tableDescriptors = admin.listTableDescriptorsByNamespace("bigHBase5".getBytes());
        for (TableDescriptor tableDescriptor : tableDescriptors) {
            // 禁用表
            admin.disableTable(tableDescriptor.getTableName());
            // 删除表
            admin.deleteTable(tableDescriptor.getTableName());
        }
        // 删除命名空间
        admin.deleteNamespace("bigHBase5");

    }

    //=====================================对表的操作=============================================================

    /**
     * 创建表 create "命名空间:表名","列族"
     *
     * @throws IOException
     */
    @Test
    public void createTable() throws IOException {
        // 创建表
        // create 表名 列族...
        // 创建列族的描述
        final ColumnFamilyDescriptor base_ifo = ColumnFamilyDescriptorBuilder.newBuilder("base_ifo".getBytes()).build();
        final ColumnFamilyDescriptor extra_info = ColumnFamilyDescriptorBuilder.newBuilder("extra_info".getBytes()).build();
        //  创建表的描述
        final TableDescriptor build = TableDescriptorBuilder.newBuilder(TableName.valueOf("person2"))
                .setColumnFamily(base_ifo)
                .setColumnFamily(extra_info)
                .build();
        //  预分区
        final byte[][] splitKeys = {"10".getBytes(), "20".getBytes(), "30".getBytes()};
        admin.createTable(build,splitKeys);
        // 创建表
        admin.createTable(build);
        //关闭资源
    }

    /**
     * 修改列族 需要注意的是:此修改会覆盖原来的列族,所以需要把之前的列族也要重新设置一次
     *
     * @throws IOException
     */
    @Test
    public void alterTable() throws IOException {
        //  修改extra_info列族的版本数

        // 1 创建列族的描述
        final ColumnFamilyDescriptor base_ifo = ColumnFamilyDescriptorBuilder.newBuilder("base_ifo".getBytes())
                .setMinVersions(2)
                .setMaxVersions(2).build();
        final ColumnFamilyDescriptor extra_info = ColumnFamilyDescriptorBuilder.newBuilder("extra_info".getBytes())
                .setMinVersions(2)
                .setMaxVersions(2)
                .build();
        // 新增一个列族
        final ColumnFamilyDescriptor address_info = ColumnFamilyDescriptorBuilder
                .newBuilder("address_info".getBytes()).build();
        // 创建表的描述 并关联列族描述
        final TableDescriptor build = TableDescriptorBuilder.newBuilder(TableName.valueOf("bigHBase:person"))
                .setColumnFamily(base_ifo)
                .setColumnFamily(extra_info)
                .setColumnFamily(address_info)
                .build();

        // 修改表结构
        admin.modifyTable(build);

    }

    /**
     * 显示所有的表
     *
     * @throws IOException
     */
    @Test
    public void listTable() throws IOException {
        final TableName[] tableNames = admin.listTableNames();
        for (TableName tableName : tableNames) {
            System.out.println(new String(tableName.getName()));
        }
    }

    /**
     * 删除表
     *
     * @throws IOException
     */
    @Test
    public void dropTable() throws IOException {
        // 禁用表
        admin.disableTable(TableName.valueOf("bigHBase:person2"));
        // 删除表
        admin.deleteTable(TableName.valueOf("bigHBase:person2"));
    }

    /**
     * 插入数据
     *
     * @throws IOException
     */
    @Test
    public void put() throws IOException {
        // 创建Table对象
        final Table table = connection.getTable(TableName.valueOf("student"));
        //插入数据 命令空间:表名 rowKey 列族:列限定名 值
        //  设置rowKey
        final Put put = new Put("1001000".getBytes());
        // 设置列族 列限定名 值
        put.addColumn("base_ifo".getBytes(), "name".getBytes(), "李四".getBytes());
       // put.addColumn("base_ifo".getBytes(), "age".getBytes(), Bytes.toBytes(20));
        put.addColumn("base_ifo".getBytes(), "age".getBytes(), "26".getBytes());
        put.addColumn("extra_info".getBytes(), "class".getBytes(), ("2523").getBytes());
      //  put.addColumn("address_info".getBytes(), "address".getBytes(), ("shenzhen").getBytes());
        // 插入数据
        table.put(put);
        // 关闭table
        table.close();
    }

    /**
     * 批量插入数据
     *
     * @throws IOException
     */
    @Test
    public void putList() throws IOException {
        // 创建表table对象
        final Table table = connection.getTable(TableName.valueOf("person2"));
        // 声明List对象 用于存放put对象 对应一个rowKey
        ArrayList<Put> list = new ArrayList<>();
        Put put = null;
        for (int i = 11; i <= 20; i++) {
            //  设置 rowKey
            put = new Put(("100" + i).getBytes());
            // 设置列族,列限定名 值
            put.addColumn("base_ifo".getBytes(), "name".getBytes(), ("zhansan-" + i).getBytes());
            //put.addColumn("base_ifo".getBytes(), "age".getBytes(), Bytes.toBytes(20 + i));
            put.addColumn("base_ifo".getBytes(), "age".getBytes(), ((20+i)+"").getBytes());
            put.addColumn("extra_info".getBytes(), "class".getBytes(), ("2025" + i).getBytes());
           // put.addColumn("address_info".getBytes(), "address".getBytes(), ("shenzhen" + i).getBytes());
            // 插入数据
            table.put(put);
        }
        // 关闭Table对象
        table.close();

    }

    // 通过rowKey查询整行数据
    @Test
    public void getValueByRowKey() throws IOException {
        // 创建table对象
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        // 创建get对象 并设置要查询那个rowKey
        final Get get = new Get("1000".getBytes());
        // 查询数据,返回一行数
        final Result result = table.get(get);
        // 获取cell对象,每一行都有多个cell
        final List<Cell> cells = result.listCells();
        // 遍历cells 显示每个一个cell对象的值
        for (Cell cell : cells) {
            // 一个cell 由 rowKey+列族+列限定符+时间戳+值组成
            // 由rowKey+列族+列限定符+时间戳确定

            // 获取rowKey
            final String rowKey = new String(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
            // 获取列族
            final String family = new String(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
            // 获取列限定符
            final String qualifier = new String(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
            // 获取时间戳
            final long timestamp = cell.getTimestamp();

            // 获取值 value 需要判断一下 值的类型
            if ("base_ifo".equals(family) && "age".equals(qualifier)) {
                int value = Bytes.toInt(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
            } else {
                String value = new String(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
            }
        }
        // 关闭table对象
        table.close();
    }

    /**
     * 根据rowKey和列族获取 cell
     *
     * @throws IOException
     */
    @Test
    public void getValueByRowKeyAndQualifier() throws IOException {
        // 创建table对象
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        // 创建get对象 并设置要查询那个rowKey
        final Get get = new Get("1001000".getBytes());
        // 设置单个列族
        get.addFamily("extra_info".getBytes());
        get.addFamily("base_ifo".getBytes());
        // 设置某个列族的某个列限定符
        get.addColumn("extra_info".getBytes(), "class".getBytes());
        // 获取结果
        final Result result = table.get(get);
        final List<Cell> cells = result.listCells();
        // 遍历cells 显示每个一个cell对象的值
        for (Cell cell : cells) {
            // 一个cell 由 rowKey+列族+列限定符+时间戳+值组成
            // 由rowKey+列族+列限定符+时间戳确定

            // 获取rowKey
            final String rowKey = new String(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
            // 获取列族
            final String family = new String(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
            // 获取列限定符
            final String qualifier = new String(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
            // 获取时间戳
            final long timestamp = cell.getTimestamp();

            // 获取值 value 需要判断一下 值的类型
            if ("base_ifo".equals(family) && "age".equals(qualifier)) {
                int value = Bytes.toInt(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
            } else {
                String value = new String(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
            }
        }
        // 关闭table对象
        table.close();

    }

    /**
     * 批量查询
     *
     * @throws IOException
     */
    @Test
    public void getBatch() throws IOException {
        final Table table = connection.getTable(TableName.valueOf("person2"));

        // 声明一个list存储get
        List<Get> list = new ArrayList<>();
        Get get = null;
        for (int i = 11; i <= 20; i++) {
            // 创建get对象,并指定rowKey
            get = new Get(("100" + i).getBytes());
            get.addFamily("base_ifo".getBytes());
            list.add(get);
        }
        // 多条数据
        final Result[] results = table.get(list);
        // 遍历得到多条记录
        for (Result result : results) {
            final List<Cell> cells = result.listCells();
            for (Cell cell : cells) {
                final String rowKey = new String(CellUtil.cloneRow(cell));
                final String family = new String(CellUtil.cloneFamily(cell));
                final String qualifier = new String(CellUtil.cloneQualifier(cell));
                final long timestamp = cell.getTimestamp();
                if ("age".equals(family) && "base_ifo".equals(family)) {
                    final int value = Bytes.toInt(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                } else {
                    String value = new String(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                }
            }
        }
        // 关闭资源
        table.close();
    }

    /**
     * 指定RowKey删除一行数据
     * @throws IOException
     */
    @Test
    public void deleteByRowKey() throws IOException {
        // 获取table对象
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        // 创建delete对象 指定删除的rowKey
        final Delete delete = new Delete("1000".getBytes());
        // 删除
        table.delete(delete);
        //关闭资源
        table.close();
    }

    /**
     * 批量删除数据
     * @throws IOException
     */
    @Test
    public void deleteBatch() throws IOException {
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        ArrayList<Delete>list = new ArrayList<>();
        Delete delete=null;
        for (int i =3; i <= 7; i++) {
            delete=new Delete(("100"+i).getBytes());
            list.add(delete);
        }
        table.delete(list);

        //
        table.close();
    }

    //==================================================scan扫描数据===================================================================

    /**
     * 使用scan全局扫描
     *
     * @throws IOException
     */
    @Test
    public void getValueByScan() throws IOException {
        // 1,获取table对象,并指定要操作那个命名空间那个table表
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        //  2,查询数据
        // 查询全部的数据
        Scan scan = new Scan();
        // 获得数据集合
        final ResultScanner results = table.getScanner(scan);
        // 3,展示数据
        // 把集合转为iterator类型
        final Iterator<Result> iterator = results.iterator();
        while (iterator.hasNext()) {
            // 遍历获取每行数据
            final Result res = iterator.next();
            // 得到每行的cell=rowKey+列族+列限定符+时间戳+value
            final List<Cell> cells = res.listCells();
            for (Cell cell : cells) {
                final byte[] familyByte = CellUtil.cloneFamily(cell);
                final String family = new String(familyByte);
                final String rowKey = new String(CellUtil.cloneRow(cell));
                final String qualifier = new String(CellUtil.cloneQualifier(cell));
                final long timestamp = cell.getTimestamp();
                if ("age".equals(family) && "base_ifo".equals(family)) {
                    final int value = Bytes.toInt(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                } else {
                    String value = new String(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                }
            }
        }
        // 4,关闭
        table.close();
    }

    /**
     * 使用scan指定family查询数据
     * @throws IOException
     */
    @Test
    public void  getValueByScanFamily() throws IOException {
        // 1获取table 并指定那个命名空间那个表
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));

        // 查询数据
        //  创建scan
        Scan scan=new Scan();
        // 设置列族
        scan.addFamily("base_ifo".getBytes());
        // 获取数据
        final ResultScanner scanner = table.getScanner(scan);
        // 展示数据
        // 把结果集转为iterator
        final Iterator<Result> iterator = scanner.iterator();
        while (iterator.hasNext()){
            // 获取一条记录
            final Result result = iterator.next();
            // 获取cell集合
            final List<Cell> cells = result.listCells();
            // 遍历cells 获取cell的组成信息
            for (Cell cell : cells) {
                final String rowKey = new String(CellUtil.cloneRow(cell));
                final String family = new String(CellUtil.cloneFamily(cell));
                final String qualifier = new String(CellUtil.cloneQualifier(cell));
                final long timestamp = cell.getTimestamp();
                if ("age".equals(family) && "base_ifo".equals(family)) {
                    final int value = Bytes.toInt(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                } else {
                    String value = new String(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                }
            }
        }
        // 4 关闭资源
        table.close();

    }

    // =====================================================过滤器=================================================================

    /**
     * 根据值来查询数据
     * 例如 select * from xx where age=25
     */
    @Test
    public void filterByValue() throws IOException {
        // 1获取table对象 并指定那个命名空间那个表
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        // 2 查询数据
        // 2.1 创建scan
        Scan scan=new Scan();
//        // 2.2 根据value进行过滤,只显示单个cell
//        BinaryComparator comparator=new BinaryComparator(Bytes.toBytes(25));
//        final ValueFilter valueFilter = new ValueFilter(CompareOperator.EQUAL, comparator);
//        scan.setFilter(valueFilter);

        // 根据vlaue进行过滤,显示整行数据 age=25的那一行数据全部查询出来
        final SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter("base_ifo".getBytes(), "age".getBytes(), CompareOperator.EQUAL, Bytes.toBytes(25));
        scan.setFilter(singleColumnValueFilter);
        final ResultScanner scanner = table.getScanner(scan);
        // 展示数据
        final Iterator<Result> iterator = scanner.iterator();
        while (iterator.hasNext()){
            // 获取一条记录
            final Result result = iterator.next();
            // 获取cell集合
            final List<Cell> cells = result.listCells();
            // 遍历cells 获取cell的组成信息
            for (Cell cell : cells) {
                final String rowKey = new String(CellUtil.cloneRow(cell));
                final String family = new String(CellUtil.cloneFamily(cell));
                final String qualifier = new String(CellUtil.cloneQualifier(cell));
                final long timestamp = cell.getTimestamp();
                if ("age".equals(family) && "base_ifo".equals(family)) {
                    final int value = Bytes.toInt(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                } else {
                    String value = new String(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                }
            }
        }
        // 4 关闭资源
        table.close();

    }

    /**
     * 实现模糊查询
     * select * form xx where name like "%5%"
     * @throws IOException
     */
    @Test
    public void filterByLike() throws IOException {
        // 1 获取table对象
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        Scan scan=new Scan();
        // 查询整行的数据
        final SubstringComparator comparator = new SubstringComparator("-5");
        final SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter("base_ifo".getBytes(), "name".getBytes(), CompareOperator.EQUAL, comparator);
        scan.setFilter(singleColumnValueFilter);
        final ResultScanner scanner = table.getScanner(scan);
        final Iterator<Result> iterator = scanner.iterator();
        while (iterator.hasNext()){
            // 获取一条记录
            final Result result = iterator.next();
            // 获取cell集合
            final List<Cell> cells = result.listCells();
            // 遍历cells 获取cell的组成信息
            for (Cell cell : cells) {
                final String rowKey = new String(CellUtil.cloneRow(cell));
                final String family = new String(CellUtil.cloneFamily(cell));
                final String qualifier = new String(CellUtil.cloneQualifier(cell));
                final long timestamp = cell.getTimestamp();
                if ("age".equals(family) && "base_ifo".equals(family)) {
                    final int value = Bytes.toInt(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                } else {
                    String value = new String(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                }
            }
        }
        // 4 关闭资源
        table.close();
    }

    /**
     * 关联条件查询
     * select * from xx where name like '%san%' and (age>20 and name='zhangsan-4')
     * @throws IOException
     */
    @Test
    public void  filterByMuti() throws IOException {
        Table table=connection.getTable(TableName.valueOf("bigHBase:person"));
        Scan scan=new Scan();
        // name like "-5"
        final SingleColumnValueFilter like = new SingleColumnValueFilter("base_ifo".getBytes(), "name".getBytes(), CompareOperator.EQUAL, new SubstringComparator("-5"));
        // age>2
        final SingleColumnValueFilter age = new SingleColumnValueFilter("base_ifo".getBytes(), "age".getBytes(), CompareOperator.GREATER, Bytes.toBytes(20));
        // name="shangsan-2"
        final SingleColumnValueFilter name = new SingleColumnValueFilter("base_ifo".getBytes(), "name".getBytes(), CompareOperator.EQUAL, Bytes.toBytes("shangsan-2"));
        //(age>20 or name='zhangsan-4')
        final FilterList nameAndAge = new FilterList(FilterList.Operator.MUST_PASS_ONE);
        nameAndAge.addFilter(name);
        nameAndAge.addFilter(age);
        //name like '%san%' and (age>20 or name='zhangsan-4')
        final FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
        filterList.addFilter(like);
        filterList.addFilter(nameAndAge);
        // 关联scan
       scan.setFilter(filterList);
       // 查询数据
        final ResultScanner scanner = table.getScanner(scan);
        final Iterator<Result> iterator = scanner.iterator();
        while (iterator.hasNext()){
            final Result result = iterator.next();
            // 获取cell集合
            final List<Cell> cells = result.listCells();
            // 遍历cells 获取cell的组成信息
            for (Cell cell : cells) {
                final String rowKey = new String(CellUtil.cloneRow(cell));
                final String family = new String(CellUtil.cloneFamily(cell));
                final String qualifier = new String(CellUtil.cloneQualifier(cell));
                final long timestamp = cell.getTimestamp();
                if ("age".equals(family) && "base_ifo".equals(family)) {
                    final int value = Bytes.toInt(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                } else {
                    String value = new String(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                }
            }
        }
        // 关闭资源
        table.close();
    }

    /**
     * 模块查询,就是指定全局查询一个字段的数据
     */
    @Test
    public void rangScan() throws IOException {
        final Table table = connection.getTable(TableName.valueOf("bigHBase:person"));
        Scan scan=new Scan();
        //根据列查询
        // base_info:1  base_info:2
        final ColumnRangeFilter filter = new ColumnRangeFilter("base_ifo".getBytes(), true, null, false);

        scan.setFilter(filter);
        final ResultScanner scanner = table.getScanner(scan);
        final Iterator<Result> iterator = scanner.iterator();
        while (iterator.hasNext()){
            final Result result = iterator.next();
            // 获取cell集合
            final List<Cell> cells = result.listCells();
            // 遍历cells 获取cell的组成信息
            for (Cell cell : cells) {
                final String rowKey = new String(CellUtil.cloneRow(cell));
                final String family = new String(CellUtil.cloneFamily(cell));
                final String qualifier = new String(CellUtil.cloneQualifier(cell));
                final long timestamp = cell.getTimestamp();
                if ("age".equals(family) && "base_ifo".equals(family)) {
                    final int value = Bytes.toInt(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                } else {
                    String value = new String(CellUtil.cloneValue(cell));
                    System.out.println(rowKey + "--" + family + "---" + qualifier + "--" + timestamp + "----" + value);
                }
            }
        }
        // 关闭资源
        table.close();
    }
}

4、原理

1、写入流程

	1、client向zookeeper发起获取元数据位置的请求
	2、zookeeper向client返回元数据所处的位置信息
	3、client向元数据所在的regionserver发起获取元数据的请求
	4、元数据所在的regionserver给client返回元数据,client会缓存元数据
	5、client根据元数据信息知道当前数据应该插入到哪个region,region处于哪个regionserver
	6、client向数据所在regionserver发起写入请求
	7、首先将数据写入HLOG中
	8、HLOG写入成功之后,再将数据写入memstore中
	9、向client返回写入完成信息

2、flush触发条件

	flush的时候是对整个region进行flush
	1、region中某一个memstore的大小达到128M的时候会进行flush
	2、当处于写高峰的时候,第一个触发条件可以适当延迟,延迟到region中所有的memstore的大小达到4*128M的时候会阻塞client的写入,优先flush
	3、regionserver中所有的region的所有的memstore的大小达到java_heap * hbase.regionserver.global.memstore.size * hbase.regionserver.global.memstore.size.lower.limit的时候会进行flush
	4、当处于写高峰的时候,第三个触发条件可以适当延迟,延迟到regionserver中所有的memstore的大小达到java_heap * hbase.regionserver.global.memstore.size,会阻塞client的写入,优先flush
	4、当预写日志的个数达到32,会触发flush
	5、当某个region中memstore的最后一次flush的时间与当前时间相比达到一个小时,会进行flush
	6、手动flush: flush '表名'

3、读流程

	1、client向zookeeper发起获取元数据位置的请求
	2、zookeeper向client返回元数据所处的位置信息
	3、client向元数据所在的regionserver发起获取元数据的请求
	4、元数据所在的regionserver给client返回元数据,client会缓存元数据
	5、client根据元数据信息知道当前数据应该插入到哪个region,region处于哪个regionserver
	6、client向数据所在regionserver发起读取请求
	7、首先从block cache中读取数据
	8、然后从memstore中读取数据
	9、从storeFile中读取数据
		store中storeFile个数可能比较多,如何快速找到数据处于哪个storeFile?
			1、通过布隆过滤器,判断数据可能存在哪些storeFile
				布隆过滤器特点: 如果判断存在,则不一定存在,如果判断不存在,则一定不存在
			2、通过HFile这种文件格式中的数据索引找到数据所在的位置
				HFile文件: Hfile中包含数据信息,数据的索引信息,数据元数据信息
	10、将数据返回给client

5、compact触发条件

	原因: 当memstore flush会生成一个storeFile文件,随着时间的流逝,storeFIle文件会越来越多,会影响查询性能,所以hbase提供文件的合并机制
	1、minor compact:
		触发条件: 当小文件[小于128M]数据达到3个的时候会触发
		合并过程: 只是单纯的合并文件的内存,不会清除过期数据或者无效数据
		合并结果: 将小文件合并成大文件
	2、major compact:
		触发条件: 7天一次
		合并过程: 在合并的过程中,会清除清除过期数据或者无效数据
		合并结果: 将store中是所有文件合并成一个文件

6、split触发条件

	原因: 当数据写入region,时间过长之后,region越来越大,后续请求大部分可能都会落在该region上,导致数据的读写请求负载不均衡
	0.94版本之前: 当region中某个store的大小达到10G,该region就会进行split
	0.9-2.0版本: 会根据region所属表在当前regionserver上有几个region[N]
		N==0 || N>100 ? 10G : Min(10G,2* 128M *N^3)
	2.0版本之后: 会根据region所属表在当前regionserver上有几个region[N]
		N==1 ? 2*128M : 10G
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值