Hadoop lzo找不到Native库解决方法

Hadoop lzo相关的错误有两个,分别为:

  1. Could not load native gpl library
  2. native-lzo library not available
    下面会分别说明

Could not load native gpl library

很多HBase用户在用BulkLoad从Hadoop往HBase导入数据的时候,会遇到如下情况。报hadoop lzo找不到gplcompression的错误。

1
2
3
4
5
6
ERROR lzo.GPLNativeCodeLoader: Could not load native gpl library
java.lang.UnsatisfiedLinkError: no gplcompression in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at com.Hadoop.compression.lzo.GPLNativeCodeLoader.<clinit>

这个错误是因为生成HFile的时候开启了LZO压缩,开启LZO压缩可以有效的减少HFile大小(压缩比平均20%),有效减少distcp传输时间。但由于云梯1的java.library.path路径下并不包含gplcompression这个Native库,所以若生成HFile时开启LZO,则会报如上错误。解决方法很简单,将hadoop-lzo-0.4.20-mr1(MapReduce 1编译版本)或hadoop-lzo-0.4.20(MapReduce 2编译版本)下载的jar包加入到-libjars参数重新执行即可。

原因是hadoop-lzo的作者考虑到了上述情况,所以直接将gplcompression打包进了jar中。查看hadoop-lzo-0.4.20-mr1.jar可发现,gplcompression的Native库,都已经加入到jar包中的 native/Linux-amd64-64/lib下面

1
2
3
4
5
6
7
8
9
$: jar -tf hadoop-lzo-0.4.20-mr1.jar |grep native
native/
native/Linux-amd64-64/
native/Linux-amd64-64/lib/
native/Linux-amd64-64/lib/libgplcompression.a
native/Linux-amd64-64/lib/libgplcompression.la
native/Linux-amd64-64/lib/libgplcompression.so.0.0.0
native/Linux-amd64-64/lib/libgplcompression.so.0
native/Linux-amd64-64/lib/libgplcompression.so

hadoop-lzo的实现中会先将gplcompression的Native库从jar包中解压到临时地址,并load进该库。详细代码可参见作者托管在Github上的代码GPLNativeCodeLoader#unpackBinaries

1
2
3
4
5
// locate the binaries inside the jar
String fileName = System.mapLibraryName(LIBRARY_NAME);
String directory = getDirectoryLocation();
// use the current defining classloader to load the resource
InputStream is = GPLNativeCodeLoader.class.getResourceAsStream(directory + "/" + fileName);

native-lzo library not available

另一个与Hadoop lzo常见的错误是:

1
java.lang.RuntimeException: native-lzo library not available

这个错误是执行你的写HDFS程序的机器没有安装lzo-devel,程序在LD_LIBRARY_PATH下找不到liblzo2.so.2导致的,在该机器上执行如下命令安装即可。

1
yum install lzo lzo-devel

或者直接到已安装lzo的机器上将/usr/lib64/liblzo2.so.2下到本地,然后代码中手动load即可。

1
System.load(liblzo2.so.2的存放地址);