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

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

Error: java.lang.IllegalArgumentException: KeyValue size too large
    at 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");
推荐此种方式。

扫描二维码关注公众号,回复: 5610703 查看本文章

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


原文:https://blog.csdn.net/u010476994/article/details/78436858 

猜你喜欢

转载自blog.csdn.net/u010499087/article/details/87882063
今日推荐