http://www.infoq.com/cn/articles/hbase-orm-simplehbase-design
目前企业软件开发占据主流的开发模式为面向对象模式。无论是建立在集合论之上的传统关系型数据库,还是以CAP定理/Hadoop/BigTable为基石的HBase,都面临以下的基本问题:
简而言之,数据存储如何提供增、删、改、查的服务能力,应用如何方便的使用该能力。关系型数据库给出的答案为SQL,JDBC和各种ORM框架(典型例子为Hibernate和MyBatis)。
ORM即Object-Relational mapping,对于HBase而言不存在Relational,因此该名称不准确,只是ORM做为一个术语使用太过广泛,这里泛指数据存储和Object之间的映射。
HBase的设计和RDBMS差异较大,因此除了上一小节的问题外,还需要解决如下问题:
本文着重介绍HBase ORM SimpleHBase框架,并和另一个HBase ORM Phoenix(http://phoenix.incubator.apache.org/)做比较。
SimpleHBase(https://github.com/zhang-xzhi/simplehbase)是Java和HBase之间的轻量级中间件,主要包含以下功能:
Phoenix的设计理念为:We put the SQL back into NoSql。该理念的优点如下:
该理念的缺点如下:
SimpleHBase的设计理念为:贴近HBase的ORM设计,简化HBase之上的Java app开发。
该理念的优点如下:
该理念的缺点如下:
1. 不兼容SQL,有一定的学习成本。
SimpleHBase和Phoenix的技术栈如下所示。
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和类型映射如下:
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); |
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 |
() |
对于group by, join等较为复杂的SQL语法,Phoenix支持,SimpleHBase目前不支持。
动态查询可以避免应用代码中大量if-else之类的判断,拼接查询条件,提高代码质量。
Phoenix的方案:
引入其他ORM框架(如hibernate或mybatis)。
Simplehbase的方案:
类似mybatis,提供动态查询能力。
目前simplehbase提供的动态查询标签如下:
isNull isNotNull isEmpty isNotEmpty isPropertyAvailable isNotPropertyAvailable |
isEqual isNotEqual isGreaterThan isGreaterEqual isLessThan isLessEqual |
Dynamic |
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支持如下映射方式:
Person(name=d) Person(name=c,age=3) Person(age=2) Person(name=a,age=1)
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上。