[ https://issues.apache.org/jira/browse/HBASE-8778?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Dave Latham updated HBASE-8778: ------------------------------- Attachment: HBASE-8778-0.94.5.patch One solution is to instead keep the table descriptor files in a subdirectory of the table directory so that only that subdirectory needs a scan. The attached patch is one from 0.94.5 that implements this scheme. In order to be applicable in a rolling restart scenario, the new descriptor is written to both the table directory and the subdirectory. Readers first read the subdirectory, then fall back to the table directory. In order to be robust against failures or races, a lock file is used in the subdirectory during writes. The patch also refactors the FSTableDescriptors class to require a Configuration (to determine lock wait duration) as well as updates so that it more uniformly enforces the fsreadonly flag (RegionServers never do writes) and stick with using instance methods rather than static methods. We are proceeding with this and hope to roll it out to our cluster. To update to this patch once the writers (HBase Master, tools like hbck, merge, compact) are upgraded then old writers should not be used. I would love to hear the opinion of the HBase community regarding this issue. Some questions: - Is it worth fixing? (I strongly believe so as it has a big impact on MTTR for large clusters) - What's the best approach to fixing? - Some other possibilities: - Using a lock file and well known table descriptor file rather than sequence ids - Relying on more descriptor caching rather than hitting hdfs on every region assignment (as bulk assignment already does). - Move table descriptors to a different location in hdfs (single location for all tables?) - Move table descriptors out of hdfs to ZK - How and when can we migrate to that approach? - For the patch above once the cluster has been upgraded and updated the location of the descriptor files to have a copy in the subdirectory it would be easy to have the next version use only those files. - Alternatively, for the singularity there could be a one-time piece of migration code that just moved the files there. > Region assigments scan table directory making them slow for huge tables > ----------------------------------------------------------------------- > > Key: HBASE-8778 > URL: https://issues.apache.org/jira/browse/HBASE-8778 > Project: HBase > Issue Type: Improvement > Reporter: Dave Latham > Attachments: HBASE-8778-0.94.5.patch > > > On a table with 130k regions it takes about 3 seconds for a region server to > open a region once it has been assigned. > Watching the threads for a region server running 0.94.5 that is opening many > such regions shows the thread opening the reigon in code like this: > {noformat} > "PRI IPC Server handler 4 on 60020" daemon prio=10 tid=0x00002aaac07e9000 > nid=0x6566 runnable [0x000000004c46d000] > java.lang.Thread.State: RUNNABLE > at java.lang.String.indexOf(String.java:1521) > at java.net.URI$Parser.scan(URI.java:2912) > at java.net.URI$Parser.parse(URI.java:3004) > at java.net.URI.<init>(URI.java:736) > at org.apache.hadoop.fs.Path.initialize(Path.java:145) > at org.apache.hadoop.fs.Path.<init>(Path.java:126) > at org.apache.hadoop.fs.Path.<init>(Path.java:50) > at > org.apache.hadoop.hdfs.protocol.HdfsFileStatus.getFullPath(HdfsFileStatus.java:215) > at > org.apache.hadoop.hdfs.DistributedFileSystem.makeQualified(DistributedFileSystem.java:252) > at > org.apache.hadoop.hdfs.DistributedFileSystem.listStatus(DistributedFileSystem.java:311) > at > org.apache.hadoop.fs.FilterFileSystem.listStatus(FilterFileSystem.java:159) > at org.apache.hadoop.fs.FileSystem.listStatus(FileSystem.java:842) > at org.apache.hadoop.fs.FileSystem.listStatus(FileSystem.java:867) > at org.apache.hadoop.hbase.util.FSUtils.listStatus(FSUtils.java:1168) > at > org.apache.hadoop.hbase.util.FSTableDescriptors.getTableInfoPath(FSTableDescriptors.java:269) > at > org.apache.hadoop.hbase.util.FSTableDescriptors.getTableInfoPath(FSTableDescriptors.java:255) > at > org.apache.hadoop.hbase.util.FSTableDescriptors.getTableInfoModtime(FSTableDescriptors.java:368) > at > org.apache.hadoop.hbase.util.FSTableDescriptors.get(FSTableDescriptors.java:155) > at > org.apache.hadoop.hbase.util.FSTableDescriptors.get(FSTableDescriptors.java:126) > at > org.apache.hadoop.hbase.regionserver.HRegionServer.openRegion(HRegionServer.java:2834) > at > org.apache.hadoop.hbase.regionserver.HRegionServer.openRegion(HRegionServer.java:2807) > at sun.reflect.GeneratedMethodAccessor64.invoke(Unknown Source) > at > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) > at java.lang.reflect.Method.invoke(Method.java:597) > at > org.apache.hadoop.hbase.ipc.WritableRpcEngine$Server.call(WritableRpcEngine.java:320) > at > org.apache.hadoop.hbase.ipc.HBaseServer$Handler.run(HBaseServer.java:1426) > {noformat} > To open the region, the region server first loads the latest > HTableDescriptor. Since HBASE-4553 HTableDescriptor's are stored in the file > system at "/hbase/<tableDir>/.tableinfo.<sequenceNum>". The file with the > largest sequenceNum is the current descriptor. This is done so that the > current descirptor is updated atomically. However, since the filename is not > known in advance FSTableDescriptors it has to do a FileSystem.listStatus > operation which has to list all files in the directory to find it. The > directory also contains all the region directories, so in our case it has to > load 130k FileStatus objects. Even using a globStatus matching function > still transfers all the objects to the client before performing the pattern > matching. Furthermore HDFS uses a default of transferring 1000 directory > entries in each RPC call, so it requires 130 roundtrips to the namenode to > fetch all the directory entries. > Consequently, to reassign all the regions of a table (or a constant fraction > thereof) requires time proportional to the square of the number of regions. > In our case, if a region server fails with 200 such regions, it takes 10+ > minutes for them all to be reassigned, after the zk expiration and log > splitting. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira