zoukankan      html  css  js  c++  java
  • Hbase写入原理-常用操作-过滤器

    hbase是基于大表的数据库
    =====================================
        随机访问和实时读写
    
    
    hbase和hive的区别:
        hbase:低延迟实时性,不支持分析
        hive:高延迟,分析工具
    
    awk '{print $1}'    //默认以'	'分割,截串取第一个成员
    
    
    hbase原理:
    ========================
        hdfs://mycluster/user/hbase/data    //hbase数据
        
        namespace    //文件夹
        Htable        //文件夹
        Hregion        //区域,文件夹
        CF        //列族, 文件夹
        数据        //文件形式存在(row,cf,col,value)
    
    
    hbase在写入数据时,先写入到memstore中,到达一定的值或重启的时候会实例化为文件
    
    
    
    scan 'hbase:meta'
        ns1:t1,,1522573626932.02aab65df5b31 column=info:regioninfo, timestamp=1522630951985, value={ENCODED => 02aab65df5b31c1145a8b799ced42c92, NAM
        c1145a8b799ced42c92.                E => 'ns1:t1,,1522573626932.02aab65df5b31c1145a8b799ced42c92.', STARTKEY => '', ENDKEY => ''}
        ns1:t1,,1522573626932.02aab65df5b31 column=info:seqnumDuringOpen, timestamp=1522630951985, value=x00x00x00x00x00x00x00x15
        c1145a8b799ced42c92.
        ns1:t1,,1522573626932.02aab65df5b31 column=info:server, timestamp=1522630951985, value=s102:16020
        c1145a8b799ced42c92.
        ns1:t1,,1522573626932.02aab65df5b31 column=info:serverstartcode, timestamp=1522630951985, value=1522629569862
        c1145a8b799ced42c92.
    
    
    hbase:meta表存放的是所有表的元数据,即表(区域)和regionserver的映射关系
    
        问题1:hbase:meta表是谁负责管辖?        
            //每个表(包括元数据表),都分别由一个regionserver负责的
    
        问题2:元数据中的元数据,hbase:meta的元数据存放位置?    
            //hbase:meta表的数据信息,由zk负责管辖
    
        普通表:    表体由regionserver负责管理,元数据是由hbase:meta表负责管理
        hbase:meta表:  表体由regionserver负责管理,元数据是由zk负责管辖
    
    
        写(put)流程:    1、客户端先联系zk,找到hbase:meta表的regionserver,在此请求数据
                2、通过hbase:meta的数据,找到表(区域)的映射关系,通过regionserver定位到指定表(区域)
                3、查询信息一旦被触发,会被缓存,以便下次使用
                4、用户向区域服务器(RegionServer)发起put请求时,会将请求交给对应的区域(region)实例来处理。    
                5、决定数据是否需要写到由HLog实现的预写日志(WAL)中。
                6、一旦数据被写入到WAL中,数据会被放到MemStore中
                7、memstore如果写满,则会被刷写(flush)到磁盘中,生成新的hfile
    
    区域:region管理
    ======================================
        是regionserver的基本管理单位
    
        rowKey是以字节数组进行排序
    
        表切割:
            split 'ns1:t1','row500'
    
        区域切割:
            split 'ns1:t1,row500,1522634115455.b88d6163f7e2eced2f2297c7fe938b3b.','row750'
    
        
        创建表,进行预切割:
            create 'ns1:t2', 'f1', SPLITS => [ '20', '30', '40']
            
        移动区域:
            move '43e14524a984a4bf6a813a4f2a8ac8eb' , 's103,16020,1522634665677'
    
    
        表切割之后,之前表所在的区域会被切割成两个新的区域,原区域处于离线状态,再次启动hbase时,原区域相关信息会被清空
            
    
        区域合并
             merge_region '28d725266b30bcef636e994f08c9e8d9','976bc7a3b8769184c1a0a5aca1339d99'
            
    
    紧凑compact:
    ====================================
        解决flush产生的小文件(hfile),将其进行合并
    
        compact 'ns1:t1'            //合并小文件,重启后生效
        compact_rs 's103,16020,1522634665677'    //合并regionserver中所有region
        major_compact                //合并小文件,即刻生效
    
        
    
            
    regionname        //区域名,eg:ns1:t1,row500,1522634115455.b88d6163f7e2eced2f2297c7fe938b3b.
    encoded_regionname    //编码区域名,eg:b88d6163f7e2eced2f2297c7fe938b3b    注意不加'.'
    server_name        //regionserver名字, eg:s102,16020,1522634665523
    
    
    hbase数据写入流程,代码分析
    ==========================================================
    在数据写入的时候,hbase会初始化一个2M的mutator缓冲区
              通过Arrays.asList(m)将Mutation对象,即数据转换成List
              writeAsyncBuffer证明,数据写入是异步写入
              每次写入数据都会在内部进行自动清理
              写入时将传来的Mutation对象,即数据放在LinkedList中
    
              put命令时:1、传入put对象
                    在传每个数据时候,都会进行autoflush自动清理,且需要一次rpc通信
    
                     2、传入put集合
                    将集合传入并且处理之后,进行一次flush,需要一次rpc通信
    
                    10000        关闭自动flush    关闭写前日志    关闭flush+WAL
            ----------------------------------------------------------------------
            put        38,532ms    3,227ms        10,769ms    2,959ms
    
            putBatch    3,507ms
    
            
            在put中设置关闭自动flush
                HTable.setAutoFlush(false,false);
    
            
            在put中关闭WAL写入
                 put.setDurability(Durability.SKIP_WAL);
    
    
    WAL
    =============================
        Write ahead log
        适用于容灾,当机器发生断电,memstore数据很可能会丢失
    
        WAL:数据写入到WAL则证明写入成功,存储对数据的修改,类似于hadoop的edits文件
             如果数据库崩溃,可以有效地回放日志
    
    *****    强烈建议用户不要关闭WAL
        实现类:org.apache.hadoop.hbase.regionserver.wal.FSHLog
        
        WAL在0.x版本中使用的是SeqFile
        新版中不是
    
    memstore:
    ================================
        1、刷写到磁盘,阈值是5M
          <property>
            <name>hbase.hregion.preclose.flush.size</name>
            <value>5242880</value>
          </property>
        
        2、关闭regionserver会使memstore强制刷写到磁盘
    
    
    
    
    hbase基本命令:
    ============================
        create_namespace 'ns1'   //create_namespace 'ns1'
        drop_namespace 'ns1'        //drop_namespace 'ns1'
        create 'ns1:t1','f1','f2'    //create 'ns1:t1','f1','f2'
        put 'ns1:t1','row1','f1:name','tom'      //put 'ns1:t1','row1','f1:name','tom'
        scan 'ns1:t1'                            //scan 'ns1:t1'
        alter 'ns1:t5', 'f3'        //添加列族 //alter 'ns1:t5' , 'f3'
    
    
    
    hbase文件:
    ===========================
        根级文件:/user/hbase
            WALs        //预写日志,和hadoop中的edits文件类似,作用是容灾
                    //通过以下配置进行周期性滚动
                     <property>
                        <name>hbase.regionserver.logroll.period</name>
                        <value>3600000</value>
                        <description>毫秒为单位,默认一小时</description>
                     </property>
    
    
            oldWALs        //旧的预写日志,当时间超过1小时,WAL会被回滚到此处
                    //十分钟后此文件会被清除,配置文件如下
                     <property>
                        <name>hbase.master.logcleaner.ttl</name>
                        <value>600000</value>
                        <description>毫秒为单位,默认十分钟</description>
                      </property>
    
            hbase.id    //hbase唯一id
            hbase.version    //hbase集群版本信息
    
            corrupt        //损坏日志文件
    
        表级文件:/user/hbase/data/ns1/t1
    
            .tabledesc/.tableinfo.0000000001    //串行化后的表描述符desc 'ns1:t1'
    
        
        region级文件:
            .regioninfo        //region的描述,和tableinfo类似
    
            recovered.edits        //WAL日志恢复文件
            
        
    当region足够大的时候,会自动切分成两个region,将原文件一分为二  region默认大小是10G
    ==================================================
          <property>
            <name>hbase.hregion.max.filesize</name>
            <value>10737418240</value>
            <description>
            Maximum HStoreFile size. If any one of a column families' HStoreFiles has
            grown to exceed this value, the hosting HRegion is split in two.</description>
          </property>
    
         注意:当所有region同时达到阈值时候,会产生切割风暴,严重消耗资源
    
         1、设置预切割:
            create 'ns1:t2', 'f1', SPLITS => [ '20', '30', '40']
    
         2、设置一个非常大的值,然后手动切割
    
    
    HFile:
    =============================
        是hbase的文件格式,以k/v形式存储,k/v均是字节数组
    
        HFile包括以下内容:
            读取或写入压缩块的存储空间。 
            每个块所指定的I/O操作的压缩编解码器
            临时的key存储
            临时的value存储
            hfile索引,存在于内存,占用空间约为(56+AvgKeySize)*NumBlocks.
            性能优化建议
        ****    最小块大小,推荐在 8KB to 1MB之间
                顺序读写推荐大块,但不便于随机访问(因为需要解压更多的数据)
                小块便于随机读写,但是需要占用更多内存,但是创建起来更慢(因为块多,每次压缩都需要flush操作)
                由于压缩缓存,最小块大小应该在20KB-30KB.
    
        查看hfile:
        ====================
        hbase hfile -a -b -p -v -h -f hdfs://mycluster/user/hbase/data/ns1/t1/77c55f893ecec3bbb2dfd02e3737c0c2/f1/5406345aabc640309be64abd21a2a500
            key:row1/f1:age/1522634241444/Put/vlen=1/seqid=22
            value:1
    
    
    Cell:
    =============================
     * 1) row        
     * 2) column family
     * 3) column qualifier
     * 4) timestamp
     * 5) type
     * 6) MVCC version    //multiple version concurrency contorl    多版本并发控制
     * 7) value
    
    
    scan操作:
    =======================
        限定列扫描:
            HTable.getScanner(Bytes.toBytes("f1"),Bytes.toBytes("name"));   //HTable.getScanner(Bytes.toBytes("f1"),Bytes.toBytes("name"));
    
        指定列族扫描:
            HTable.getScanner(Bytes.toBytes("f1"));  //Htable.getScanner(Bytes.toBytes("f1"));
        
        全表扫描
            HTable.getScanner(Scanner)   //Htable.getScanner(Scanner)
    
        限定row范围进行扫描:
            new Scan(Byte[] startKey,Byte[] stopKey)   //new Scan(Byte[] startKey,Byte[] stopKey)
    
        
        catch和batch
            每次it.next()的时候,都会调用一次rpc,效率很差
            避免此问题,引入cache的概念
    
            catch:将指定数量行数进行缓存,到达阈值,通过一个RPC共同发给客户端
    
              <property>
                <name>hbase.client.scanner.caching</name>
                <value>2147483647</value>
                <description>每次查询缓存的数量</description>
              </property>
    
        
            cache    10        1000        10000        1
            -------------------------------------------------------------
            time    6,423ms        5,434ms        5,831ms        14,339ms
    
        
            batch: 缓存指定的列数,到达阈值,通过一个RPC共同发给客户端
    
            
            RPC次数:    row x col / min(cache,rowNo) / min(batch, colNo) +1
            result次数:    row x col / min(batch, colNo)            //只和batch有关
    
    
    hbase过滤器:
    ===================================================
        相当于sql的where子句
        使用谓词下推的原理,通过server端过滤,返回给client数据
    
        hbase过滤器中的比较方法:
            CompareFilter.CompareOp.EQUAL    ====> '='
    
        使用过滤器:
            1、初始化过滤器        //new RowFilter
            2、初始化参数:比较方法    //CompareFilter.CompareOp.EQUAL
                       比较器    //
            
        过滤器:
            RowFilter            //行过滤器    //RowFilter
            FamilyFilter            //列族过滤器   //FamilyFilter
            QualifierFilter            //列过滤器   //QualifierFilter
            ValueFilter            //值过滤器  //ValueFileter
            SingleColumnValueFilter        //单列值过滤器,通过搜索制定列族和制定col的值,返回整行数据    //SingleColumnValueFilter
                            //相当于select * from xxx where id=1;
            TimeStampFilter            //时间戳过滤器   //TimeStampFilter
    
    
            
                
        
        比较器:
            BinaryComparator        //二进制比较器        //BianryComparator
            RegexStringComparator        //正则比较器, 比较时最好使用EQUAL   //RegexStringComparator
            SubstringComparator        //子串比较器, 比较时最好使用EQUAL    //SubstringComparator
    
            
            
            /**
         * 组合过滤器
         * @throws Exception
         */
        @Test
        public void testCombineFilter() throws Exception {
            long start = System.currentTimeMillis();
            //初始化配置信息
            //Configuration conf = new Configuration();
            Configuration conf = HBaseConfiguration.create();
            //入口点,创建连接
            Connection conn = ConnectionFactory.createConnection(conf);
    
            //通过getTable方法获取表的实例
            HTable table = (HTable) conn.getTable(TableName.valueOf("ns1:t5"));  
            //HTable table = (HTable) conn.getTable(TableName.valueOf("ns1:t5"));
            
            //Scan scan = new Scan();
            Scan scan = new Scan();
    
    
            //行过滤器,使用正则过滤器,过滤出111结尾的rowKey
            RowFilter filter1 = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*111"));
            //RowFilter filter = new RowFilter(CompareFilter.CompareOpEQUAL,new RegexStringComparator(".*111"));
    
            //列族过滤器,使用二进制过滤器,过滤出f2列族的数据
            FamilyFilter filter2 = new FamilyFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("f2")));
            //FamilyFilter filter2 = new FamilyFilter(ComparaFilter.CompareOp.EQUAL,new BinaryComparator(Bytes.toBytes("f2")));
            
            
            FilterList filterList = new FilterList();   //FilterList filterList = new FilterList();
            filterList.addFilter(filter1);   //filterList.addFilter(filter1);
    
            filterList.addFilter(filter2);   //filterList.addFilter(filter2);
    
            scan.setFilter(filterList);  //scan.setFilter(filterList);
    
            //通过扫描器得到结果集
            ResultScanner rs = table.getScanner(scan);         ResultScanner rs = table.getScanner(scan);
            //得到迭代器
            Iterator<Result> it = rs.iterator();   rs.iterator();  
    
            TestFilter.printVal(it);   TestFilter.printVal(it);
    
            table.close(); //table.close();
            System.out.println(System.currentTimeMillis() - start);
        }
        
        
        public static void printVal(Iterator<Result> it){
            while (it.hasNext()){
                Result next = it.next();
                List<Cell> cells = next.listCells();   //next.listCells();
                for (Cell cell : cells) {
                    String val = Bytes.toString(CellUtil.cloneValue(cell));    //Bytes.toString(CellUtil.cloneValue(cell));
                    String clo = Bytes.toString(CellUtil.cloneQualifier(cell));  //Bytes.toString(CellUtil.cloneQualifier(cell))
                    String cf = Bytes.toString(CellUtil.cloneFamily(cell));     //Bytes.toString(CellUtil.cloneFamily(cell));
                    String row = Bytes.toString(CellUtil.cloneRow(cell));    //Bytes.toString(CellUtil.cloneRow(cell)); 
    
                    System.out.println(row+"/"+cf+"/"+clo+"/"+val);
    
                }
    
    
            }
        }
  • 相关阅读:
    8.9_java_35
    8.8_java_34
    8.7_java_33
    8.6_java_32
    8.5_java_31
    8.4_java_30
    8.3_java_29
    2020年春季学期《软件工程》教学总结
    json的标准格式
    详解 【Vue】 生命周期
  • 原文地址:https://www.cnblogs.com/zyde/p/9015523.html
Copyright © 2011-2022 走看看