快乐学习
前程无忧、中华英才非你莫属!

让我们一起来了解前端应用怎么开发Hbase

一、前言

对于前两篇的特别概念化的介绍了Hbase,这章用通俗易懂的语言来结束上两章里面的专业术语。

回忆上回内容:8.6 、hbase核心概念:HBase并不是一个列式存储的数据库,HBase是以列式存储的格式在磁盘上存储数据。

解惑:

什么是列式存储?列存储不同于传统的关系型数据库,其数据在表中是按行存储的,列方式所带来的重要好处之一就是,由于查询中的选择规则是通过列来定义的,因 此整个数据库是自动索引化的。按列存储每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量,一个字段的数据聚集存储,那就 更容易为这种聚集存储设计更好的压缩/解压算法。这张图讲述了传统的行存储和列存储的区别:


二、很多朋友会问我Hbase这么好为什么不能取代Mysql?

   

  解答如下:

            因为玩Hbase对运维人员的要求较高,一旦出现Bug很容易造成业务断链,能玩的6的只有公司的背景需要有一定开源技术水平的支撑。

            对于传统型中小型公司 组建专有的Hadoop运维团队甚至是研发团队,从公司规划与发展上来说是比较困难的事情。

            Hbase的特点只有牛逼的读写速度,修改和事务性处理这方面表现力太挫,如果事务性处理是公司的核心业务,那就别用Hbase了,除了阿里巴巴之外

            我没看到哪家银行交易系统用Hbase弄的!

           

            所以hbase暂时不能取代mysql,除非你有媲美阿里巴巴的技术,这我一点话都没有!

            我个人推荐业务场景,只涉及到大量的读写,在Mysql上已经没有优化空间了,并且核心业务事务性处理比较少,没有大量复杂的关系查询。

            并且自己的DAO,PO层改起来不麻烦和一定的大数据开源技术储备,和阅读源码以及快速修复Bug的能力,建议上手Hbase。


三、几款Hbase的ORM框架这里重点介绍Kundera

http://stackoverflow.com/questions/3257034/java-orm-for-hbase

Kundera是一个带有JPA接口的“Polyglot Object Mapper”。Kundera背后的想法是使NoSQL数据库的工作变得简单而有趣。昆德拉正在开发具有以下目标:

  • 使用NoSQL与处理SQL一样简单

  • 作为NoSQL数据存储的JPA兼容映射解决方案。

  • 为了帮助开发人员,忘记了NoSQL存储的复杂性,并专注于域模型。

  • 跨数据存储进行切换,就像更改配置一样简单。

入门

昆德拉最新的稳定版本是3.8。它是一个基于maven的项目。您可以直接从github下载并使用以下命令进行构建:

mvn clean install -Dfile src / pom.xml

或者可以以下列方式直接在您的项目中添加为maven依赖关系:

  • 将以下存储库添加到pom.xml中:

 <repository>
     <id>sonatype-nexus</id>
     <name>Kundera Public Repository</name>
     <url>https://oss.sonatype.org/content/repositories/releases</url>
    <releases>
        <enabled>true</enabled>
    </releases>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
 </repository>
  • 添加数据存储特定的Kundera模块作为依赖(例如下面的Cassandra):

  <dependency>
        <groupId>com.impetus.kundera.client</groupId>
        <artifactId>kundera-cassandra</artifactId>
        <version>${kundera.version}</version>
  </dependency>

通过上述对您的pom.xml的更改来构建您的项目,并开始使用Kundera!

kundera-hbase-example.zip


四、国内Hbase 的轻量级ORM封装好的包

Hbase在处理billion级别的能力是毫无质疑的,目前优于其他的nosql数据库,如MongoDB、cassandra、Redis等, 配合它强大的rowkey查询,fileter,协处理器等,在海量数据库中发挥了强大的功能。但是HBase因为满足的是CAP原则中C和P,所以在查询过程中语句支持较弱,使用过程较为复杂。存在下面的一些痛点。

痛点

  1. 首先HBase只能存储byte数组的数据,数据存入到hbase中时都需要做相应的转换,读取的数据的时候也要相应的转换回来,使用麻烦。

  2. 第二,HBase在使用过程中,涉及到filter、协处理的使用,如果对API不熟悉,无法下手。

  3. 第三,hbase本身不提供分页的功能,每次分页需要在代码中记录当前读取的rowkey,在使用PageFilter读取一定数量的rowkey,然后继续读取,编程复杂度高。

  4. 最后,不熟悉hbase的开发人员,无法理解nosql、hbase的no schema,期望还是用关系数据库的方式操作hbase。

HBase ORM框架

基于以上的原因,所以我有了想写一个类似于hibernate那种对象关系映射框架(ORM)的想法,像操作对象一样方便的操作HBase数据库,但是它要是轻量级的,无侵入的,只提供CURD、分页、映射功能的一个简单功能。

一些特性:

  • 使用注解的方式,将PO(Persistent Object)映射成HBase对应的表

  • 提供CRUD的方法:create\research\update\delete

  • 提供分页查询的功能

  • 提供类似于hibernate中Criteria 风格的操作方式

Demo:

1、在po对象上添加相应的注解:@Table\@RowKey\@Column

 @Table(name = "user")</br>
 public class User {

  @RowKey
  private int id;

  @Column(family = "info")
  private int userId;

  @Column(family = "info", name = "user_name1")
  private String userName;

  @Column(family = 

2、使用HBaseColumnarClient实例操作PO对象

  HBaseColumnarClient client = new    HBaseColumnarClient(scanCaching, scanBatch);
  DataSourceConfig config = new DataSourceConfig("hbase.properties");
  HBaseSource source = new HBaseSource(config.getProperties());
  client.setHBaseSource(source);

  //create
  client.putObject(user);

  //delete
  client.deleteObject(user);

  //query

  User user = client.findObject(Bytes.toB6

3、提供类似于Hibernate Criteria的风格操作hbase

  // count the data
  Filter[] filters = null;
  long count =
               Criteria.aggregate(User.class).fromRow(startRow).toRow(endRow)
                               .filters(filters).build().count(client);

  // sum the column value
  long sum =
               Criteria.aggregate(User.class).fromRow(startRow).toRow(endRow)
                               .filters(filters).propertyName("age").build().sum(client);

   // query by rowKey
             User queryUser =
                         Criteria.find(User.class).byRowKey(Bytes.toBytes(id)).build().query(client);

   // query from startRow to endRow
  List<User> queryList =
               Criteria.find(User.class).fromRow(startRow).toRow(endRow).build()
                               .queryList(client);

  // query by page
  PageBean<User> pageBean = new PageBean<User>() {};
  pageBean.setPageSize(10);
  pageBean.setStartRow(startRow);
  pageBean.setStopRow(endRow);
  PageBean<User> queryPage =
               Criteria.find(User.class).pageBean(pageBean).build().queryPage(client);

  // delete data

  byte[] rowKey = Bytes.toBytes(id);

  Criteria.delete(User.class).byRowKey(rowKey).buil1

希望大家喜欢这个框架,多提意见 

项目地址:https://github.com/zacharyzhanghao/orm-hbase

五、springdatahadoop -- hbasetemplate

java 利用 sping-data-hadoop       HbaseTemplate 操作hbase

转载请注明出处:http://blog.csdn.net/linlinv3/article/details/42737113

官网api地址:http://docs.spring.io/autorepo/docs/spring-data-hadoop/2.1.0.M1-hadoop24/api/org/springframework/data/hadoop/hbase/HbaseTemplate.html为了让自己的项目能够融合hbase ,这里讲解了 如何 利用hbasetemplate 对hbase进行操作

具体的hbase的特性和原理就不多说了

直接贴程序

配置文件

1、建立 spring-hbase.xml 获取连接池

第一种:直接在配置文件注明 hdfs的端口和zk的地址以及端口进行连接

[html] view plain copy print?派生到我的代码片

  1. <?xml version="1.0" encoding="UTF-8"?>  

  2.     <beans xmlns="http://www.springframework.org/schema/beans"  

  3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

  4.    xmlns:hdp="http://www.springframework.org/schema/hadoop"  

  5.    xmlns:beans="http://www.springframework.org/schema/beans"  

  6.    xmlns:context="http://www.springframework.org/schema/context"  

  7.    xsi:schemaLocation="  

  8.     http://www.springframework.org/schema/beans   

  9.     http://www.springframework.org/schema/beans/spring-beans.xsd  

  10.     http://www.springframework.org/schema/hadoop   

  11.     http://www.springframework.org/schema/hadoop/spring-hadoop.xsd  

  12.     http://www.springframework.org/schema/context   

  13.     http://www.springframework.org/schema/context/spring-context-3.1.xsd">  

  14.      

  15.    <context:property-placeholder location="hbase.properties" />  

  16.      

  17.       <!-- 配置HbaseTemplate -->  

  18.     <bean id="htemplate" class="org.springframework.data.hadoop.hbase.HbaseTemplate">    

  19.           <property name="configuration" ref="hbaseConfiguration">  

  20.           </property>  

  21.      </bean>    

  22.     <!-- 配置hadoop的基本信息 -->   

  23.      <hdp:configuration>  

  24.           fs.default.name="hdfs://192.168.0.173:8082"  

  25.      </hdp:configuration>   

  26.      <!-- 配置zookeeper地址和端口 -->  

  27.      <hdp:hbase-configuration zk-quorum="192.168.0.173" zk-port="2181" />   

  28.  </beans>  

第二种:只需要配置zk的地址和端口,但是需要在classpath另外新增 hbase-site.xml的配置

spring-hbase.xml 配置:

[java] view plain copy print?派生到我的代码片

  1. <?xml version="1.0" encoding="UTF-8"?>  

  2.     <beans xmlns="http://www.springframework.org/schema/beans"  

  3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

  4.    xmlns:hdp="http://www.springframework.org/schema/hadoop"  

  5.    xmlns:beans="http://www.springframework.org/schema/beans"  

  6.    xsi:schemaLocation="  

  7.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  

  8.     http://www.springframework.org/schema/hadoop http://www.springframework.org/schema/hadoop/spring-hadoop.xsd">  

  9.       <!-- 配置zookeeper的信息,远程连接hbase时使用 -->  

  10.     <hdp:configuration resources="classpath:/hbase-site.xml" />  

  11.     <hdp:hbase-configuration configuration-ref="hadoopConfiguration" />  

  12.     <!-- 配置HbaseTemplate -->  

  13.     <bean id="htemplate" class="org.springframework.data.hadoop.hbase.HbaseTemplate">  

  14.         <property name="configuration" ref="hbaseConfiguration">  

  15.         </property>  

  16.     <property name="encoding" value="UTF-8"></property>  

  17.     </bean>  

  18.  </beans>  

hbase-site.xml 配置  放在classpath下(直接扔到src下即可)

[java] view plain copy print?派生到我的代码片

  1. <?xml version="1.0"?>  

  2. <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>  

  3. <configuration>  

  4.     <property>  

  5.         <name>hbase.zookeeper.quorum</name>  

  6.         <value>192.168.0.173</value>  

  7.     </property>  

  8.   

  9.     <property>  

  10.         <name>hbase.zookeeper.property.clientPort</name>  

  11.         <value>2181</value>  

  12.     </property>  

  13. </configuration>  

配置完成

程序代码

官网的api地址已经在上面发过了,这里只做了一个简单的demo,列举了简单的 get  find execue 方法

[java] view plain copy print?派生到我的代码片

  1. package cn.fulong.hbase;  

  2.   

  3. import java.util.HashMap;  

  4. import java.util.List;  

  5. import java.util.Map;  

  6.   

  7. import org.apache.hadoop.hbase.Cell;  

  8. import org.apache.hadoop.hbase.client.HTableInterface;  

  9. import org.apache.hadoop.hbase.client.Put;  

  10. import org.apache.hadoop.hbase.client.Result;  

  11. import org.apache.hadoop.hbase.client.Scan;  

  12. import org.apache.hadoop.hbase.util.Bytes;  

  13. import org.springframework.beans.factory.BeanFactory;  

  14. import org.springframework.context.ApplicationContext;  

  15. import org.springframework.context.support.ClassPathXmlApplicationContext;  

  16. import org.springframework.data.hadoop.hbase.HbaseTemplate;  

  17. import org.springframework.data.hadoop.hbase.RowMapper;  

  18. import org.springframework.data.hadoop.hbase.TableCallback;  

  19.   

  20. import cn.fulong.view.HbaseModel;  

  21. public class HbaseTest {  

  22.     //ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "application_hbase.xml" });    

  23.     ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "spring_hbase.xml" });    

  24.   

  25.     BeanFactory factory = (BeanFactory) context;   

  26.     HbaseTemplate htemplate = (HbaseTemplate) factory.getBean("htemplate");  

  27.     Map hMap = new HashMap<String, List<HbaseModel>>();  

  28.     public String key;  

  29.     public String familyName ;  

  30.     public String qualifier;  

  31.     public String value;  

  32.           

  33.     public String getValue() {  

  34.         return value;  

  35.     }  

  36.     public void setValue(String value) {  

  37.         this.value = value;  

  38.     }  

  39.     public String getFamilyName() {  

  40.         return familyName;  

  41.     }  

  42.     public void setFamilyName(String familyName) {  

  43.         this.familyName = familyName;  

  44.     }  

  45.     public String getQualifier() {  

  46.         return qualifier;  

  47.     }  

  48.     public void setQualifier(String qualifier) {  

  49.         this.qualifier = qualifier;  

  50.     }  

  51.     public String getKey() {  

  52.         return key;  

  53.     }  

  54.     public void setKey(String key) {  

  55.         this.key = key;  

  56.     }  

  57.       

  58.            

  59.           

  60.     public static void main(String[] args) {  

  61.         //PrefixFilter  

  62.         HbaseTest h = new HbaseTest();  

  63.    

  64.         for(int i=0;i<=10000;i++){  

  65.             h.setKey("linlin"+i);  

  66.             h.setFamilyName("info");   

  67.             h.setQualifier("service");  

  68.             h.setValue(i+"技术创新和质量服务");  

  69.             h.execute("linlintest"null);  

  70.         }  

  71.       

  72.      List<Map<String,Object>>  mapList1 = h.find("linlintest",null,null);  

  73.         System.out.println("2");  

  74.     }  

  75.     /** 

  76.      * 写数据 

  77.      * @param tableName 

  78.      * @param action 

  79.      * @return 

  80.      */  

  81.     public Boolean execute(String tableName, TableCallback<Boolean> action) {    

  82.         return htemplate.execute(tableName, new TableCallback<Boolean>() {  

  83.             public Boolean doInTable(HTableInterface table) throws Throwable {  

  84.                 boolean flag = false;  

  85.                 try{  

  86.                     byte[] rowkey = key.getBytes();  

  87.                     Put put = new Put(rowkey);  

  88.                     put.add(Bytes.toBytes(familyName),Bytes.toBytes(qualifier), Bytes.toBytes(value));  

  89.                     table.put(put);  

  90.                  flag = true;  

  91.                 }catch(Exception e){  

  92.                     e.printStackTrace();  

  93.                 }  

  94.                 return flag;  

  95.             }  

  96.         });  

  97.     }    

  98.      /** 

  99.       * 通过表名和key获取一行数据 

  100.       * @param tableName 

  101.       * @param rowName 

  102.       * @return 

  103.       */  

  104.     public Map<String, Object> get(String tableName, String rowName) {  

  105.          return htemplate.get(tableName, rowName,new RowMapper<Map<String,Object>>(){  

  106.                public Map<String,Object> mapRow(Result result, int rowNum) throws Exception {      

  107.                    List<Cell> ceList =   result.listCells();  

  108.                    Map<String,Object> map = new HashMap<String, Object>();  

  109.                         if(ceList!=null&&ceList.size()>0){  

  110.                             for(Cell cell:ceList){  

  111.                                 map.put(Bytes.toString(cell.getFamilyArray(),cell.getFamilyOffset(),cell.getFamilyLength())+  

  112.                                    "_"+Bytes.toString( cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength()),   

  113.                                    Bytes.toString( cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));  

  114.                        }  

  115.                    }  

  116.                     return  map;  

  117.                }  

  118.              });  

  119.     }  

  120.       

  121.     /** 

  122.      * 通过表名  key 和 列族 和列 获取一个数据 

  123.      * @param tableName 

  124.      * @param rowName 

  125.      * @param familyName 

  126.      * @param qualifier 

  127.      * @return 

  128.      */  

  129.     public String get(String tableName ,String rowName, String familyName, String qualifier) {  

  130.           return htemplate.get(tableName, rowName,familyName,qualifier ,new RowMapper<String>(){  

  131.                  public String mapRow(Result result, int rowNum) throws Exception {     

  132.                      List<Cell> ceList =   result.listCells();  

  133.                      String res = "";  

  134.                      if(ceList!=null&&ceList.size()>0){  

  135.                          for(Cell cell:ceList){  

  136.                              res = Bytes.toString( cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());  

  137.                          }  

  138.                      }  

  139.                    return res;  

  140.                  }  

  141.           });  

  142.     }  

  143.       

  144.       

  145.      /** 

  146.       * 通过表名,开始行键和结束行键获取数据 

  147.       * @param tableName 

  148.       * @param startRow 

  149.       * @param stopRow 

  150.       * @return 

  151.       */  

  152.     public List<Map<String,Object>> find(String tableName , String startRow,String stopRow) {  

  153.          Scan scan = new Scan();  

  154.          if(startRow==null){  

  155.              startRow="";  

  156.          }  

  157.          if(stopRow==null){  

  158.              stopRow="";      

  159.          }  

  160.          scan.setStartRow(Bytes.toBytes(startRow));  

  161.          scan.setStopRow(Bytes.toBytes(stopRow));  

  162.         /* PageFilter filter = new PageFilter(5); 

  163.          scan.setFilter(filter);*/  

  164.          return     htemplate.find(tableName, scan,new RowMapper<Map<String,Object>>(){  

  165.                public Map<String,Object> mapRow(Result result, int rowNum) throws Exception {   

  166.                     

  167.                      List<Cell> ceList =   result.listCells();  

  168.                      Map<String,Object> map = new HashMap<String,Object>();  

  169.                      Map<String,Map<String,Object>> returnMap = new HashMap<String,Map<String,Object>>();  

  170.                      String  row = "";  

  171.                      if(ceList!=null&&ceList.size()>0){  

  172.                            for(Cell cell:ceList){  

  173.                             row =Bytes.toString( cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());  

  174.                             String value =Bytes.toString( cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());  

  175.                             String family =  Bytes.toString(cell.getFamilyArray(),cell.getFamilyOffset(),cell.getFamilyLength());  

  176.                             String quali = Bytes.toString( cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength());  

  177.                             map.put(family+"_"+quali, value);  

  178.                            }  

  179.                            map.put("row",row );  

  180.                        }  

  181.                        return  map;  

  182.                    }  

  183.                  });  

  184.     }  

  185.   

  186.       

  187.     /* public  void scanValueByFilter(String tableName,String row) throws IOException{ 

  188.          HTable table = new HTable(conf, tableName);   

  189.          Scan scan = new Scan(); 

  190.          scan.setFilter(new PrefixFilter(row.getBytes())); 

  191.          ResultScanner resultScanner = table.getScanner(scan); 

  192.          for(Result rs:resultScanner){ 

  193.      

  194.               

  195.          } 

  196.           

  197.      }*/  

  198. }  

下载

具体可运行代码下载地址   http://download.csdn.net/detail/linlinv3/8580185

项目目录结构和所需jar包如下图所示:



六、HBase Object Mapper

介绍

这个紧凑型实用程序库是一个基于注释的HBase 对象映射器(用Java编写),可帮助您:

  • 将bean类的对象转换为HBase行,反之亦然

  • 用于从HBase表读取和/或写入Hadoop MapReduce作业

  • 并编写有效的单元测试MapperReducer

  • 定义映射到HBase行的实体的数据访问对象

  • 用于HBase表的行的单次/范围/批量访问


七、simplehbase

是阿里巴巴的一个开源项目。15年之后就不更新了,既然是阿里大神写的,应该不会太差,易用性更符合国情!

simplehbase是java和hbase之间的轻量级中间件。 主要包含以下功能。

  • 数据类型映射:java类型和hbase的bytes之间的数据转换。

  • 简单操作封装:封装了hbase的put,get,scan等操作为简单的java操作方式。

  • hbase query封装:封装了hbase的filter,可以使用sql-like的方式操作hbase。

  • 动态query封装:类似于myibatis,可以使用xml配置动态语句查询hbase。

  • insert,update支持: 建立在hbase的checkAndPut之上。

  • hbase多版本支持:提供接口可以对hbase多版本数据进行查询,映射。

  • hbase批量操作支持。

  • hbase原生接口支持。

  • HTablePool管理。

  • HTable count和sum功能。


八、参考博客

Phoenix综述(史上最全Phoenix中文文档):

http://www.cnblogs.com/linbingdong/p/5832112.html

 

ORM-HBASE 一个轻量级映射框架

 http://blog.csdn.net/shifenglov/article/details/50772636

 

hbase是否能取代mysql

 http://blog.csdn.net/cqboy1991/article/details/26366781

GitHub一个外国大神封装的hbase的ORM层:hbase-object-mapper/

https://flipkart-incubator.github.io/hbase-object-mapper/

simplehbase 阿里大神开发的,知识库:

https://github.com/alibaba/simplehbase/wiki/_pageshbase-object-mapper

打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » 让我们一起来了解前端应用怎么开发Hbase

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!