HBase用户福利
新用户9.9元即可使用6个月云数据库HBase,更有低至1元包年的入门规格供广大HBase爱好者学习研究,更多内容请参考链接
阿里云HBase SQL服务简介
云HBase2.0是阿里云对社区HBase2.0的深度定制,在内核层面做了大量优化升级,并提供全球多活、备份恢复、冷存储等企业级特性,目前已被广泛应用于车联网、社交、推荐、画像等场景。阿里云HBase SQL基于Phoenix 5.0版本,为云HBase2.0赋予NewSQL特性,降低kv接口使用复杂性,并提供Schema、Secondary Indexes、View 、Bulk Loading(离线大规模load数据)、Atomic Upsert、Salted Tables、Dynamic Columns、Skip Scan等特性的能力,大大降低了用户的使用门槛(关于更多Phoenix的介绍可以参考:HBase进化之从NoSQL到NewSQL,凤凰涅槃成就Phoenix)。阿里云HBase团队将SQL能力服务化,在产品、内核上做了一系列优化升级,笔者将在本文中对这些特性做深度解读。
HBase SQL服务化
HBase SQL服务如图所示,用户在阿里云HBase实例管理页面可以一键开通,并在界面进行配置、重启、升级,获取URL串之后直接可以访问。用户可以使用Java、Python、Go、C#开发应用程序访问SQL服务,也可以使用命令行工具直接访问SQL服务,详细使用说明,可以参考我们的文档:SQL服务使用文档。使用过Phoenix的开发者都知道,Phoenix社区提供两种访问方式,重客户端和轻客户端,关于这两者之间的区别,可以参考:Phoenix客户端进化之由重到轻。除了将Phoenix服务化外,我们还做了一系列优化升级,既有对轻客户端的优化升级,也有对Phoenix Core本身的优化升级。
轻客户端优化
云HBase SQL团队针对社区Phoenix5.0版本进行深度测试,对轻客户端进行了一系列的优化和bug fix,并反馈给Phoenix和Avatica社区,推动社区共同发展。
1.轻客户端写性能优化
在对轻客户端的写入性能测试时,我们发现社区轻客户端的写入性能比直接使用重客户端慢2~3倍,主要原因正式由于轻客户端相比重客户端多了一层HTTP传输链路,因此在尽量不修改业务代码的前提下,如何减少请求次数是优化写性能的重点。
在业务代码中经常使用jdbc的PreparedStatement的executeUpdate进行写入,社区轻客户端在autoCommit为false时会将数据传输至QueryServer并缓存,在commit时将数据batch写入到HBase中。阿里云Phoenix修改了executeUpdate执行逻辑,将数据缓存在客户端,commit时将批量数据发到QueryServer并直接写入HBase,在这一阶段减少了轻客户端到QueryServer的RPC请求次数,并避免缓存在QueryServer的数据在未提交前由于服务挂掉而丢失。
优化后在代码写入性能提升了2倍多,与重客户端性能基本没有差距。
2.支持upsert multi values语法
原生Phoenix在写入时仅支持单次upsert一条数据的语法,这在对接Mybatis等不支持commit的框架时,每次写入一条数据并提交HBase性能上较差,为此阿里云Phoenix在SQL服务上支持了单次upsert写入多值功能,语法示例:upsert into tableName(col1,col2,...) values (v11,v12,...),(v21,v22,...),...,(vn1,vn2,...)
在使用时注意:
- 为避免列次序混乱,必须指定写入列
- 写入数据其中一条失败导致整批数据写入失败
3.支持QueryServer线程池最大线程和HTTP传输参数可配
QueryServer使用Jetty做为HttpServer,在初始化时默认最大200个线程,在使用配置比较高的HBase集群时,往往由于处理线程数成为性能瓶颈,阿里云Phoenix修改了Avatica代码,通过增加配置方式使得线程数以及HTTP传输size大小等都可配,增加了Phoenix使用的灵活性,具体配置及说明如下:
参数名 | 描述 |
---|---|
phoenix.queryserver.maximun.threads | QueryServer最大线程数,默认200 |
phoenix.queryserver.minimum.threads | QueryServer最小线程数,默认8 |
phoenix.queryserver.idle.timeout | 线程空闲超时时间,默认60s |
phoenix.queryserver.maximum.header.size | HTTP请求包头大小,默认65536byte |
以上参数在云HBase控制台都可以进行修改,并重启HBase SQL服务后生效。
4.轻客户端Connection超时Reopen时设置参数丢失问题
轻客户端连接默认空闲10min会超时,下次使用时会进行重建,如果在超时前设置autoCommit、schema等连接属性会在reOpen时失效,这是社区avatica的一个bug,我们对此进行了修复,并贡献到社区,对应jira:https://issues.apache.org/jira/browse/CALCITE-2882 (贡献社区calcite-avatica 1.14.0版本)
5.轻客户端PrepareStatement预编译带有子查询/join语句时参数越界
在使用轻客户端PrepareStatement预编译SQL时会将phoenix客户端的ParamMetaData同步到轻客户端的Connection,当SQL带有子查询或join语句时,Phoenix在实现上缺失了右表的Meta信息,导致出现参数越界的问题。
阿里云的Phoenix版本也对此进行了修复,详细见jira:https://issues.apache.org/jira/browse/PHOENIX-5192
6.轻客户端写入Array类型数据NPE
轻客户端写入Array类型数据时由于获取Array中子元素的类型默认处理为空,导致在写入时出现NPE。问题修复见
jira:https://issues.apache.org/jira/browse/CALCITE-2939 (贡献社区calcite-avatica 1.14.0版本)
Phoenix Core优化与改进
我们对Phoenix Core做了大量稳定性、性能方面的优化和改进,提交了数十个patch给社区,团队的瑾谦同学也成为了Phoenix社区的Commiter。下面介绍几个比较有代表性的改进工作:
1.大表MetaCache缓存优化
Phoenix每次查询都需要使用表的所有region信息,当表很大有上万个region时,读取meta表的region信息并缓存到客户端需要耗时几十秒,占用查询时间超过80%以上。阿里云Phoenix使用ZooKeeper订阅的方式,通过监控Region的状态变化,当Region发生balance/merge/split动作时,更新客户端缓存失效的region信息,这样可以大大减少客户端因为Region元数据更新不及时导致的查询失败,同时显著提高查询性能。
优化效果:经过测试对一张大表查询时如果出现Region状态变化,查询时延由40s降低到5s左右。
2.使用Lookup Join提升大表的索引表回查性能
如果Phoenix二级索引不是覆盖索引,也就是说SELECT语句中的返回字段不在索引表中,那么在执行过程中会先查询索引表,获取RowKey,然后再用SemiJoin主表的方式获取最终结果。除了索引表本身的Scan开销外,还存在网络开销和SemiJoin本身的开销。我们采用Lookup Join的方式进行优化,在服务端scan索引表的时候,直接回查主表。经过测试,性能有大幅提高,500w数据量的查询,原有方式需要200s,而新的方式只需要10s,如果主表开启了bloomfilter,性能还能进一步提高到5s左右。
3.使用MultiGet取代SkipScan
Phoenix在执行SemiJoin的时候会使用SkipScan的方式,该方式比较通用,scan的过程中会skip掉一定的读HFile开销,但是当SemiJoin的查询条件比较多并且比较分散时,就转变为了近似扫全表,这时性能就会下降严重,甚至超时。对于这种情况,我们采用了MultiGet的方式取代SkipScan会获得更好的性能。当用户对Primary Key做in查询时,可以通过添加“USE_GET”的hint使用该功能,可以支持10w级别的子查询结果。在查询条件比较多并且分散的情况,会有数量级的性能提升。
4.临时禁止掉存在风险的功能feature
社区Phoenix功能很多很全,但是某些功能存在一定缺陷,或者会引入风险,在确保功能完善可用之前,我们会选择将部分功能禁掉,以避免用户误用,导致错误。目前涉及到的功能有:
- ColumnDef中的DESC关键字。对于可变长度类型,比如varchar、decimal,该功能可能范围查询结果返回错误。
- 全表扫描。对于没有加查询条件的查询语句,可能会触发全表扫描,导致系统不稳定。
- Local Index。由于社区反馈和我们在实际支持用户的过程中发现的Local Index问题较多,而且大部分二级索引的场景,Global Index已经足够使用,因此我们临时禁掉了Local Index的功能。
5.时区问题解决
社区Phoenix在时区处理上的逻辑会导致用户的不同用法,写入数据和查询结果不一致。详见文章:Phoenix关于时区的处理方式说明
总结展望
阿里云HBase团队在SQL服务上持续深耕,不断在稳定性、易用性、功能以及性能上继续增强优化,并不断反馈社区,积极推动Phoenx社区的发展。从HBase的架构上来看,相比于其他NoSQL存储引擎,其在数据规模,扩展性上具有明显优势。跟大数据其他组件,比如,搜索引擎、分析引擎、消息引擎,会更紧密的结合,SQL服务也会在这方面进行更多的探索,满足用户在实际使用过程中遇到的复杂查询、复杂分析等需求。在这里可以预告下,我们基于HBase和Solr双引擎,支持复杂查询的Phoenix Search Index功能即将上线。