apache / apache/druid

Tasks can fail to allocate segments with segment lock if segment granularity has changed

Open
#10,220 0 comments 3 reactions 0 assignees View on GitHub
Area - Batch Ingestion Area - Streaming Ingestion Bug
Dominant language
Java
Stars
14.1k
Forks
3.8k
Avg merge
2d 58m
Merged PRs (30d)
233

Description

### Affected Version

All versions since 0.16.

### Description

This error can happen in this scenario.

1. A task is started with `forceTimeChunkLock = false` and `segmentGranularity = MONTH`. Assuming this task is not overwriting existing data, the task will use the segment lock and the Overlord-based segment allocation which creates entries in the `pendingSegments` table of the metadata store. This task will successfully publishes created segments. The published segments will have partitionIds starting from 32767 since segment lock is used.
2. After `1.`, a compaction task is started also with `forceTimeChunkLock = false` but `segmentGranularity = YEAR`. Since the segment granularity is different from existing segments, the compaction task will use time chunk lock. This task will successfully publishes compacted segments. The published segments will have partitionIds starting from 0 since time chunk lock is used.
3. After `2.`, another compaction task is started also with `forceTimeChunkLock = false` and `segmentGranularity = YEAR`. This task will fail because of a conflict with segments created in `1.` with the below error.

```
2020-07-28T19:15:28,451 WARN [qtp1280512370-105] org.apache.druid.metadata.IndexerSQLMetadataStorageCoordinator - Cannot allocate new segment for dataSource[ds], interval[2000-01-01T00:00:00.000Z/2001-01-01T00:00:00.000Z], maxVersion[2020-07-28T19:15:28.440Z]: conflicting segment[ds_2000-03-01T00:00:00.000Z_2000-04-01T00:00:00.000Z_2020-07-28T16:47:40.943Z_32787].
```

In the overlord-based segment allocation, the overlord searches for the current maximum segment ID to find the available partitionId for new segments. When it searches, it takes only the segments sharing the same partition space into consideration. Note that segments created with segment lock and segments created with time chunk lock don't share partition space. Instead, the former ones use the space of [32767, 65536) while the later ones use the space of [0, 32767). As a result, in `3.`, the max ID will be searched among the segments created in `1.` which have a different segment granularity which in turn causing the above error.

We might be possible to clean up the part of the `pendingSegments` table when an overwrite task publishes segments with time chunk lock where the rows have matching intervals to published segments. Because the max segment ID in a time chunk will always be found among the segments created by an overwrite task once it publishes segments, we can safely delete the pending segments in the same time chunk. This also introduce an eager cleanup for the `pendingSegments` table which will reduce the load of the metadata store.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the Overlord-based segment allocation and pendingSegments handling described in the issue, comparing segment-lock and time-chunk-lock partition spaces. Reproduce the three-step sequence and define done as preventing the conflicting allocation, with matching pendingSegments rows cleaned up after publication.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
databases, distributed-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.