Fix auto compaction by adjusting compaction task's interval to align with segmentGranularity when segmentGranularity is set#12334
Conversation
| private final String sha256OfSortedSegmentIds; | ||
|
|
||
| public static ClientCompactionIntervalSpec fromSegments(List<DataSegment> segments) | ||
| public static ClientCompactionIntervalSpec fromSegments(List<DataSegment> segments, Granularity segmentGranularity) |
There was a problem hiding this comment.
| public static ClientCompactionIntervalSpec fromSegments(List<DataSegment> segments, Granularity segmentGranularity) | |
| public static ClientCompactionIntervalSpec fromSegments(List<DataSegment> segments, @Nullable Granularity segmentGranularity) |
| // - The umbrella interval of the segments is 2015-02-01/2015-03-01 but configured segmentGranularity is MONTH, | ||
| // if the compaction task's interval is 2015-02-01/2015-03-01 then compacted segments created will be | ||
| // 2015-01-26/2015-02-02, 2015-02-02/2015-02-09, 2015-02-09/2015-02-16, 2015-02-16/2015-02-23, 2015-02-23/2015-03-02. |
There was a problem hiding this comment.
I'm not sure how the segments will have these intervals after compacted. Can you elaborate? It would be nice to add your explanation in the comment.
There was a problem hiding this comment.
oops typo. The configured segmentGranularity in auto compaction is WEEK. Added more details to the comment too.
| // 2015-01-26/2015-02-02, 2015-02-02/2015-02-09, 2015-02-09/2015-02-16, 2015-02-16/2015-02-23, 2015-02-23/2015-03-02. | ||
| // The compacted segment would cause existing data from 2015-01-26 to 2015-02-01 and 2015-03-01 to 2015-03-02 to be lost. | ||
| // Hence, in this case, we must adjust the compaction task interval to 2015-01-26/2015-03-02 | ||
| interval = JodaUtils.umbrellaInterval(segmentGranularity.getIterable(interval)); |
There was a problem hiding this comment.
Looking at JodaUtils.umbrellaInterval(), I think this code can cause OOM if segmentGranularity.getIterable() returns lots of intervals. JodaUtils.umbrellaInterval() doesn't seem to need to store all startDates and endDates in memory. Instead, it can keep only one pair of minStartDate and maxEndDate which are updated in the loop. Should we fix it in this PR too?
There was a problem hiding this comment.
Or should we have a guardrail for segmentGranularity to not return such many intervals?
There was a problem hiding this comment.
I don't think we need a guardrail here. The list of segments passed to this method should be from a single time chunk (from the CompactionSegmentIterator). The single time chuck is then adjusted based on some segmentGranularity. Since the original interval (from the umbrellaInterval of the list of segments) is limited to a single time chunk, segmentGranularity.getIterable() should not returns lots of intervals. The edge case to this is if the granularities are either ALL or NONE. I think we should put a guardrail against ALL or NONE but not here. (actually I think it would blow up in the NewestSegmentFirstIterator before getting here anyway)
There was a problem hiding this comment.
I agree that the guardrail should be somewhere else than here.
| } | ||
|
|
||
| @Test | ||
| public void testAutoCompactionDutyWithSegmentGranularityCoarserAndNotAlignWithSegment() throws Exception |
There was a problem hiding this comment.
Should this tests week -> month instead of month -> year if it's for the case when the new granularity does not align with the previous?
| // from 2015-01-26 to 2015-02-01 and 2015-03-01 to 2015-03-02 to be lost. Hence, in this case, | ||
| // we must adjust the compaction task interval to 2015-01-26/2015-03-02 | ||
| interval = JodaUtils.umbrellaInterval(segmentGranularity.getIterable(interval)); | ||
| } |
There was a problem hiding this comment.
Is it necessary to log some message about the interval extension? If the interval was extended, extra segments may be included in this compaction task and then the total input bytes may exceed inputSegmentSizeBytes.
There was a problem hiding this comment.
Added some extra logs.
Regarding inputSegmentSizeBytes, I think inputSegmentSizeBytes should actually be deprecated now that the issued compaction task can run in parallel.
jihoonson
left a comment
There was a problem hiding this comment.
LGTM overall. Please check the CI failure. It seems legit.
| DateTime minStart = minDateTime(startDates.toArray(new DateTime[0])); | ||
| DateTime maxEnd = maxDateTime(endDates.toArray(new DateTime[0])); | ||
|
|
||
| if (minStart == null || maxEnd == null) { |
There was a problem hiding this comment.
This function now will return an interval of Long.MIN_VALUE, Long.MAX_VALUE when the input intervals is empty. It should throw an exception instead.
There was a problem hiding this comment.
BTW, I'm OK if you don't want to make this change in this PR. It's optional and up to you.
| // 2015-01-26/2015-02-02, 2015-02-02/2015-02-09, 2015-02-09/2015-02-16, 2015-02-16/2015-02-23, 2015-02-23/2015-03-02. | ||
| // The compacted segment would cause existing data from 2015-01-26 to 2015-02-01 and 2015-03-01 to 2015-03-02 to be lost. | ||
| // Hence, in this case, we must adjust the compaction task interval to 2015-01-26/2015-03-02 | ||
| interval = JodaUtils.umbrellaInterval(segmentGranularity.getIterable(interval)); |
There was a problem hiding this comment.
I agree that the guardrail should be somewhere else than here.
…with segmentGranularity when segmentGranularity is set (apache#12334) * add impl * add ITs * address comments * address comments * address comments * fix failure * fix checkstyle * fix checkstyle
…with segmentGranularity when segmentGranularity is set (apache#12334) * add impl * add ITs * address comments * address comments * address comments * fix failure * fix checkstyle * fix checkstyle
Fix auto compaction by adjusting compaction task's interval to align with segmentGranularity when segmentGranularity is set
Description
This bug can cause data lost if segmentGranularity is set in auto compaction.
If segmentGranularity is set, then the intervals of the segments to be compacted may not align with the configured segmentGranularity. We must adjust the interval of the compaction task to fully cover and align with the segmentGranularity to prevent unexpected data lost.
For example,
The umbrella interval of the segments to be compacted is 2015-04-11/2015-04-12 but configured segmentGranularity is YEAR, if the compaction task's interval is 2015-04-11/2015-04-12 then we can run into race condition where after submitting the compaction task if a new segment outside of the interval (i.e. 2015-02-11/2015-02-12) got created will be lost as it is overshadowed by the compacted segment (compacted segment has interval 2015-01-01/2016-01-01). Hence, in this case, we must adjust the compaction task interval to 2015-01-01/2016-01-01.
The umbrella interval of the segments to be compacted is 2015-02-01/2015-03-01 but configured segmentGranularity is WEEK, if the compaction task's interval is 2015-02-01/2015-03-01 then compacted segments created will be 2015-01-26/2015-02-02, 2015-02-02/2015-02-09, 2015-02-09/2015-02-16, 2015-02-16/2015-02-23, 2015-02-23/2015-03-02. The compacted segment would cause existing data from 2015-01-26 to 2015-02-01 and 2015-03-01 to 2015-03-02 to be lost. Hence, in this case, we must adjust the compaction task interval to 2015-01-26/2015-03-02
This PR has: