文章来源:http://www.open-open.com/lib/view/open1421501717312.htmlhtml
实现目的:java
因为hbase基于行健有序存储,在查询时使用行健十分高效,而后想要实现关系型数据库那样能够随意组合的多条件查询、查询总记录数、分页等就比较麻烦了。想要实现这样的功能,咱们能够采用两种方法:shell
第一种方法很少说了,使用起来很方便,可是局限性也很大,hbase的filter是直接扫记录的,若是数据范围很大,会致使查询速度很慢.
因此若是能先使 用行健把记录缩小到一个较小范围,那么就比较适合,不然就不适用了.此外该方法不能解决获取总数的为.数据库
第二种是适用范围就比较普遍了,不过根据实现二级索引的方式解决的问题也不一样.这里咱们选择solr主要是由于solr能够很轻松实现各类查询(原本就是全文检索引擎).异步
实现思路:post
其实hbase结合solr实现方法仍是比较简单的,重点在于一些实现细节上.性能
将hbase记录写入solr的关键就在于hbase提供的Coprocessor,Coprocessor提供了两个实现:endpoint和observer,
endpoint至关于关系型数据库的存储过程,而observer则至关于 触 发器.说到这相信你们应该就明白了,咱们要利用的就是observer.
observer容许咱们在记录put先后作一些处理,而咱们就是经过postPut将记录同步写入solr(关于Coprocessor具体内容请自行查资料).测试
而写入solr这块就比较简单了,主要是要考虑性能!默认状况下hbase每写一条数据就会向出发一次postPut,
若是直接提交个solr,速度会很是慢,并且若是有异常处理起来也会很是的麻烦.所以要本身实现一个本地可持久化的队列,经过后台线程异步向向solr提交.spa
限制:不能单独删除指定的列簇(${Family})
,必须是删除行(Row)
,或者删除指定的列(${Family}#${Qualifier})
!线程
部署:
<dynamicField name="*_i" type="int" indexed="true" stored="true"/> <dynamicField name="*_l" type="long" indexed="true" stored="true"/> <dynamicField name="*_f" type="float" indexed="true" stored="true"/> <dynamicField name="*_d" type="double" indexed="true" stored="true"/> <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/> <dynamicField name="*_s" type="string" indexed="true" stored="true" /> <dynamicField name="*_t" type="text_general" indexed="true" stored="true"/> <dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
solr里的每一条Dcoument对应HBase表里的一条记录
每一条Dcoument里缺省都会有4个字段: id
格式是:${TableName}#${RowKey}
t_s
格式是:${TableName}
r_s
格式是:${RowKey}
u_dt
格式是:${d当前更新时的日期和时间}
其余字段格式是:${Family}#${Qualifier}
若是HBase表里的字段须要在solr里索引,那么Qualifier
设计为已_(i|l|f|d|b|s|t|dt)
结尾的solr动态字段!
在master hbase server上执行:
${HBASE_HOME}/bin/stop-hbase.sh
Region Servers
的$(HBASE_HOME}/conf/hbase-site.xml
配置文件:在最后添加:
<!-- 调试时,将hbase的hbase.coprocessor.abortonerror设置成true,待肯定Coprocessor运行正常后在改成false. 此步骤非必要,可是若是Coprocessor有问题会致使全部Region Server没法启动! --> <property> <name>hbase.coprocessor.abortonerror</name> <value>true</value> </property> <!-- Solr Coprocessor --> <property> <name>hbase.coprocessor.region.classes</name> <value>wjw.hbase.solr.SolrRegionObserver</value> </property> <!-- 本地保存Queue的目录名,没有时使用:System.getProperty("java.io.tmpdir")得来的值 --> <property> <name>hbase.solr.queueDir</name> <value>/tmp</value> </property> <!-- Solr的URL,多个以逗号分隔 --> <property> <name>hbase.solr.solrUrl</name> <value>http://${solrHost1}:8983/solr/,http://${solrHost2}:8983/solr/</value> </property> <!-- core名字 --> <property> <name>hbase.solr.coreName</name> <value>hbase</value> </property> <!-- 链接超时(秒) --> <property> <name>hbase.solr.connectTimeout</name> <value>60</value> </property> <!-- 读超时(秒) --> <property> <name>hbase.solr.readTimeout</name> <value>60</value> </property>
在master hbase server上执行:
${HBASE_HOME}/bin/start-hbase.sh
/opt/hbase/bin/hbase shell >status >create 'demotable','col' >describe 'demotable' >list 'demotable' >put 'demotable','myrow-1','col:q1','value-1' >put 'demotable','myrow-1','col:q2_s','value-2-测试' >put 'demotable','myrow-1','col:name_t','张三 李四 王五' >put 'demotable','myrow-1','col:q3_s','value-3-测试' >scan 'demotable'