Skip to content

KAFKA-6834: Handle compaction with batches bigger than max.message.bytes#4953

Merged
rajinisivaram merged 6 commits intoapache:trunkfrom
rajinisivaram:KAFKA-6834-log-cleaner
May 9, 2018
Merged

KAFKA-6834: Handle compaction with batches bigger than max.message.bytes#4953
rajinisivaram merged 6 commits intoapache:trunkfrom
rajinisivaram:KAFKA-6834-log-cleaner

Conversation

@rajinisivaram
Copy link
Copy Markdown
Contributor

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

@rajinisivaram rajinisivaram requested a review from junrao May 2, 2018 08:20
Copy link
Copy Markdown
Member

@ijuma ijuma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, left a few comments.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be CorruptRecordException too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only ever invoke this method from nextBatch() which has already done this check, or when growing log cleaner buffers beyond max.message.size. So we don't expect this check to fail, hence IllegalStateException seems better?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also invoke it from MemoryRecords, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We invoke it from MemoryRecords#nextBatchSize() for use in LogCleaner since this class is package-private.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, so it seems a bit brittle to assume that some checks have already been done.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have the check in nextBatch already, would it make sense to grab the record size there and pass it to this function as an argument?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the method to return null if there isn't enough data in the buffer, making it consistent with nextBatch. Added comments and test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the max message size is reduced? Is this check too strict?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See seem to only create ByteBufferLogInputStream with maxMessageSize of Integer.MAX_VALUE.

Copy link
Copy Markdown
Member

@ijuma ijuma May 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is a general class, right. It may be used in different ways in the future. We should try to write robust code that makes sense conceptually. If there are some assumptions, we should document them and ideally have tests so that we can't break them.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we do something If this evaluates to false?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When invoked from nextBatch, we return null and would do this again when there is sufficient data in the buffer (that was the existing behaviour). For log cleaner, this should always succeed since since we are growing buffer beyond max.message.bytes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should include the log segment base offset if we can in messages such as this. Also, at this point we have already allocated the batch, so is checking crc even helpful?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking that if there is a lot of corrupt data in the logs and we managed to allocate a buffer for the first one because the size was small enough to allocate, it may be worth checking CRC to detect corruption and avoid allocating even larger buffers later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated exception messsage.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be duplicating the buffer?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, not really sure we need to expose nextBatchSize. Couldn't we do nextBatch().size()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We dont change the position in the buffer in nextBatchSize, so duplicate() is not required? The unit test verifies that position is not changed.

nextBatch() returns null if the buffer is not large enough to hold the batch. nextBatchSize returns the batch size as long as the header is present, so we can allocate the buffer based on this size. Have I misunderstood the comment?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The notion of "next batch" is a little weird for MemoryRecords since it just represents a chunk of messages. Is firstBatchSize the intent?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, changed to firstBatchSize.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. should we validate the CRC before growing the buffers? The length is not protected by the CRC of course, but corruption may impact both the length and parts of the batch.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed with @ijuma offline. This probably doesn't make much sense because checking the CRC requires pulling the record into memory in the first place (which requires the length). In that case, I feel like the CRC check on the first batch is just kind of weird. Do we really get a lot of benefit from it? Maybe a simple validation we could do is at least ensure that the size of the batch is not bigger than the remaining size of the segment.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that we need to grow buffers in a similar way in buildOffsetMapForSegment() too?

@rajinisivaram rajinisivaram force-pushed the KAFKA-6834-log-cleaner branch from 2e234b1 to 43aa1dc Compare May 8, 2018 17:04
@rajinisivaram
Copy link
Copy Markdown
Contributor Author

@ijuma @hachikuji @junrao Thanks for the reviews. I have addressed the comments so far.

Copy link
Copy Markdown
Contributor

@hachikuji hachikuji left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the fix. Just one comment which does not need re-review.

}

def createLogWithMessagesLargerThanMaxSize(largeMessageSize: Int): (Log, FakeOffsetMap) = {
// Create cleaner with very small default max message size
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems misplaced?

@rajinisivaram
Copy link
Copy Markdown
Contributor Author

@hachikuji Thanks for the review, merging to trunk.

@rajinisivaram rajinisivaram merged commit 0ecb72f into apache:trunk May 9, 2018
ijuma added a commit to ijuma/kafka that referenced this pull request May 11, 2018
…-record-version

* apache-github/trunk:
  KAFKA-6894: Improve err msg when connecting processor with global store (apache#5000)
  KAFKA-6893; Create processors before starting acceptor in SocketServer (apache#4999)
  MINOR: Fix typo in ConsumerRebalanceListener JavaDoc (apache#4996)
  MINOR: Remove deprecated valueTransformer.punctuate (apache#4993)
  MINOR: Update dynamic broker configuration doc for truststore update (apache#4954)
  KAFKA-6870 Concurrency conflicts in SampledStat (apache#4985)
  KAFKA-6361: Fix log divergence between leader and follower after fast leader fail over (apache#4882)
  KAFKA-6813: Remove deprecated APIs in KIP-182, Part II (apache#4976)
  KAFKA-6878 Switch the order of underlying.init and initInternal (apache#4988)
  KAFKA-6299; Fix AdminClient error handling when metadata changes (apache#4295)
  KAFKA-6878: NPE when querying global state store not in READY state (apache#4978)
  KAFKA 6673: Implemented missing override equals method (apache#4745)
  KAFKA-6834: Handle compaction with batches bigger than max.message.bytes (apache#4953)
ying-zheng pushed a commit to ying-zheng/kafka that referenced this pull request Jul 6, 2018
…tes (apache#4953)

Grow buffers in log cleaner to hold one message set after sanity check even if message set is bigger than max.message.bytes.

Reviewers: Jason Gustafson <jason@confluent.io>, Ismael Juma <ismael@juma.me.uk>, Jun Rao <junrao@gmail.com>
mumrah pushed a commit to confluentinc/kafka that referenced this pull request Jun 27, 2019
…tes (apache#4953)

Grow buffers in log cleaner to hold one message set after sanity check even if message set is bigger than max.message.bytes.

Reviewers: Jason Gustafson <jason@confluent.io>, Ismael Juma <ismael@juma.me.uk>, Jun Rao <junrao@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants