分享

HBase ORM SimpleHBase设计

问题导读

1.SimpleHBase是Java和HBase之间的轻量级中间件,主要包含哪些功能?
2.SimpleHBase的设计理念为:贴近HBase的ORM设计,理念的优点是什么?






目前企业软件开发占据主流的开发模式为面向对象模式。无论是建立在集合论之上的传统关系型数据库,还是以CAP定理/Hadoop/BigTable为基石的HBase,都面临以下的基本问题:



  • 如何保存对象到数据存储?
  • 如何从数据存储获取对象?
  • 如何更新数据存储中的现有数据?数据存储的类型系统和开发语言(Java)的类型系统之间如何相互转换?


简而言之,数据存储如何提供增、删、改、查的服务能力,应用如何方便的使用该能力。关系型数据库给出的答案为SQL,JDBC和各种ORM框架(典型例子为Hibernate和MyBatis)。


0604001.png

HBase ORM

ORM即Object-Relational
mapping,对于HBase而言不存在Relational,因此该名称不准确,只是ORM做为一个术语使用太过广泛,这里泛指数据存储和Object之间的映射。


HBase的设计和RDBMS差异较大,因此除了上一小节的问题外,还需要解决如下问题:


  • 如何映射HTable的RowKey?
  • 如何映射HTable的bytes到Java类型?
  • 如何映射HTable的多版本能力?


本文着重介绍HBase ORM SimpleHBase框架,并和另一个HBase ORM Phoenix(http://phoenix.incubator.apache.org/)做比较。



SimpleHBase简介

SimpleHBase(https://github.com/zhang-xzhi/simplehbase)是Java和HBase之间的轻量级中间件,主要包含以下功能:


  • 数据类型映射:Java类型和HBase的bytes之间的数据转换。
  • 简单操作封装:封装了HBase的put,get,scan等操作为简单的Java操作方式。
  • HBase query封装:封装了HBase的filter,可以使用SQL-like的方式操作HBase。
  • 动态query封装:类似于mybatis,可以使用xml配置动态语句查询hbase。
  • insert,update支持: 建立在HBase的checkAndPut之上。
  • HBase多版本支持:提供接口可以对HBase多版本数据进行查询,映射。
  • HBase原生接口支持。
  • HTablePool管理。

设计理念

Phoenix的设计理念为:We put the SQL back into NoSql。该理念的优点如下:


  • SQL做为大众熟悉的API,用户学习成本较低。
  • 减少程序员的代码开发量。
  • 性能优化对用户透明。
  • 兼容既有的基于SQL的工具。


该理念的缺点如下:


  • SQL屏蔽了HBase和RDBMS设计上的差别,抽象泄露的风险较高。关于抽象泄露参考http://www.joelonsoftware.com/articles/LeakyAbstractions.html
  • 为了SQL兼容,引入了JDBC层。由于RDBM和HBase的设计与模型本身差异较大,引入JDBC后,导致部分HBase的特性难以友好的支持。
  • 大部分的应用不会直接使用JDBC,而是使用ORM,技术栈较深,导致抽象泄露问题更加严重。


SimpleHBase的设计理念为:贴近HBase的ORM设计,简化HBase之上的Java app开发。


该理念的优点如下:


  • 设计紧贴HBase的逻辑模型,提供一站式HBase ORM解决方案。
  • 减少程序员的代码开发量。
  • 用户友好的HBase特征支持。


该理念的缺点如下:


1. 不兼容SQL,有一定的学习成本。


SimpleHBase和Phoenix的技术栈如下所示。


060400.png

类型转换

Phoenix支持如下类型,目前不支持自定义类型。每种类型的序列化(转化为bytes保存到HBase中)和反序列化为固定的方式。


INTEGER


UNSIGNED_INT


BIGINT


UNSIGNED_LONG


TINYINT


UNSIGNED_TINYINT


SMALLINT


UNSIGNED_SMALLINT


FLOAT


UNSIGNED_FLOAT


DOUBLE


UNSIGNED_DOUBLE


DECIMAL


BOOLEAN


TIME


DATE


TIMESTAMP


UNSIGNED_TIME


UNSIGNED_DATE


UNSIGNED_TIMESTAMP


VARCHAR


CHAR


BINARY


VARBINARY





SimpleHBase支持如下类型。每种类型的序列化和反序列化方式,可以使用SimpleHBas提供的默认方式,也可以用户自定义。


boolean


byte


short


char


int


long


float


double


String


Date


Enum


用户自定义类型:


通过TypeHandler支持自定义类型扩展。





SimpleHBase的rowkey和类型映射如下:


0604003.png

RowKey支持

Phoenix把rowkey内化为table的PRIMARY KEY处理。





CREATE TABLE IF NOT EXISTS us_population ( state CHAR(2) NOT NULL, city
VARCHAR NOT NULL, population BIGINT CONSTRAINT my_pk PRIMARY KEY (state,
city));





同时,Phoenix的Salted Tables技术可以解决region server的热点问题。


SimpleHBase认为rowkey的设计是HBase应用设计中最重要的一环。因此,对于RowKey单独建模,给用户提供较高的灵活性。实际上,对于HBase而言,任何可以转换为bytes的对象都可以做为rowkey使用。

简单场景支持

对于简单的put,scan,delete场景。


Phoenix提供的方案为:


Java app -> ORM(可选) -> SQL -> phoenix -> HBase


SimpleHBase提供的方案为:


Java app -> SimpleHBase-> HBase


无需SQL这一层,直接用类似如下代码即可实现。


simpleHbaseClient.putObject(new PersonRowKey(1), person);


Person result = simpleHbaseClient.findObject(new PersonRowKey(1),


Person.class);




简单SQL支持

Phoenix做为HBase上面的SQL封装,这块的功能比较丰富。SimpleHBase提供SQL-Like方式的查询。支持常见的简单查询场景。目前,SimpleHBase提供的运算符如下:


lessequal


less


greaterequal


greater


notequal


equal


notmatch


match


in


notin


between


notbetween


isnull


Isnotnull


Ismissing


isnotmissing


and


or


()




复杂SQL支持

对于group by, join等较为复杂的SQL语法,Phoenix支持,SimpleHBase目前不支持。

动态SQL支持

动态查询可以避免应用代码中大量if-else之类的判断,拼接查询条件,提高代码质量。


Phoenix的方案:


引入其他ORM框架(如hibernate或mybatis)。


Simplehbase的方案:


类似mybatis,提供动态查询能力。


目前simplehbase提供的动态查询标签如下:


isNull


isNotNull


isEmpty


isNotEmpty


isPropertyAvailable


isNotPropertyAvailable


isEqual


isNotEqual


isGreaterThan


isGreaterEqual


isLessThan


isLessEqual


Dynamic




HBase时间戳和多版本支持

Phoenix方案:


时间戳,由HBase管理,或在connection建立时指定一个时间戳,该connection上所有操作就是基于该时间戳。


不支持多版本,只能支持最新值。


Simplehbase方案:


时间戳可以由HBase管理,或者由应用自行指定。版本数,可以选择最新版本,或者多版本支持,由应用指定。


rowkey


timestamp


name


Age


key1


t4


d


key1


t3


c


3


key1


t2


2


key1


t1


a


1





假设name和age映射为一个Person类型对象。SimpleHBase支持如下映射方式:


  • 一个rowkey对应的所有最新值映射为一个object。
        例:该数据被映射为Person(name=d,age=3)。
  • 一个rowkey对应的时间戳范围内(由用户指定)的最新值映射为一个object (Phoenix只提供一个时间戳,而不是时间戳范围) 。
       
    例:指定时间戳范围(左闭右开)为 [t1,t3),该数据被映射为Person(name=a,age=2)。
  • 一个rowkey对应的所有值,以时间戳为维度,映射成一个object list。
       
    例:指定maxVersion(控制最大版本数)为4,该数据被映射为一个person的列表,按照时间戳排序。    Person(name=d)Person(name=c,age=3)Person(age=2)Person(name=a,age=1)
  • 一个rowkey对应的时间戳范围内的所有值,以时间戳为维度,映射成一个object list。
        例:指定时间戳范围为
    [t1,t3),maxVersion为4,该数据被映射为一个person的列表,按照时间戳排序。    Person(age=2)Person(name=a,age=1)

其他

SimpleHBase中包含了一些HBase特性的封装或增强。


如:


SimpleHBase支持批量put操作,以提升性能。


HTable的autoflush设置为false,同时,有一个线程定期做flush。既可以提高应用的吞吐能力,也可以有一定的flush保证。




小结

目前,SimpleHBase已经在阿里的多个项目中得到应用。从设计理念看,SimpleHBase并不是Phoenix的一个重复轮子,而是有着自己清晰的目标。即贴近HBase的ORM设计,简化HBase之上的Java
app开发。同时,又可以把HBase的一些核心概念暴露给用户,方便用户对HBase特性的使用。

关于作者:

张信之,支付宝高级工程师,目前负责支付宝消费数据组,西安交通大学计算机科学与技术专业硕士。兴趣广泛,近期工作聚焦在HBase
ORM框架Simplehbase上。








已有(3)人评论

跳转到指定楼层
韩克拉玛寒 发表于 2014-11-22 14:35:32
回复

使用道具 举报

hb1984 发表于 2014-11-22 19:45:53
谢谢楼主分享。            
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条