Skip to content

KAFKA-8428: Always require a single batch with compressed messages#6816

Merged
guozhangwang merged 10 commits into
apache:trunkfrom
guozhangwang:KXXX-require-only-one-batch-in-compressed-data
May 29, 2019
Merged

KAFKA-8428: Always require a single batch with compressed messages#6816
guozhangwang merged 10 commits into
apache:trunkfrom
guozhangwang:KXXX-require-only-one-batch-in-compressed-data

Conversation

@guozhangwang

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)

@guozhangwang
guozhangwang requested a review from hachikuji May 25, 2019 05:14
@guozhangwang

Copy link
Copy Markdown
Contributor Author

github somehow makes a lot of diff out of it, but actually no logical changes here except removing one forloop with iterator.next(). @hachikuji

@hachikuji hachikuji left a 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 fix LGTM. Could we have a test case?

@guozhangwang

Copy link
Copy Markdown
Contributor Author

@hachikuji Thanks for the review, added unit tests.

@hachikuji hachikuji left a 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.

Thanks @guozhangwang . Left a couple comments.

}
}

private[kafka] def validateRecords(records: MemoryRecords): RecordBatch = {

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.

Maybe name should be validateCompressedRecords?

outputBuffer.put(inputBuffer);

// write again
inputBuffer = inputRecords.buffer().duplicate ();

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.

nit: unneeded space. A couple of these above also.

return builder.build();
}

// for testing only, create a new memory-records that contains duplicated

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.

Seems like it would be easier to create a record set with two batches... Here's an example:

        ByteBuffer buffer = ByteBuffer.allocate(2048);
        MemoryRecordsBuilder builder = MemoryRecords.builder(buffer, magic, compression, TimestampType.CREATE_TIME, 0L);
        builder.append(10L, "1".getBytes(), "a".getBytes());
        builder.close();

        builder = MemoryRecords.builder(buffer, magic, compression, TimestampType.CREATE_TIME, 1L);
        builder.append(11L, "2".getBytes(), "b".getBytes());
        builder.append(12L, "3".getBytes(), "c".getBytes());
        builder.close();
        buffer.flip();

In any case, perhaps we can move this to LogValidatorTest since we are not likely to need it elsewhere?

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.

builder.close(); would reset the position so that the next batch would overwrite the first one. Let me change a bit to make it work.

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 only resets the position of a dup. We use the pattern above in several existing test cases

Comment thread core/src/main/scala/kafka/log/LogValidator.scala
@guozhangwang

Copy link
Copy Markdown
Contributor Author

Addressed comments.

@hachikuji hachikuji left a 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.

Thanks, just one more comment.

}

private def checkOnlyOneBatchCompressed(magic: Byte) {
LogValidator.validateCompressedRecords(createRecords(magic, 0L, CompressionType.GZIP))

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.

I wonder if it would be better to validate through validateMessagesAndAssignOffsets since that is the method which Log actually calls. Also, we may as well add a similar check to ensure that non-compressed v2 only accepts one batch.

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 thought about that too and was a bit lazy getting to pass in all those parameters, I can change that again.

Regarding the check for uncompressed V2: yeah I can do that too.

@hachikuji hachikuji left a 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.

LGTM

val id: Int = 23
}


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.

Looks like we didn't need this?

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.

Ack. Was trying to create a KAFKA_LATEST case object but ended up with a different approach.

@guozhangwang
guozhangwang merged commit 592410f into apache:trunk May 29, 2019
guozhangwang added a commit that referenced this pull request May 29, 2019
…ges (#6816)

I think it's better just to make single-batch as a universal requirement for all versions for compressed messages, and for V2 and beyond uncompressed messages as well.

Reviewers: Jason Gustafson <jason@confluent.io>
@guozhangwang

Copy link
Copy Markdown
Contributor Author

Cherry-picked to 2.3.

@ijuma

ijuma commented May 29, 2019

Copy link
Copy Markdown
Member

Why did we cherry pick this to 2.3?

@guozhangwang

Copy link
Copy Markdown
Contributor Author

@ijuma : @hachikuji and I discussed about this, and we suggested to get this check in as early version as possible since additional validation stops us from accepting bad data -- if it breaks any clients in the wild, better break it earlier than later.

@ijuma

ijuma commented May 29, 2019

Copy link
Copy Markdown
Member

@guozhangwang did you check if this breaks any other clients like librdkafka? I disagree that we should risk breaking clients so late in the cycle without discussing with the release manager at least. We are one day away from code freeze after all.

@hachikuji

Copy link
Copy Markdown
Contributor

Just to clarify, having multiple compressed batches in a single produce payload was already broken. We would have accepted the data without properly assigning offsets beyond the first batch.

@guozhangwang

Copy link
Copy Markdown
Contributor Author

@ijuma The way we look at it is that it is more about fixing a bug than adding an extra check: in log validator, after the first pass our logic is the following: 1) if !inPlaceAssignment, read the transational info from the first batch, 2) otherwise update the offsets of the first batch only. Note 2) already assumes one batch only and if there are multiple, it will break badly -- I think rather than fix it be allowing to process multiple batches per partition, it's better guarded by rejecting the partition.

@ijuma

ijuma commented May 29, 2019

Copy link
Copy Markdown
Member

The change is definitely good. I just don't see the need to backport to 2.3 so late in the cycle. In any case, it's done.

haidangdam pushed a commit to haidangdam/kafka that referenced this pull request May 29, 2019
…ges (apache#6816)

I think it's better just to make single-batch as a universal requirement for all versions for compressed messages, and for V2 and beyond uncompressed messages as well.

Reviewers: Jason Gustafson <jason@confluent.io>
hachikuji added a commit that referenced this pull request May 31, 2019
@ijuma

ijuma commented Jun 2, 2019

Copy link
Copy Markdown
Member

Some problems were identified and the change was reverted in 2.3 via 0701a79.

pengxiaolong pushed a commit to pengxiaolong/kafka that referenced this pull request Jun 14, 2019
…ges (apache#6816)

I think it's better just to make single-batch as a universal requirement for all versions for compressed messages, and for V2 and beyond uncompressed messages as well.

Reviewers: Jason Gustafson <jason@confluent.io>
@guozhangwang
guozhangwang deleted the KXXX-require-only-one-batch-in-compressed-data branch April 24, 2020 23:58
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.

3 participants