暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

修复Phoenix异步索引Bug时学到的小技巧

架构与英文 2020-04-15
1371

HBase不支持sql语法,让人觉得很难用,Phoenix的问世让用户使用SQL操作HBase变为了现实。PhoenixHBase表做了映射后,就可以直接使用phoenixSQL语法在HBase表上操作了。通常为了加速SQL语句的执行,我们会对表做索引操作。但是当HBase表有数亿行的时候,直接建立索引无疑会对HBase造成很大的影响。因此我们可以尝试建立异步索引去解决。

语法如下:

Hbaseorg.apache.phoenix.mapreduce.index.IndexTool –s “schema”  –dt  “data_table”–it “index_table” –op  output_path

但在Phoenix5.0之前的版本都存在一个问题,那就是无法对HBase中小写名字的表建立异步索引。

问题背景:江苏某局点的大数据平台(HBase3.0Phoenix5.0.x。客户的HBase单张表有数亿条业务数据,命名空间和表名都是小写,使用Phoenix做了表映射后,无法建立异步索引。

问题分析:接到客户问题后,我开始尝试在测试平台对问题复现,果然小写命名空间和表名,会提示找不到索引表。由于对Phoenix不是很熟悉,所以不得不打开Idea编译器,下载源码去查看,并一路远程DebugPhoenix使用的是java语言,远程Debug只需要在Phoenix进程上配置-agentlib参数和端口号就可以了)。

根据异常函数调用栈入口:


很快就定位到了是在IndexTool.java

语句中把“双引号”给解析丢了,该函数涉及的是第三方库,该库默认是对字符串去除双引号;再深入分析,发现后面又有两处会连续对传入的字符串进行去双引号处理,所以单纯的在parseOptions里更改还是无法解决问题。继续Debug发现Phoenix程序自己写的去双引号操作在SchemaUtil.javanormalizeIdentifier函数里。

其逻辑很简单,如果传入的是空则直接返回,如果是双引号括起来的字符串则去除双引号,其它则转为大写字符。

于是便打算在这个被调用的地方进行处理。对于该问题常用的思路有两种处理方法。

方法一:(最简单但会有隐患)

SchemaUtil.javanormalizeIdentifie()函数里直接把return  name.toUpperCase()改为 return name就是不让其再去转换为大写,输入的是什么就是什么。


由于该函数是工具类,会有很多的地方调用,冒然改掉或许会有隐患存在。(不推荐)

方法二:(较麻烦但安全)

就是在IndexTool.java里添加一个自定义参数的解析(忽略大小写ignore=true);执行异步索引命令时带上ignore=true参数,然后对命令行进行解析,当读取到ignore参数为true时就不再执行大小写转换。更改后SchemaUtil.javanormalizeIdentifie()如下:

这貌似是一种可行的方案,但是改如何改呢,因为在IndexTool.java里有很多函数间接调用SchemaUtil.javanormalizeIdentifie()。如:

如果直接在源文件更改,需要重写大量的接口,很是麻烦,有没有方法可以绕过这些呢?  

必须有。 注意了, 要敲黑板了

在和同事的讨论中,突然看到源码里其它代码中有一个static变量,联想到static的性质,感觉static变量真的非常适合做这些事情,便尝试用static变量去改动。

static变量是Class的所有实例共享的,一个Class只能存在一份static数据。因此可以考虑在SchemaUtil.java文件里增加一个static变量。分析到IndexTool.java里面对参数的调用都是线程安全的,可不用考虑修改丢失问题。定义为public static boolean即可:


把ignore的默认值为false,则会消除对其它线程的影响,因为其它调用者不会对它解析,也就感知不到它的存在。在主文件IndexTool.java里面,我们添加对命令行的解析,当读取到命令行有ignore参数传入时就对其判断,如果是ignore=true,那么则赋值SchemaUtil.ignore = true; 具体代码逻辑实现如下:


由于static变量在所有实例只存在一份,那么当调用到SchemaUtil.javanormalizeIdentifie()函数时,便可感知到它ignore值的变化:

这样我们就不用改变任何函数调用接口,只需很小的改动就可以直接达到我们的目的,也不会对其它调用函数产生附加影响。

 

流行组件的源码都是很好的框架,通过对源码变量的跟踪调试可以学到很多的技巧。你若有什么好的技巧,欢迎分享。


文章转载自架构与英文,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论