向Hbase插入时,报错java.lang.IllegalArgumentException: KeyValue size too large的解决办法

来源:互联网 发布:如何制作淘宝网店 编辑:程序博客网 时间:2024/05/17 05:57

最近在向Hbase中插入数据时, 报了个KeyValue size too large 的错误,  具体报错信息如下:

Error: java.lang.IllegalArgumentException: KeyValue size too largeat org.apache.hadoop.hbase.client.HTable.validatePut(HTable.java:1567)at org.apache.hadoop.hbase.client.BufferedMutatorImpl.validatePut(BufferedMutatorImpl.java:152)at org.apache.hadoop.hbase.client.BufferedMutatorImpl.mutate(BufferedMutatorImpl.java:127)at org.apache.hadoop.hbase.client.BufferedMutatorImpl.mutate(BufferedMutatorImpl.java:113)at org.apache.hadoop.hbase.mapreduce.TableOutputFormat$TableRecordWriter.write(TableOutputFormat.java:138)at org.apache.hadoop.hbase.mapreduce.TableOutputFormat$TableRecordWriter.write(TableOutputFormat.java:94)at org.apache.hadoop.mapred.ReduceTask$NewTrackingRecordWriter.write(ReduceTask.java:558)at org.apache.hadoop.mapreduce.task.TaskInputOutputContextImpl.write(TaskInputOutputContextImpl.java:89)at org.apache.hadoop.mapreduce.lib.reduce.WrappedReducer$Context.write(WrappedReducer.java:105)at com.dxyun.dxdp.activity.tempScript.countMaxInvNumSingleTel.reducer.CountMaxNumReducer.reduce(CountMaxNumReducer.java:50)at com.dxyun.dxdp.activity.tempScript.countMaxInvNumSingleTel.reducer.CountMaxNumReducer.reduce(CountMaxNumReducer.java:20)at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:171)at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:627)at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:389)at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164)at java.security.AccessController.doPrivileged(Native Method)at javax.security.auth.Subject.doAs(Subject.java:422)at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1693)at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
根据错误信息提示,找到源码中的 validatePut 方法:
public static void validatePut(Put put, int maxKeyValueSize) throws IllegalArgumentException {        if (put.isEmpty()) {            throw new IllegalArgumentException("No columns to insert");        } else {            if (maxKeyValueSize > 0) {                Iterator i$ = put.getFamilyCellMap().values().iterator();                while(i$.hasNext()) {                    List<Cell> list = (List)i$.next();                    Iterator i$ = list.iterator();                    while(i$.hasNext()) {                        Cell cell = (Cell)i$.next();                        if (KeyValueUtil.length(cell) > maxKeyValueSize) {                            throw new IllegalArgumentException("KeyValue size too large");                        }                    }                }            }        }    }

在源码中我们发现,在进行插入操作的时候,hbase会挨个检查要插入的列,检查每个列的大小是否小于 maxKeyValueSize值,当cell的大小大于maxKeyValueSize时,就会抛出KeyValue size too large的异常。问题定位到了,下面看这个maxKeyValueSize值是在哪里设定的。在validatePut方法所在的同一个类(HTable.class)中,可以找到maxKeyValueSize的信息:

public static int getMaxKeyValueSize(Configuration conf) {        return conf.getInt("hbase.client.keyvalue.maxsize", -1);    }
在上述方法中可以看出,maxKeyValueSize的值是在配置文件中配置的,配置参数的key值就是:hbase.client.keyvalue.maxsize。

在官网,我查到了关于hbase.client.keyvalue.maxsize的描述信息:

hbase.client.keyvalue.maxsize一个KeyValue实例的最大size.这个是用来设置存储文件中的单个entry的大小上界。因为一个KeyValue是不能分割的,所以可以避免因为数据过大导致region不可分割。
明智的做法是把它设为可以被最大region size整除的数。如果设置为0或者更小,就会禁用这个检查。默认10MB。默认: 10485760
也就是说,hbase.client.keyvalue.maxsize 的默认大小是10M,如果cell的大小超过10M,那么就会报 KeyValue size too large的错误。

解决方法:

方法一、根据官网提示,修改配置文件hbase-default.xml ,调大hbase.client.keyvalue.maxsize  的值: 

<property>    <name>hbase.client.keyvalue.maxsize</name>    <value>20971520</value>  </property>
不建议通过直接修改配置文件的方式修改。改完后,需重启hbase(需不需要重启?带验证)

方法二:修改代码,使用configuration对象修改此配置:

Configuration conf = HBaseConfiguration.create();  conf.set("hbase.client.keyvalue.maxsize","20971520");
推荐此种方式。

附:Hbase 官方文档(中文)地址


阅读全文
0 0