Repository navigation
[fix](load) Persist Kinesis LATEST positions before scheduling tasks - #67678
0AyanamiRei wants to merge 4 commits into
Conversation
### What problem does this PR solve? Issue Number: N/A Related PR: N/A Problem Summary: Kinesis tasks can lose an initial LATEST iterator before committing a concrete sequence. Retrying LATEST then chooses a newer tip and skips intervening records. Resolve unresolved OPEN shards through a bounded BE scan pool and journal the complete batch before creating tasks. Use a dedicated RPC connection for cancellation and separate the optional batch deadline from finite HTTP request timeouts. ### Release note Fix Kinesis Routine Load initial LATEST positions drifting after empty polling, aborts, timeouts, and task replacement. ### Check List (For Author) - Test: Unit Test; 12 FE tests and 8 BE tests passed. FE package and BE ASAN_UT build passed. Production BE package blocked by local thirdparty layout. Full clang-tidy remains blocked by existing diagnostics. - Behavior changed: Yes; initialize and journal positions before tasks, bound per-BE scan concurrency, and cancel initialization on PAUSE. - Does this need documentation: Yes; new settings and behavior are documented in the PR description; no website documentation PR included.
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
run buildall |
Cloud UT Coverage ReportIncrement line coverage Increment coverage report
|
|
run buildall |
|
run buildall |
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
sollhui
left a comment
There was a problem hiding this comment.
Found a scheduling gap when a shard is split or merged while initial LATEST resolution is still pending; details inline.
| writeLock(); | ||
| try { | ||
| if (state == JobState.NEED_SCHEDULE) { | ||
| if (!getUnresolvedLatestShards().isEmpty()) { |
There was a problem hiding this comment.
[P1] Keep task creation blocked until the pending initialization batch is persisted
getUnresolvedLatestShards() only examines the current OPEN shards, but the tasks below also include CLOSED shards. If an initial shard A is being scanned and is split before that scan completes, the next metadata refresh moves A to closedKinesisShards and initializes its children at TRIM_HORIZON. When no other OPEN shard has an unresolved LATEST position, this guard passes even though latestSequenceFetch is still pending. The job then enters RUNNING with a task containing A=LATEST, before the initialization result has been journaled. This bypasses the durable-start-position guarantee, and the normal scheduler no longer calls prepare() for that RUNNING job to collect the pending result.
I reproduced the gate bypass in an isolated Java harness using five unchanged methods from this PR, with infrastructure stubbed: before the split there are no tasks and the state is NEED_SCHEDULE; after refreshing the topology and calling divideRoutineLoadJob(1), the state is RUNNING, the scan is still pending, and task positions are {parent=LATEST, child-0=-2, child-1=-2}. This is not a full Doris/AWS integration test.
Please also block scheduling while an initialization batch remains uncollected/unpersisted, including when its requested shards become CLOSED. A regression test covering pending initialization -> split/merge -> scheduler round should assert that no tasks are created until the result is journaled.
|
draft,计划是希望对routine load kinese先去持久化的维护一个shards父子关系的拓扑图 |
|
Absorbed into the Kinesis shard topology change, closing this draft. Production code from this PR is in the working branch (
Deliberate differences in the absorbed form:
The regression suite is added verbatim as |
### What problem does this PR solve? Issue Number: None Related PR: apache#67678, apache#67696, apache#67869, apache#67874, apache#67879 Problem Summary: Kinesis shards can split and merge while a routine load job is running. Maintaining only open/closed shard lists and progress cannot express parent-child lineage or the COMMITTED-to-VISIBLE completion barrier, which can schedule children too early, lose lineage, or recreate completed parents. This change adds a durable shard topology state machine, concrete initial-position persistence, idempotent journal/image replay, and Kinesis BE progress handling for EOF and ChildShards metadata. New FE, BE, and regression coverage verifies shard transitions, transaction visibility, latest-position resolution, reshard boundaries, and deterministic Kinesis upstream behavior. ### Release note Add parent-child shard topology tracking and visibility-gated scheduling for Kinesis Routine Load. ### Check List (For Author) - Test: Unit Test - `./run-be-ut.sh --run --filter='*Kinesis*' -j48` - Result: 18 Kinesis tests passed - No FE unit test or AWS regression test was run in this environment. - Behavior changed: Yes (Kinesis Routine Load now schedules shards through the topology state machine.) - Does this need documentation: No
What problem does this PR solve?
Issue Number: N/A
Related PR: N/A
Problem Summary:
Kinesis Routine Load can skip records when a shard starts at
LATESTand its first task does not commit a concrete sequence number. The BE has resolvedLATESTinto a shard iterator, but FE progress still contains the symbolic position. Empty polling, an aborted transaction, a timeout, or task replacement can discard the iterator. The replacement task then interpretsLATESTagain against a later stream tip.For example:
Kafka resolves symbolic offsets through its watermark metadata API before consumption. Kinesis
GetShardIterator(LATEST)returns an opaque iterator, not a durable numeric end offset, and an emptyGetRecordsresponse does not reveal the preceding record's sequence number. The five-minute expiration applies to the iterator; a record sequence number can be used to obtain another iterator while the source position remains available within retention.This PR resolves initial Kinesis positions before creating data tasks, persists the resolved positions in FE, and keeps the existing task and transaction progress protocol.
1. Resolve only the shards that need initialization
FE selects the intersection of the job's currently tracked OPEN shards and progress entries still set to
LATEST(case insensitive) or-1.TRIM_HORIZONpositions are reused without scanning.prepare()submits one asynchronous metadata RPC containing the batch. The job remainsNEED_SCHEDULEwhile the result is pending.divideRoutineLoadJob()checks the same unresolved set and does not create tasks until resolution and persistence have completed. No data-task transaction is opened while waiting for this scan.2. Find restartable positions by scanning retained records
For each selected shard, the BE requests a
TRIM_HORIZONiterator and followsGetRecordspages, keeping the last record's sequence number. It continues across empty intermediate pages and finishes when the service reportsMillisBehindLatest == 0or the iterator reaches a closed shard's end.sequence(R3)AFTER_SEQUENCE_NUMBER(R3)TRIM_HORIZONThe scan downloads historical payloads but never sends them to the Doris load pipe. Its total work is
O(sum(L_i)), orO(N * L)for N shards with average retained length L. Each worker retains a response page rather than buffering the entire history.3. Bound concurrency across all initialization requests on a BE
A dedicated BE scan pool is shared by all batches, with 8 workers by default. Each batch submits at most
min(shard_count, configured_worker_count)workers. Workers claim shards within their batch, and each worker owns its scan consumer/client.Scanning is dispatched directly to this pool, so ordinary Routine Load workers do not block waiting for long metadata scans. The queue is bounded to 1024 workers; submission failure fails the batch and causes already submitted workers to stop. This is a concurrency bound, not a guarantee of fair scheduling between jobs.
The result map is protected by a mutex. Completion accounting includes both executed workers and failed submissions. The response and RPC
donecallback are completed only after all workers have exited, so no worker can continue using the RPC controller after it is released.4. Persist the complete batch before scheduling tasks
The new operation is wired into journal serialization and replay. The existing job image continues to persist the progress map. A crash after journaling but before applying the in-memory update recovers the positions through replay.
No successful subset is persisted or reused after a failed initialization attempt. Once the batch is persisted, an abort or replacement uses the saved position instead of choosing a newer tip. Successful data transactions continue advancing progress through the original attachment path; no changes are made to the data-task Thrift schema or transaction commit behavior.
5. Make cancellation visible to the BE
The current brpc implementation does not reliably expose cancellation of an individual gRPC stream through
Controller::IsCanceled(), which observes socket failure. Each initialization batch therefore uses its own gRPC channel, created through the existing channel provider and DNS handling. A Future listener calls non-blockingshutdownNow()on completion, failure, or cancellation.PAUSE, terminal job states, explicit source ALTER, and an enabled total timeout cancel the pending initialization. Closing its dedicated connection lets the BE observe cancellation without closing connections used by unrelated requests. This does not add a cancel RPC or a scan-registration handshake.
Workers check shared batch status before claiming shards, around AWS calls, and during backoff. AWS requests also receive a continuation callback. The BE checks server shutdown as well, preventing an unlimited scan from blocking brpc shutdown before the executor's stop phase.
Configuration and timeout semantics
kinesis_latest_sequence_timeout_second-1kinesis_latest_sequence_scan_threads8kinesis_latest_sequence_request_timeout_ms30000A positive overall timeout covers the batch, including BE queueing, and is never reset per shard or successful page. FE also sets a gRPC deadline and rejects results collected after its deadline. BE workers share one local monotonic deadline established before queueing.
Scan clients use the SDK's actual HTTP timeout (
httpRequestTimeoutMs), independently of the ordinary consumers' settings. SDK-internal retries are disabled for these clients; iterator acquisition and record reads use up to three cancellable retries with 1, 2, and 4 second backoffs.Cancellation is cooperative: the SDK continuation handler does not immediately interrupt every silent network wait. An in-flight Kinesis HTTP call may take until its finite request timeout to finish. Credential-provider initialization/refresh is not fully covered by that Kinesis HTTP timeout.
Semantics and compatibility boundaries
AWS API references: GetShardIterator, GetRecords.
Release note
Fix Kinesis Routine Load initialization from
LATESTlosing its starting position after empty polling, transaction aborts, timeouts, or task replacement. Initial positions are resolved and journaled before data tasks are created, using bounded BE scan concurrency.Check List (For Author)
LATESTshards are scanned before scheduling, complete results are journaled, and PAUSE cancels pending initialization.Validation performed
KinesisLatestPositionTestKinesisDataSourcePropertiesTestKinesisLatestSequenceTest.*RoutineLoadTaskExecutorTest.*Commands used (the local Arrow 24/Paimon installation uses the unversioned prefix):
Validation limitations:
NOLINTENDinbe/src/core/types.hand existing whole-file warnings. The newly added functions' complexity and request-copy diagnostics were fixed. A focused rerun of the two adjusted C++ files reported no diagnostics on their final changed lines; this is not a claim that full clang-tidy passed.Check List (For Reviewer who merge this PR)