HBASE-12332 [mob] improve how we resolve mobfiles in reads (Jingcheng Du and Jiajia Li)
This commit is contained in:
parent
2124d3df70
commit
45711ebaaf
|
@ -23,8 +23,10 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
@ -58,6 +60,7 @@ import org.apache.hadoop.hbase.regionserver.compactions.CompactionContext;
|
||||||
import org.apache.hadoop.hbase.regionserver.compactions.CompactionThroughputController;
|
import org.apache.hadoop.hbase.regionserver.compactions.CompactionThroughputController;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.HFileArchiveUtil;
|
import org.apache.hadoop.hbase.util.HFileArchiveUtil;
|
||||||
|
import org.apache.hadoop.hbase.util.IdLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The store implementation to save MOBs (medium objects), it extends the HStore.
|
* The store implementation to save MOBs (medium objects), it extends the HStore.
|
||||||
|
@ -90,10 +93,11 @@ public class HMobStore extends HStore {
|
||||||
private volatile long mobFlushedCellsSize = 0;
|
private volatile long mobFlushedCellsSize = 0;
|
||||||
private volatile long mobScanCellsCount = 0;
|
private volatile long mobScanCellsCount = 0;
|
||||||
private volatile long mobScanCellsSize = 0;
|
private volatile long mobScanCellsSize = 0;
|
||||||
private List<Path> mobDirLocations;
|
|
||||||
private HColumnDescriptor family;
|
private HColumnDescriptor family;
|
||||||
private TableLockManager tableLockManager;
|
private TableLockManager tableLockManager;
|
||||||
private TableName tableLockName;
|
private TableName tableLockName;
|
||||||
|
private Map<String, List<Path>> map = new ConcurrentHashMap<String, List<Path>>();
|
||||||
|
private final IdLock keyLock = new IdLock();
|
||||||
|
|
||||||
public HMobStore(final HRegion region, final HColumnDescriptor family,
|
public HMobStore(final HRegion region, final HColumnDescriptor family,
|
||||||
final Configuration confParam) throws IOException {
|
final Configuration confParam) throws IOException {
|
||||||
|
@ -103,11 +107,12 @@ public class HMobStore extends HStore {
|
||||||
this.homePath = MobUtils.getMobHome(conf);
|
this.homePath = MobUtils.getMobHome(conf);
|
||||||
this.mobFamilyPath = MobUtils.getMobFamilyPath(conf, this.getTableName(),
|
this.mobFamilyPath = MobUtils.getMobFamilyPath(conf, this.getTableName(),
|
||||||
family.getNameAsString());
|
family.getNameAsString());
|
||||||
mobDirLocations = new ArrayList<Path>();
|
List<Path> locations = new ArrayList<Path>(2);
|
||||||
mobDirLocations.add(mobFamilyPath);
|
locations.add(mobFamilyPath);
|
||||||
TableName tn = region.getTableDesc().getTableName();
|
TableName tn = region.getTableDesc().getTableName();
|
||||||
mobDirLocations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils
|
locations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils.getMobRegionInfo(tn)
|
||||||
.getMobRegionInfo(tn).getEncodedName(), family.getNameAsString()));
|
.getEncodedName(), family.getNameAsString()));
|
||||||
|
map.put(Bytes.toString(tn.getName()), locations);
|
||||||
if (region.getRegionServerServices() != null) {
|
if (region.getRegionServerServices() != null) {
|
||||||
tableLockManager = region.getRegionServerServices().getTableLockManager();
|
tableLockManager = region.getRegionServerServices().getTableLockManager();
|
||||||
tableLockName = MobUtils.getTableLockName(getTableName());
|
tableLockName = MobUtils.getTableLockName(getTableName());
|
||||||
|
@ -310,9 +315,28 @@ public class HMobStore extends HStore {
|
||||||
Cell result = null;
|
Cell result = null;
|
||||||
if (MobUtils.hasValidMobRefCellValue(reference)) {
|
if (MobUtils.hasValidMobRefCellValue(reference)) {
|
||||||
String fileName = MobUtils.getMobFileName(reference);
|
String fileName = MobUtils.getMobFileName(reference);
|
||||||
result = readCell(mobDirLocations, fileName, reference, cacheBlocks);
|
Tag tableNameTag = MobUtils.getTableNameTag(reference);
|
||||||
if (result == null) {
|
if (tableNameTag != null) {
|
||||||
result = readClonedCell(fileName, reference, cacheBlocks);
|
byte[] tableName = tableNameTag.getValue();
|
||||||
|
String tableNameString = Bytes.toString(tableName);
|
||||||
|
List<Path> locations = map.get(tableNameString);
|
||||||
|
if (locations == null) {
|
||||||
|
IdLock.Entry lockEntry = keyLock.getLockEntry(tableNameString.hashCode());
|
||||||
|
try {
|
||||||
|
locations = map.get(tableNameString);
|
||||||
|
if (locations == null) {
|
||||||
|
locations = new ArrayList<Path>(2);
|
||||||
|
TableName tn = TableName.valueOf(tableName);
|
||||||
|
locations.add(MobUtils.getMobFamilyPath(conf, tn, family.getNameAsString()));
|
||||||
|
locations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils
|
||||||
|
.getMobRegionInfo(tn).getEncodedName(), family.getNameAsString()));
|
||||||
|
map.put(tableNameString, locations);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
keyLock.releaseLockEntry(lockEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = readCell(locations, fileName, reference, cacheBlocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
@ -353,11 +377,18 @@ public class HMobStore extends HStore {
|
||||||
return file.readCell(search, cacheMobBlocks);
|
return file.readCell(search, cacheMobBlocks);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
mobCacheConfig.getMobFileCache().evictFile(fileName);
|
mobCacheConfig.getMobFileCache().evictFile(fileName);
|
||||||
if (e instanceof FileNotFoundException) {
|
if ((e instanceof FileNotFoundException) ||
|
||||||
|
(e.getCause() instanceof FileNotFoundException)) {
|
||||||
LOG.warn("Fail to read the cell, the mob file " + path + " doesn't exist", e);
|
LOG.warn("Fail to read the cell, the mob file " + path + " doesn't exist", e);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
mobCacheConfig.getMobFileCache().evictFile(fileName);
|
||||||
|
LOG.warn("Fail to read the cell", e);
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
mobCacheConfig.getMobFileCache().evictFile(fileName);
|
||||||
|
LOG.warn("Fail to read the cell", e);
|
||||||
} finally {
|
} finally {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
mobCacheConfig.getMobFileCache().closeFile(file);
|
mobCacheConfig.getMobFileCache().closeFile(file);
|
||||||
|
@ -365,43 +396,10 @@ public class HMobStore extends HStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.error("The mob file " + fileName + " could not be found in the locations "
|
LOG.error("The mob file " + fileName + " could not be found in the locations "
|
||||||
+ mobDirLocations);
|
+ locations);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the cell from a mob file of source table.
|
|
||||||
* The table might be cloned, in this case only hfile link is created in the new table,
|
|
||||||
* and the mob file is located in the source table directories.
|
|
||||||
* 1. The working directory of the source table.
|
|
||||||
* 2. The archive directory of the source table.
|
|
||||||
* Reads the cell from the files located in both of the above directories.
|
|
||||||
* @param fileName The file to be read.
|
|
||||||
* @param search The cell to be searched.
|
|
||||||
* @param cacheMobBlocks Whether the scanner should cache blocks.
|
|
||||||
* @return The found cell. Null if there's no such a cell.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private Cell readClonedCell(String fileName, Cell search, boolean cacheMobBlocks)
|
|
||||||
throws IOException {
|
|
||||||
Tag tableNameTag = MobUtils.getTableNameTag(search);
|
|
||||||
if (tableNameTag == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
byte[] tableName = tableNameTag.getValue();
|
|
||||||
if (Bytes.equals(this.getTableName().getName(), tableName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// the possible locations in the source table.
|
|
||||||
List<Path> locations = new ArrayList<Path>();
|
|
||||||
TableName tn = TableName.valueOf(tableName);
|
|
||||||
locations.add(MobUtils.getMobFamilyPath(conf, tn, family.getNameAsString()));
|
|
||||||
locations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils.getMobRegionInfo(tn)
|
|
||||||
.getEncodedName(), family.getNameAsString()));
|
|
||||||
// read the cell from the source table.
|
|
||||||
return readCell(locations, fileName, search, cacheMobBlocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the mob file path.
|
* Gets the mob file path.
|
||||||
* @return The mob file path.
|
* @return The mob file path.
|
||||||
|
|
|
@ -42,6 +42,8 @@ import org.apache.hadoop.hbase.HTableDescriptor;
|
||||||
import org.apache.hadoop.hbase.KeyValue;
|
import org.apache.hadoop.hbase.KeyValue;
|
||||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
|
import org.apache.hadoop.hbase.Tag;
|
||||||
|
import org.apache.hadoop.hbase.TagType;
|
||||||
import org.apache.hadoop.hbase.client.Get;
|
import org.apache.hadoop.hbase.client.Get;
|
||||||
import org.apache.hadoop.hbase.client.Scan;
|
import org.apache.hadoop.hbase.client.Scan;
|
||||||
import org.apache.hadoop.hbase.mob.MobConstants;
|
import org.apache.hadoop.hbase.mob.MobConstants;
|
||||||
|
@ -164,8 +166,8 @@ public class TestHMobStore {
|
||||||
KeyValue key3 = new KeyValue(row2, family, qf3, 1, value2);
|
KeyValue key3 = new KeyValue(row2, family, qf3, 1, value2);
|
||||||
KeyValue[] keys = new KeyValue[] { key1, key2, key3 };
|
KeyValue[] keys = new KeyValue[] { key1, key2, key3 };
|
||||||
int maxKeyCount = keys.length;
|
int maxKeyCount = keys.length;
|
||||||
StoreFile.Writer mobWriter = store.createWriterInTmp(currentDate,
|
StoreFile.Writer mobWriter = store.createWriterInTmp(currentDate, maxKeyCount,
|
||||||
maxKeyCount, hcd.getCompactionCompression(), region.getStartKey());
|
hcd.getCompactionCompression(), region.getStartKey());
|
||||||
mobFilePath = mobWriter.getPath();
|
mobFilePath = mobWriter.getPath();
|
||||||
|
|
||||||
mobWriter.append(key1);
|
mobWriter.append(key1);
|
||||||
|
@ -173,20 +175,15 @@ public class TestHMobStore {
|
||||||
mobWriter.append(key3);
|
mobWriter.append(key3);
|
||||||
mobWriter.close();
|
mobWriter.close();
|
||||||
|
|
||||||
int valueLength1 = key1.getValueLength();
|
|
||||||
int valueLength2 = key2.getValueLength();
|
|
||||||
int valueLength3 = key3.getValueLength();
|
|
||||||
|
|
||||||
String targetPathName = MobUtils.formatDate(currentDate);
|
String targetPathName = MobUtils.formatDate(currentDate);
|
||||||
byte[] referenceValue =
|
byte[] referenceValue = Bytes.toBytes(targetPathName + Path.SEPARATOR + mobFilePath.getName());
|
||||||
Bytes.toBytes(targetPathName + Path.SEPARATOR
|
Tag tableNameTag = new Tag(TagType.MOB_TABLE_NAME_TAG_TYPE, store.getTableName().getName());
|
||||||
+ mobFilePath.getName());
|
KeyValue kv1 = new KeyValue(row, family, qf1, Long.MAX_VALUE, referenceValue);
|
||||||
byte[] newReferenceValue1 = Bytes.add(Bytes.toBytes(valueLength1), referenceValue);
|
KeyValue kv2 = new KeyValue(row, family, qf2, Long.MAX_VALUE, referenceValue);
|
||||||
byte[] newReferenceValue2 = Bytes.add(Bytes.toBytes(valueLength2), referenceValue);
|
KeyValue kv3 = new KeyValue(row2, family, qf3, Long.MAX_VALUE, referenceValue);
|
||||||
byte[] newReferenceValue3 = Bytes.add(Bytes.toBytes(valueLength3), referenceValue);
|
seekKey1 = MobUtils.createMobRefKeyValue(kv1, referenceValue, tableNameTag);
|
||||||
seekKey1 = new KeyValue(row, family, qf1, Long.MAX_VALUE, newReferenceValue1);
|
seekKey2 = MobUtils.createMobRefKeyValue(kv2, referenceValue, tableNameTag);
|
||||||
seekKey2 = new KeyValue(row, family, qf2, Long.MAX_VALUE, newReferenceValue2);
|
seekKey3 = MobUtils.createMobRefKeyValue(kv3, referenceValue, tableNameTag);
|
||||||
seekKey3 = new KeyValue(row2, family, qf3, Long.MAX_VALUE, newReferenceValue3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue