3

我有一个关于使用 timerange 进行 hbase 扫描的问题。我创建了一个“测试”表,它有一个系列“cf”和一个版本,在我将 4 行数据放入该表中后,并使用时间范围扫描该表,但是,我在时间范围内得到一个旧版本行。

例如:

 create 'test',{NAME=>'cf',VERSIONS=>1}
 put 'test','row1','cf:u','value1' 
 put 'test','row2','cf:u','value2'
 put 'test','row3','cf:u','value3'
 put 'test','row3','cf:u','value4'

然后我扫描这个表,以下是输出:

 hbase(main):008:0> scan 'test'
 ROW                                      COLUMN+CELL                                                                                                          
 row1                                    column=cf:u, timestamp=1340259691771, value=value1                                                                   
 row2                                    column=cf:u, timestamp=1340259696975, value=value2                                                                   
 row3                                    column=cf:u, timestamp=1340259704569, value=value4   

没错,row3 有最新版本。

但是,如果我使用 timerange 扫描它,我会得到:

  hbase(main):010:0> scan 'test',{TIMERANGE=>[1340259691771,1340259704569]}
  ROW                                      COLUMN+CELL                                                                                                          
  row1                                    column=cf:u, timestamp=1340259691771, value=value1                                                                   
  row2                                    column=cf:u, timestamp=1340259696975, value=value2                                                                   
  row3                                    column=cf:u, timestamp=1340259701085, value=value3     

它返回 row3 旧版本,但这张表我设置版本等于 1

如果我增加 maxtimestamp ,我得到:

  hbase(main):011:0> scan 'test',{TIMERANGE=>[1340259691771,1340259704570]}
  ROW                                      COLUMN+CELL                                                                                                          
  row1                                    column=cf:u, timestamp=1340259691771, value=value1                                                                   
  row2                                    column=cf:u, timestamp=1340259696975, value=value2                                                                   
  row3                                    column=cf:u, timestamp=1340259704569, value=value4                                                                   

0.0330 秒内 3 行

没错,我能理解。

我想要的是在一个时间范围内扫描一个表,它只返回最新版本,我知道有一个 TimestampsFilter,但是该过滤器只支持特定的时间戳,而不是时间范围。

有没有办法在一个时间范围内扫描一个表并且只返回最新的版本?

我尝试编写自己的时间范围过滤器,以下是我的代码。

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;

import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.FilterBase;
import org.apache.hadoop.hbase.filter.ParseFilter;

import com.google.common.base.Preconditions;  

public class TimeRangeFilter extends FilterBase {

private long minTimeStamp = Long.MIN_VALUE;
private long maxTimeStamp = Long.MAX_VALUE;

public TimeRangeFilter(long minTimeStamp, long maxTimeStamp) {
    Preconditions.checkArgument(maxTimeStamp >= minTimeStamp, "max timestamp %s must be big than min timestamp %s", maxTimeStamp, minTimeStamp);
    this.maxTimeStamp = maxTimeStamp;
    this.minTimeStamp = minTimeStamp;
}

@Override
public ReturnCode filterKeyValue(KeyValue v) {
    if (v.getTimestamp() >= minTimeStamp && v.getTimestamp() <= maxTimeStamp) {
        return ReturnCode.INCLUDE;
    } else if (v.getTimestamp() < minTimeStamp) {
        // The remaining versions of this column are guaranteed
        // to be lesser than all of the other values.
        return ReturnCode.NEXT_COL;
    }
    return ReturnCode.SKIP;
}

public static Filter createFilterFromArguments(ArrayList<byte[]> filterArguments) {
    long minTime, maxTime;
    if (filterArguments.size() < 2)
        return null;
    minTime = ParseFilter.convertByteArrayToLong(filterArguments.get(0));
    maxTime = ParseFilter.convertByteArrayToLong(filterArguments.get(1));
    return new TimeRangeFilter(minTime, maxTime);
}

@Override
public void write(DataOutput out) throws IOException {
    // TODO Auto-generated method stub
    out.writeLong(minTimeStamp);
    out.writeLong(maxTimeStamp);
}

@Override
public void readFields(DataInput in) throws IOException {
    // TODO Auto-generated method stub
    this.minTimeStamp = in.readLong();
    this.maxTimeStamp = in.readLong();
}

}

我将此 jar 添加到 hbase-env.sh 中的 hbase HBASE_CLASSPATH 中,但是,我收到以下错误:

org.apache.hadoop.hbase.client.ScannerCallable@a9255c,java.io.IOException:IPC 服务器无法读取调用参数:readFields 中的错误

4

3 回答 3

2
java.io.IOException: IPC server unable to read call parameters: Error in readFields

您需要将 jar 复制到所有区域服务器,并相应地在区域服务器上编辑 hbase-env.sh 中的 HBASE_CLASSPATH

您可以在 Scanner 上指定 timerange 和 MaxVersions 以获取时间范围内的旧版本

scan.setMaxVersions(Integer.MAX_VALUE);
scan.setTimeRange(startVersion, endVersion);
于 2013-02-05T05:33:36.387 回答
2

大佩,

当您将最大版本设置为 1 并且一个单元格有多个条目时,Hbase 会删除较旧的单元格并获取和扫描无法看到它们,除非您当然指定了一个特定的时间戳范围,该时间戳范围仅限定一个单元格。只有在对表运行 Major_compact 后才会删除墓碑单元格,此时旧单元格将停止弹出。

要始终从扫描中获取最新的单元格,您需要做的就是使用以下方法 -

    Result.getColumnLatest(family, qualifier)
于 2012-06-21T17:12:51.350 回答
1

我认为这与我在这里遇到的问题完全相同:HBase get return old values even with max versions = 1

原来是hbase的一个bug。请参阅:https ://issues.apache.org/jira/browse/HBASE-10102

于 2013-12-07T14:25:07.607 回答