Add the ability to write ConsumeQueue using fileChannel to prevent JVM crashes in some situations (#8403)

This commit is contained in:
rongtong
2024-07-22 17:20:11 +08:00
committed by GitHub
parent 6ecdc48223
commit 86d59d2485
6 changed files with 71 additions and 9 deletions
@@ -833,7 +833,13 @@ public class ConsumeQueue implements ConsumeQueueInterface, FileQueueLifeCycle {
}
}
this.setMaxPhysicOffset(offset + size);
return mappedFile.appendMessage(this.byteBufferIndex.array());
boolean appendResult;
if (messageStore.getMessageStoreConfig().isPutConsumeQueueDataByFileChannel()) {
appendResult = mappedFile.appendMessageUsingFileChannel(this.byteBufferIndex.array());
} else {
appendResult = mappedFile.appendMessage(this.byteBufferIndex.array());
}
return appendResult;
}
return false;
}
@@ -846,7 +852,12 @@ public class ConsumeQueue implements ConsumeQueueInterface, FileQueueLifeCycle {
int until = (int) (untilWhere % this.mappedFileQueue.getMappedFileSize());
for (int i = 0; i < until; i += CQ_STORE_UNIT_SIZE) {
mappedFile.appendMessage(byteBuffer.array());
if (messageStore.getMessageStoreConfig().isPutConsumeQueueDataByFileChannel()) {
mappedFile.appendMessageUsingFileChannel(byteBuffer.array());
} else {
mappedFile.appendMessage(byteBuffer.array());
}
}
}
@@ -419,6 +419,8 @@ public class MessageStoreConfig {
*/
private boolean readUnCommitted = false;
private boolean putConsumeQueueDataByFileChannel = true;
public boolean isEnabledAppendPropCRC() {
return enabledAppendPropCRC;
}
@@ -1832,4 +1834,12 @@ public class MessageStoreConfig {
public void setReadUnCommitted(boolean readUnCommitted) {
this.readUnCommitted = readUnCommitted;
}
public boolean isPutConsumeQueueDataByFileChannel() {
return putConsumeQueueDataByFileChannel;
}
public void setPutConsumeQueueDataByFileChannel(boolean putConsumeQueueDataByFileChannel) {
this.putConsumeQueueDataByFileChannel = putConsumeQueueDataByFileChannel;
}
}
@@ -97,14 +97,14 @@ public class DefaultMappedFile extends AbstractMappedFile {
protected long mappedByteBufferAccessCountSinceLastSwap = 0L;
/**
* If this mapped file belongs to consume queue, this field stores store-timestamp of first message referenced
* by this logical queue.
* If this mapped file belongs to consume queue, this field stores store-timestamp of first message referenced by
* this logical queue.
*/
private long startTimestamp = -1;
/**
* If this mapped file belongs to consume queue, this field stores store-timestamp of last message referenced
* by this logical queue.
* If this mapped file belongs to consume queue, this field stores store-timestamp of last message referenced by
* this logical queue.
*/
private long stopTimestamp = -1;
@@ -357,6 +357,24 @@ public class DefaultMappedFile extends AbstractMappedFile {
return false;
}
@Override
public boolean appendMessageUsingFileChannel(byte[] data) {
int currentPos = WROTE_POSITION_UPDATER.get(this);
if ((currentPos + data.length) <= this.fileSize) {
try {
this.fileChannel.position(currentPos);
this.fileChannel.write(ByteBuffer.wrap(data, 0, data.length));
} catch (Throwable e) {
log.error("Error occurred when append message to mappedFile.", e);
}
WROTE_POSITION_UPDATER.addAndGet(this, data.length);
return true;
}
return false;
}
/**
* @return The current flushed position
*/
@@ -840,7 +858,6 @@ public class DefaultMappedFile extends AbstractMappedFile {
this.stopTimestamp = stopTimestamp;
}
public Iterator<SelectMappedBufferResult> iterator(int startPos) {
return new Itr(startPos);
}
@@ -101,12 +101,23 @@ public interface MappedFile {
/**
* Appends a raw message data represents by a byte array to the current {@code MappedFile}.
* Using mappedByteBuffer
*
* @param data the byte array to append
* @return true if success; false otherwise.
*/
boolean appendMessage(byte[] data);
/**
* Appends a raw message data represents by a byte array to the current {@code MappedFile}.
* Using fileChannel
*
* @param data the byte array to append
* @return true if success; false otherwise.
*/
boolean appendMessageUsingFileChannel(byte[] data);
/**
* Appends a raw message data represents by a byte array to the current {@code MappedFile}.
*
@@ -587,7 +587,12 @@ public class BatchConsumeQueue implements ConsumeQueueInterface {
MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile(this.mappedFileQueue.getMaxOffset());
if (mappedFile != null) {
boolean isNewFile = isNewFile(mappedFile);
boolean appendRes = mappedFile.appendMessage(this.byteBufferItem.array());
boolean appendRes;
if (messageStore.getMessageStoreConfig().isPutConsumeQueueDataByFileChannel()) {
appendRes = mappedFile.appendMessageUsingFileChannel(this.byteBufferItem.array());
} else {
appendRes = mappedFile.appendMessage(this.byteBufferItem.array());
}
if (appendRes) {
maxMsgPhyOffsetInCommitLog = offset;
maxOffsetInQueue = msgBaseOffset + batchSize;
@@ -262,7 +262,15 @@ public class SparseConsumeQueue extends BatchConsumeQueue {
this.byteBufferItem.putShort((short)0);
this.byteBufferItem.putInt(INVALID_POS);
this.byteBufferItem.putInt(0); // 4 bytes reserved
boolean appendRes = mappedFile.appendMessage(this.byteBufferItem.array());
boolean appendRes;
if (messageStore.getMessageStoreConfig().isPutConsumeQueueDataByFileChannel()) {
appendRes = mappedFile.appendMessageUsingFileChannel(this.byteBufferItem.array());
} else {
appendRes = mappedFile.appendMessage(this.byteBufferItem.array());
}
if (!appendRes) {
log.error("append end position info into {} failed", mappedFile.getFileName());
}