[ 
https://issues.apache.org/jira/browse/HBASE-22539?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16855688#comment-16855688
 ] 

Wellington Chevreuil commented on HBASE-22539:
----------------------------------------------

Symptoms:

Upon an RS crash that required log split/replay, RSes splitting WALs would 
eventually fail and crash with the following stack trace error:
{noformat}
ERROR org.apache.hadoop.hbase.executor.EventHandler: Caught throwable while 
processing event RS_LOG_REPLAY
java.lang.ArrayIndexOutOfBoundsException: 18056
        at org.apache.hadoop.hbase.KeyValue.getFamilyLength(KeyValue.java:1365)
        at org.apache.hadoop.hbase.KeyValue.getFamilyLength(KeyValue.java:1358)
        at 
org.apache.hadoop.hbase.PrivateCellUtil.matchingFamily(PrivateCellUtil.java:735)
        at org.apache.hadoop.hbase.CellUtil.matchingFamily(CellUtil.java:816)
        at 
org.apache.hadoop.hbase.wal.WALEdit.isMetaEditFamily(WALEdit.java:143)
        at org.apache.hadoop.hbase.wal.WALEdit.isMetaEdit(WALEdit.java:148)
        at 
org.apache.hadoop.hbase.wal.WALSplitter.splitLogFile(WALSplitter.java:297)
        at 
org.apache.hadoop.hbase.wal.WALSplitter.splitLogFile(WALSplitter.java:195)
        at 
org.apache.hadoop.hbase.regionserver.SplitLogWorker$1.exec(SplitLogWorker.java:100)
{noformat}
 Trying to read given wal file with WalPP also gets:
{noformat}
Cell Codec Class: org.apache.hadoop.hbase.regionserver.wal.WALCellCodec
Exception in thread "main" java.lang.IllegalArgumentException: offset (537087) 
+ length (8) exceed the capacity of the array: 1066
        at 
org.apache.hadoop.hbase.util.Bytes.explainWrongLengthOrOffset(Bytes.java:830)
        at org.apache.hadoop.hbase.util.Bytes.toLong(Bytes.java:813)
        at org.apache.hadoop.hbase.util.Bytes.toLong(Bytes.java:798)
        at org.apache.hadoop.hbase.KeyValue.getTimestamp(KeyValue.java:1488)
        at org.apache.hadoop.hbase.KeyValue.getTimestamp(KeyValue.java:1479)
        at 
org.apache.hadoop.hbase.wal.WALPrettyPrinter.toStringMap(WALPrettyPrinter.java:359)
        at 
org.apache.hadoop.hbase.wal.WALPrettyPrinter.processFile(WALPrettyPrinter.java:305)
        at 
org.apache.hadoop.hbase.wal.WALPrettyPrinter.run(WALPrettyPrinter.java:444)
{noformat}
After applying the changes committed on [my fork branch 
HBASE-22539|https://github.com/wchevreuil/hbase/tree/HBASE-22539], the 
following exception logged on this cluster led to conclude the corruption 
happens when copying from BB to array 
[here|https://github.com/wchevreuil/hbase/blob/HBASE-22539/hbase-common/src/main/java/org/apache/hadoop/hbase/io/ByteBufferWriterOutputStream.java#L92]:
{noformat}
2019-05-30 13:10:26,240 WARN org.apache.hadoop.hbase.KeyValueUtil: Got a KV 
validation error while writing. Just logging it for now and allowing to 
continue:
java.lang.IllegalArgumentException: Invalid key length in KeyValue. 
keyLength=40723827, KeyValueBytesHex=...
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
...
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,
 offset=0, length=2098
        at 
org.apache.hadoop.hbase.KeyValueUtil.checkKeyValueBytes(KeyValueUtil.java:555)
        at 
org.apache.hadoop.hbase.KeyValueUtil.isBufferValid(KeyValueUtil.java:532)
        at 
org.apache.hadoop.hbase.io.ByteBufferWriterOutputStream.write(ByteBufferWriterOutputStream.java:99)
        at 
org.apache.hadoop.hbase.util.ByteBufferUtils.copyBufferToStream(ByteBufferUtils.java:451)
        at 
org.apache.hadoop.hbase.ByteBufferKeyValue.write(ByteBufferKeyValue.java:277)
        at org.apache.hadoop.hbase.KeyValueUtil.oswrite(KeyValueUtil.java:794)
        at 
org.apache.hadoop.hbase.regionserver.wal.WALCellCodec$EnsureKvEncoder.write(WALCellCodec.java:382)
        at 
org.apache.hadoop.hbase.regionserver.wal.ProtobufLogWriter.append(ProtobufLogWriter.java:54)
        at 
org.apache.hadoop.hbase.regionserver.wal.FSHLog.doAppend(FSHLog.java:302)
        at 
org.apache.hadoop.hbase.regionserver.wal.FSHLog.doAppend(FSHLog.java:67)
        at 
org.apache.hadoop.hbase.regionserver.wal.AbstractFSWAL.append(AbstractFSWAL.java:918)
        at 
org.apache.hadoop.hbase.regionserver.wal.FSHLog$RingBufferEventHandler.append(FSHLog.java:1082)
        at 
org.apache.hadoop.hbase.regionserver.wal.FSHLog$RingBufferEventHandler.onEvent(FSHLog.java:973)
        at 
org.apache.hadoop.hbase.regionserver.wal.FSHLog$RingBufferEventHandler.onEvent(FSHLog.java:881)
        at 
com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:129)
        at java.lang.Thread.run(Thread.java:748)
2019-05-30 13:10:26,293 WARN 
org.apache.hadoop.hbase.io.ByteBufferWriterOutputStream: DBB copy via unsafe is 
corrupt.
         DBB offset: 155
         bytes to copy: 2098
 Will check normal copy next... 
{noformat}
 

Note the check fails 
[here|https://github.com/wchevreuil/hbase/blob/HBASE-22539/hbase-common/src/main/java/org/apache/hadoop/hbase/io/ByteBufferWriterOutputStream.java#L99],
 where it's validating this *testBuf* byte[], which is an exact copy of the 
resulting array from *ByteBufferUtils.copyFromBufferToArray(this.buf, b, off + 
totalCopied, 0, bytesToCopy);* call 
[here|https://github.com/wchevreuil/hbase/blob/HBASE-22539/hbase-common/src/main/java/org/apache/hadoop/hbase/io/ByteBufferWriterOutputStream.java#L92].

When the check from line #99 fails (printing the first WARN with IAE and stack 
trace), it copies again from DBB to this test byte[], but instead of using 
*Unsafe.copyMemory*, it uses *ByteBuffer.get* method, and check the resulting 
byte[] on line #106, but this second validation passes. This leads to conclude 
the error happens on this *ByteBufferUtils.copyFromBufferToArray(this.buf, b, 
off + totalCopied, 0, bytesToCopy);* call, which uses Unsafe.copyMemory 
underneath it.

I can't see anything suspicious, however, on current implementation for 
*UnsafeCopy.unsafeCopy* (apart from minor improvement reported on HBASE-22496, 
which shouldn't be causing this corruption). A remote possibility could be due 
to thread contention, as I noticed Compaction executions happening at same 
time, and those would also rely on on *UnsafeCopy.unsafeCopy* calls, but that's 
a high guess, would think a bit unusual for this *UnsafeAccess.copyMemory* not 
be thread safe. Could it be an specific issue on this *UnsafeAccess.copyMemory* 
method? ** Maybe folks with better understanding of such implementation could 
share some useful insights here.

Additional observations:

1) The main workaround for now is to complete disable the usage of 
DirectByteBuffer and the need for unsafe copies by switching 
*hbase.rpc.server.impl* back to SimpleRpcServer. After applying this change and 
running for some weeks, no corruption has been observed.

2) RSes on the given cluster have been running on hosts suffering memory 
contention, including swapping has been observed. Ain't sure if that would be 
relevant for unsafe copy.

3) Prior to switching rpc server implementation, we had also suspected on 
AsyncFSWal, but switching to FSHLog didn't prevent given corruptions from 
re-occur. Those were only gone after the change applied on #1.

Special thanks to [~psomogyi], [~busbey], [~elserj] for the continuing 
assistance with this investigation.

 

> Potential WAL corruption due to Unsafe.copyMemory usage when DBB are in place
> -----------------------------------------------------------------------------
>
>                 Key: HBASE-22539
>                 URL: https://issues.apache.org/jira/browse/HBASE-22539
>             Project: HBase
>          Issue Type: Bug
>    Affects Versions: 2.1.1
>            Reporter: Wellington Chevreuil
>            Priority: Blocker
>
> Summary
> We had been chasing a WAL corruption issue reported on one of our customers 
> deployments running release 2.1.1 (CDH 6.1.0). After providing a custom 
> modified jar with the extra sanity checks implemented by HBASE-21401 applied 
> on some code points, plus additional debugging messages, we believe it is 
> related to DirectByteBuffer usage, and Unsafe copy from offheap memory to 
> on-heap array triggered 
> [here|https://github.com/apache/hbase/blob/branch-2.1/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java#L1157],
>  such as when writing into a non ByteBufferWriter type, as done 
> [here|https://github.com/apache/hbase/blob/branch-2.1/hbase-common/src/main/java/org/apache/hadoop/hbase/io/ByteBufferWriterOutputStream.java#L84].
> More details on the following comment.
>  



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to