`
flyingdutchman
  • 浏览: 358982 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

《Hbase权威指南》深入学习hbase:表定义和基本操作

阅读更多
        在HBase中,要定义一个用户表(HTable),只需要以下几个步骤:
                  Configuration conf = HBaseConfiguration.create();[/b][i]//通过HBase配置工厂生成一个Configuration配置实例
                  HBaseAdmin admin = new HBaseAdmin(conf);
                  HTableDescriptor htableDesc = new HTableDescriptor("users");//声明一个叫“users”的表[/i]
                  HColomnDescriptor colomnFamilyDesc = new HColomnDescriptor("info");//声明一个叫“info”的列族
                  colomnFamilyDesc.setMaxVersions(3);//将版本数由1改为3
                  htableDesc.addFamily(colomnFamilyDesc);//给“users”表添加“info”列族
                  admin.createTable(htableDesc);[/b][i]//生成“users”表
                  


        在操作用户表的时候,可以通过两种方式获得用户表的实例:
           1、直接生成HTable实例:
                 
                  Configuration conf = HBaseConfiguration.create();
                  HTableInterface userTable = new HTable(conf,"users");
                  

           2、通过HTablePool连接池获取用户表:
                 
                  HTablePool htablePool = new HTablePool();
                  //HTablePool htablePool = new HTablePool(30);
                  HTableInterface userTable = htablePool.getTable("users");
                  

对于HTable,有如下几个特点:
        1、HTable实例不是线程安全的,我们来看其API中的说明:
          "This class is not thread safe for updates; the underlying write buffer can be corrupted  if multiple threads contend over a single HTable instance."
        2、需要尽可能地共享Configuration实例,在第一种获取HTable对象的方式中,每次都活生成一个新的Configuration对象,可以把每次生成的Configuration对象都代表一个HBase的连接,在会造成线程不安全,建议使用同一个HBaseConfiguration实例来创建HTable实例;
        3、HTable实例创建是一个代价非常昂贵的操作。      
对于HTable的以上特性,故尽量通过第二种方式获取HTable的实例,HTablePool对象池中保有一个共享的Configuration对象,HTablePool对象池提供了一个线程封闭技术下的方案,它保证多线程下的共享安全。
        通过第一种方式获得的HTable对象,使用完后都必须关闭;而对于第二种方式获得的HTable对象,执行userTable.close()操作就表示要把该对象返回给htablePool对象池。 [/b]  

        HBase有4种基本的操作类型:Put,Get,Delete,Scan。在默认情况下,每次对一个HTable表调用Put,Get,Delete操作,都会执行一次RPC调用,每次对Scan执行后的结果集的每一次循环也代表一次RPC调用。这表明如果在一个批量提交数据的场景中,比如说要一个提交1000个Put操作,那么就要和服务器做1000次RPC操作,这无疑会带来很多不必要的网络开销。
        HBase内建有客户端的写缓冲(a built-in client-side write buffer),可以通过一次RPC调用将多个数据提交操作发送到服务器端。具体做如下:
             userTable.setAutoFlush(false);//默认为true
来禁止默认情况下的制动刷新行为,这些Puts操作会保存在客户端的内存中,然后在调用
              userTable.flushCommits();或userTable.close();
操作来提交批量修改,数据只有在被提交后才能再次被查出。但是,禁用自动刷新功能会有一个弊端,那就是如果客户端在调用RPC时出现问题,那么一部分数据就有可能丢失。         
          注:userTable.close()操作会隐含包括userTable.flushCommits()的调用。
 

          Put操作:
          Put操作可以对应HBase数据库表的保存和修改两个操作。除了可以一次提交一个put对象外,还可以一次提交一个put的集合:
                userTable.put(put);
                userTable.put(putList);

          示例如下:
          HTablePool htablePool = new HTablePool(); 
          HTableInterface userTable = htablePool.getTable("users"); 
          
          /**
           * 提交单个修改
           */
          Put singlePut = new Put(Bytes.toBytes("张三丰13560204"));
          singlePut.add(Bytes.toBytes("info"),Bytes.toBytes("sex"),Bytes.toBytes("male"));
          userTable.put(singlePut);
          
          /**
           * 提交单个修改
           */
          List<Put> putList = new ArrayList<Put>(3);
          singlePut = new Put(Bytes.toBytes("杨过12760204"));
          singlePut.add(Bytes.toBytes("info"),Bytes.toBytes("address"),Bytes.toBytes("湖北"));
          putList.add(singlePut);

          singlePut = new Put(Bytes.toBytes("小龙女12760204"));
          singlePut.add(Bytes.toBytes("info"),Bytes.toBytes("address"),Bytes.toBytes("湖北"));

          putList.add(singlePut);
          singlePut = new Put(Bytes.toBytes("段誉11760204"));
          singlePut.add(Bytes.toBytes("info"),Bytes.toBytes("address"),Bytes.toBytes("大理"));
          putList.add(singlePut);
          userTable.put(putList);//批量提交
          userTable.close();

          注:userTable.put(putList)操作并不能象传统关系型数据库那样,保证所有的put要么全部成功,要么全部失败。下面就是一个这样的示例:
          HTablePool htablePool = new HTablePool(); 
          HTableInterface userTable = htablePool.getTable("users"); 
          
          List<Put> putList = new ArrayList<Put>(3);
          Put put1 = new Put(Bytes.toBytes("李三19260204"));
          put1.add(Bytes.toBytes("info"),Bytes.toBytes("address"),Bytes.toBytes("陕西"));
          putList.add(put1);

          Put put2 = new Put(Bytes.toBytes("王五19760204"));   
          put1.add(Bytes.toBytes("info"),Bytes.toBytes("sex"),Bytes.toBytes("female"));
          putList.add(put2);
          
          Put put3 = new Put(Bytes.toBytes("王五19460204"));
          put1.add(Bytes.toBytes("empty"),Bytes.toBytes("sex"), Bytes.toBytes("female"));[b]//注意:在定义users表时并没有定义"empty"列族[/b]
          putList.add(put3);
         
          try{
              userTable.put(putList);
          }catch(Exception e){
              System.err.println("Error: ) + e;
              userTable.flushCommits();
          }
          userTable.close();
          

上例提交运行后只有rowkey为"李三19260204"和"王五19760204"行会被保存,而在保存rowkey="王五19460204"的行将不会被保存,提交的操作的集合会在保存rowkey="王五19460204"的行时会报报如下异常:
           Error:java.lang.IllegalArgumentException: No colomns to insert
           Exception in thread "main"
           org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException:
           Failed 1 action: NoSuchColomnFamilyException: 1 time,
           servers with issues:10.0.0.57:51640

产生的Error是一个客户端出检查(client-side check)的error,第二个Exception是服务器端由userTable.flushCommits()产生的远程异常。
          注意:由于之前设置过userTable.setAutoFlush(false)激活了client-side write buffer,客户端检查(“client-side check”)不会立即报错,一直延迟到buffer刷新。在这种情况下,可以通过调用checkAndPut()来将客户端检查不延迟报错。

          Get操作:
          Get操作是对HBase数据库表的读操作。可以一次读一条记录,也可以同时读取多条数据,如下所示:
          userTable.put(get);  
          userTable.put(getList);  
          

可以通过Get操作一次获取整行的数据,也可以一次获取一行中的一个列族中的数据,还可以获得具体的一个cell的数据:
          HTablePool htablePool = new HTablePool(); 
          HTableInterface userTable = htablePool.getTable("users"); 

          /**
           *一次获取整行的数据
           */
          Get get = new Get(Bytes.toBytes("张三丰13560204"));
          Result result = userTable.get(get); 
          
          /**
           *一次获取一行的"info"列族的数据
           */
          get = new Get(Bytes.toBytes("张三丰13560204"));
          get.addFamily(Bytes.toBytes("info"));
          result = userTable.get(get); 

          /**
           *获取具体的cell中的数据
           */
          Get get = new Get(Bytes.toBytes("张三丰13560204"));
          get.addColomn(Bytes.toBytes("info"),Bytes.toBytes("address"));
          result = userTable.get(get);  
          

一次RPC调用获得多个Get的操作的示例:
          HTablePool htablePool = new HTablePool(); 
          HTableInterface userTable = htablePool.getTable("users");
          
          List<Get> getList = new ArrayList<Get>(3);
          Get get = new Get(Bytes.toBytes("张三丰13560204"));          
          getList.add(get);

          get = new Get(Bytes.toBytes("段誉11760204"));
          getList.add(get);//2
   
          get = new Get(Bytes.toBytes("小龙女12760204));
          getList.add(get);//3

          Result[] results = userTable.get(getList);
          for(Result result : results){
              ... //在此做数据处理逻辑
          }
          

在一次RPC调用中List<Get>获取多条数据时,如果其中一个Get有问题报错的话,整个RPC调用都会失败,不会像批处理List<Put>操作那样部分成功部分失败,如下例所示:
         HTablePool htablePool = new HTablePool(); 
         HTableInterface userTable = htablePool.getTable("users");
          
         List<Get> getList = new ArrayList<Get>(3);
         Get get = new Get(Bytes.toBytes("张三丰13560204"));
         get.addColomn(Bytes.toBytes("info"),Bytes.toBytes("address"));
         getList.add(get);//1

         get = new Get(Bytes.toBytes("段誉11760204"));
         get.addColomn(Bytes.toBytes("info"),Bytes.toBytes("sex"));
         getList.add(get);//2
   
         get = new Get(Bytes.toBytes("小龙女12760204));
         get.addColomn(Bytes.toBytes("no_such_cf"),Bytes.toBytes("address"));
         getList.add(get);//3

         Result[] results = userTable.get(getList);
         for(Result result : results){
             ... //在此做数据处理逻辑
         }
         

由于在users中没有定义“no_such_cf”列族,故在执行userTable.get(getList);时会报如下异常:
         org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException:  
         Failed 1 action: NoSuchColomnFamilyException: 1 time,  
         servers with issues:10.0.0.57:51640 
         

         Get操作可以保证数据库的原子性。
   
         Delete操作:
         Delete是对HBase数据库表的删除操作。从前面的章节中我们已经知道HBase并没有真正的“删除”操作,对HTable执行delete实际上是向表中追加了一条被标记为“删除”标记的记录。
         在delete操作中可以删除整条数据,或具体的cell的数据,当然也可以删除某一个列族。可以一次删除一行数据,也可以一次删除多条数据。
         在删除数据时,当指定一个不存在的列族时会报错,这种情况下可以调用checkAndDelete()方法在客户端捕获这个异常并处理之。
         在批处理List<Delete>时,如果其中有一个delete有问题时,情况和批处理List<Put>同。

         Scan操作:
         Scan是HBase中对表的基于磁盘顺序“读”的扫描操作,功能和关系数据库中的游标相同。默认情况下,在遍历整个返回结果集时,没遍历一个对象会执行一次RPC调用,基于性能考虑,可以给scan设置缓存。
         Scan和Get都是“读”操作,但二者有明显的却别:Get操作需要一个具体的rowkey,而Scan并不需要,在一般情况下Scan是查询区间的。
         Scan是一个功能强大的操作,它提供如下几个构造函数:
         Scan()
         Scan(byte[] starRow,Filter filter)
         Scan(byte[] starRow)
         Scan(byte[] starRow,byte[] stopRow)
         

另外,可以由如下方法获取扫描结果集:
         ResultScanner getScanner(Scan sacn) throws IOException
         ResultScanner getScanner(byte[] family) throws IOException
         ResultScanner getScanner(byte[] family,byte[] qualifier) throws IOException
         

注:在Scan操作中,当设置一个不存在的列族时不会保存。
         下面代码是scan操作的示例:
         HTablePool htablePool = new HTablePool();   
         HTableInterface userTable = htablePool.getTable("users"); 
         
         Scan scan = new Scan();
         scan.addFamily(Bytes.toBytes("info"));
         scan.setStartRow(Bytes.toBytes("段誉11760204"));
         //scan.setStopRow(Bytes.toBytes("张三丰13560204"));
         ResultScanner scanner = userTable.getScanner(scan);
         for(Result rs : scanner){
             ... //do something here
         }
         scanner.close();//结束遍历后要一定要关闭scanner
         userTable.close();
         

         如上所说,在遍历scanner返回集时,默认情况下每一行都会触发一个RPC调用,这是在客户端(client-side)循环RPC调用。显而易见,在性能上这有很大的不足。要提升Scan扫描的性能,一次RPC调用抓取多条数据,可以激活scanner的cache功能,这个功能在默认情况下是禁用的。
         我们可以从两个方面来激活这个功能:在表层面,设置scanner客户端缓存的记录条数,如:
         scanner.setScannerCaching(20);//默认为1
         

也可以通过HBase的hbase-site.xml配置文件设置全局的扫描缓存的记录数:
         <property>
             <name>hbase.client.scanner.caching</name>
             <value>20</value>
         </property>
         

还要在服务器端设置scanner的缓存记录数:
         void setCaching(20);         
         

有了这两个设置,才可以真正激活该缓存功能。但是要注意的时,要设置恰当的缓存数量,要不然会造成OutOfMemoryException和时间过期的错误。


         Batch操作:
         前面介绍的List<Put>、List<Get>、List<Delete>,只能是通过一次RPC调用处理一种类型的集合处理操作,而Batch操作将将Put、Get、Delete等类型的操作组成一个批处理操作,由一个RPC处理,如下所示:
         HTablePool htablePool = new HTablePool();   
         HTableInterface userTable = htablePool.getTable("users");
   
         List<Row> batch = new ArrayList<Row>();

         Get get = new Get("张三丰13560204"");
         batch.add(get);

         Delete delete =new Delete("王五19460204");
         batch.add(delete);
         
         Put put = new Put(Bytes.toBytes("小张20120406");
         batch.add(put);
         
         Object[] results = new Object[batch.size];
         try{
             userTable.batch(batch,results);
         }catch(Exception e){
             System.err.out("Error: " + e);
         }
         
 
            
  • 大小: 83.3 KB
分享到:
评论

相关推荐

    hbase权威指南源码

    《HBase权威指南》是一本深入探讨Apache HBase这一分布式列式数据库的著作,源码则是作者为了辅助读者理解书中理论知识而提供的实践材料。HBase是构建在Hadoop文件系统(HDFS)之上的开源数据库,专为处理大规模数据...

    《HBase权威指南》示例代码

    《HBase权威指南》是大数据领域的一本经典著作,它深入浅出地介绍了HBase这一分布式列存储系统。HBase是构建在Hadoop生态系统之上的,用于处理大规模数据的NoSQL数据库,尤其适合实时读写操作。这本书的示例代码提供...

    Hbase权威指南 随书源代码 源码包 绝对完整版

    《HBase权威指南》是Hadoop生态中关于分布式数据库HBase的重要参考书籍,随书附带的源代码是学习和理解HBase实现机制的关键资源。这个源码包名为"hbase-book-master",意味着它是该书的主代码仓库,包含完整的示例和...

    HBase:The Definition Guide,HBase权威指南完全版

    《HBase:The Definition Guide》是一本全面深入探讨HBase的权威指南,旨在为读者提供HBase的详尽理解。HBase,作为Apache Hadoop生态系统中的一个分布式、面向列的数据库,源自Google的BigTable设计,被Facebook等...

    HBase权威指南中文版 高清版的

    《HBase权威指南中文版》是一本深度解析分布式大数据存储系统的专著,专注于Apache HBase这一开源的非关系型数据库。HBase是构建在Hadoop文件系统(HDFS)之上,设计用于处理海量数据的列式数据库,尤其适用于实时...

    HBase权威指南中文版

    通过对《HBase权威指南中文版》的学习,读者不仅能理解HBase的基本概念,还能掌握如何设计表结构、优化查询、管理和维护HBase集群,从而在实际项目中充分利用HBase的优势,处理大规模数据存储与查询挑战。

    HBase:权威指南

    总之,《HBase:权威指南》是深入学习和掌握HBase的宝贵资源,无论你是初学者还是经验丰富的开发者,都能从中受益匪浅,提升处理大数据的能力。通过阅读这本书,你将能够熟练地运用HBase解决各种大数据存储和处理的...

    HBase权威指南

    《HBase权威指南》是一本深入探讨分布式列式数据库HBase的专业书籍,旨在为读者提供全面、详尽的HBase知识。HBase是构建在Apache Hadoop文件系统(HDFS)之上的开源数据库,主要用于存储大规模结构化数据,是大数据...

    Hbase学习资料

    学习HBase,可以从《HBase权威指南》和《HBase实战》这两本书入手,它们分别深入探讨了HBase的设计原理、使用方法以及最佳实践,是理解并掌握HBase的重要资源。通过阅读这些书籍,你可以全面了解HBase的核心特性和...

    hadoop权威指南第三版完整版

    ### Hadoop权威指南第三版知识点总结 #### 一、Hadoop概述 - **定义与背景**:Hadoop是一个能够对大量数据...以上就是《Hadoop权威指南第三版》的主要知识点总结,希望能够帮助读者深入了解Hadoop的相关技术和应用。

    最新 Hadoop权威指南 第四版 中文(绝非水军)

    通过《Hadoop权威指南》第四版的学习,读者不仅可以掌握Hadoop的基本概念和操作,还能深入了解其背后的分布式计算理论,从而在大数据领域打下坚实的基础。尽管原版书籍可能存在质量问题,但中文版的翻译为国内用户...

    [HBase.The.Definitive.Guide].Lars.George.文字版

    无论是对于想要学习HBase的新手,还是已经有一定经验的开发者,这本书都是一份宝贵的资源。通过阅读本书,读者将能够更好地理解HBase的工作原理,掌握其核心功能,并学会如何有效地利用HBase来解决大数据处理中的...

    Hadoop权威指南

    ### Hadoop权威指南知识点概述 ...综上所述,《Hadoop权威指南》不仅全面地介绍了Hadoop的基本概念和技术细节,还深入探讨了其在实际项目中的应用和优化技巧,是一本非常适合初学者和有经验的开发者参考学习的书籍。

    Hadoop权威指南(第3版) 修订版 中文PDF高清晰

    《Hadoop权威指南(第3版) 修订版 中文PDF高清晰》是关于大数据处理领域的一款经典教材,深入解析了Hadoop生态系统的核心组件和技术原理。Hadoop是Apache基金会的一个开源项目,它为大规模数据处理提供了分布式计算...

    Hadoop权威指南中文版

    ### Hadoop权威指南知识点概述 #### 一、Hadoop概览 - **定义与起源**:Hadoop是一个开源框架,用于分布式存储和处理大规模数据集。它最初由Doug Cutting和Mike Cafarella创建,并于2006年作为Apache项目的一部分...

Global site tag (gtag.js) - Google Analytics