Commit 2034234
committed
[server] Add lkc heartbeat header for active-key-count consistency check
across replicas
When the active-key-count replica consistency check is enabled, the A/A
leader attaches an `lkc` (leader key count) PubSub header on every VT
heartbeat carrying its current active key count. Followers compare against
their own count when processing the heartbeat; a mismatch records
`ingestion.key.active_count_mismatch_across_replicas` (Tehuti + OTel) and
emits a rate-limited WARN log. The follower's count is NOT invalidated —
the check is diagnostic-only.
Design notes:
- New config `server.active.key.count.replica.consistency.check.enabled`
(default false). Effective only when
`server.active.key.count.for.hybrid.store.enabled` is also true; the
`VeniceServerConfig` accessor ANDs the two so registration and
recording sites can't drift.
- `PartitionConsumptionState.lastVTProduceCallFuture` switched from a
volatile `CompletableFuture<Void>` to a `final AtomicReference<
CompletableFuture<Void>>` with `swapLastVTProduceCallFuture(next)`
returning the prior head. The new swap rejects null.
`sendIngestionHeartbeatToVT` chains the HB send behind the previous
chain entry via `whenCompleteAsync` so the lkc lands at the broker
after preceding view-writer data writes.
- The lkc value is read synchronously on the SIT thread BEFORE the swap
and captured in the chained-callback lambda. Reading from inside the
deferred callback would observe later SIT increments for records
queued AFTER this HB → false-positive mismatches.
- The chained callback propagates the upstream chain failure (skipping
the HB to avoid stamping records that never landed) and surfaces
synchronous `sendIngestionHeartbeat` failures into the chain head;
async broker rejections are logged separately and don't gate the
chain (matches `queueUpVersionTopicWritesWithViewWriters`
enqueue-completion semantics).
- `closeVeniceViewWriters` now short-circuits the chain head
unconditionally so hybrid A/A configs without view writers (which can
still grow the chain via the HB swap) don't leave a pending head
orphaned at close. `checkAndWaitForLastVTProduceFuture` bounds the
EOP-time wait with `VIEW_WRITER_CLOSE_TIMEOUT_IN_MS` and surfaces
`TimeoutException` with explicit attribution at the caller.
- `decodeLeaderKeyCountHeaderValue` throws `IllegalArgumentException` on
wrong-length payloads rather than returning a `Long.MIN_VALUE`
sentinel that would collide with a legitimately round-trippable value.
- `ActiveKeyCountInvalidationReason` now implements
`VeniceDimensionInterface` and is wired as a dimension on the existing
`ingestion.key.active_count_invalidation` metric. Three corruption
variants were renamed for clarity: `CORRUPT_KCS_SIGNAL_VALUE →
CORRUPT_KEY_COUNT_SIGNAL_HEADER_VALUE`, `CORRUPT_KCS_HEADER_LENGTH →
CORRUPT_KEY_COUNT_SIGNAL_HEADER_LENGTH`, and the new
`CORRUPT_LEADER_KEY_COUNT_HEADER_LENGTH` for malformed lkc. The enum
guards `getMessage` vs `getMessage(int)` against mismatched overload
usage via a constructor-computed `templateWithExtraData` flag.
- `VeniceWriter.sendHeartbeat` gained a 7-arg overload that attaches an
optional extra PubSub header. The 6-arg overload still exists and
delegates to the 7-arg with null. Tests migrated to stub the 7-arg
signature; production code calls the 7-arg form unconditionally.
- `EmptyPubSubMessageHeaders` singleton is promoted to a fresh mutable
instance before appending the extra header.
Wire constants moved to `PubSubMessageHeaders`:
`VENICE_KEY_COUNT_SIGNAL_HEADER` (kcs) and `VENICE_LEADER_KEY_COUNT_HEADER`
(lkc).
Test coverage:
- `ActiveKeyCountHeartbeatTest`: encode/decode round-trip including
Long.MIN_VALUE and Long.MAX_VALUE; `buildLeaderActiveKeyCountHeader`
gating (check disabled, pre-EOP, untracked, null PCS, happy path);
`compareLeaderActiveKeyCountOnHeartbeat` branches (check disabled,
pre-EOP, follower not tracking, header absent, leader sentinel,
match, mismatch, corrupt length); `sendIngestionHeartbeatToVT`
ordering, upstream-failure propagation, sync send-failure propagation.
- `ActiveKeyCountInvalidationReasonTest`: dimension fixture for all
7 enum values.
- `ActiveKeyCountScenarioTest`: end-to-end Tehuti+OTel parity for both
`recordActiveKeyCountInvalidation` and
`recordActiveKeyCountMismatchAcrossReplicas`, plus cross-system
isolation.
- `PartitionConsumptionStateTest`: 32-thread chain atomicity test for
`swapLastVTProduceCallFuture`; null-arg NPE test.
- `LeaderFollowerStoreIngestionTaskTest`: bounded EOP-wait timeout,
empty-view-writers + pending chain head short-circuit, view-writer/
CM-write chain-failure-propagation tests.
- `IngestionOtelMetricEntityTest` / `IngestionOtelStatsTest` /
`ServerMetricEntityTest` / `VeniceMetricsDimensionsTest`: updated for
the new dimension and the new mismatch metric entity.1 parent d2dd325 commit 2034234
27 files changed
Lines changed: 1869 additions & 165 deletions
File tree
- clients/da-vinci-client/src
- main/java/com/linkedin/davinci
- config
- kafka/consumer
- stats
- ingestion
- test/java/com/linkedin/davinci
- kafka/consumer
- stats
- ingestion
- internal
- venice-client-common/src
- main/java/com/linkedin/venice/stats/dimensions
- test/java/com/linkedin/venice/stats/dimensions
- venice-common/src
- main/java/com/linkedin/venice
- pubsub/api
- writer
- test/java/com/linkedin/venice/writer
Lines changed: 13 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| 74 | + | |
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
| |||
738 | 739 | | |
739 | 740 | | |
740 | 741 | | |
| 742 | + | |
741 | 743 | | |
742 | 744 | | |
743 | 745 | | |
| |||
1290 | 1292 | | |
1291 | 1293 | | |
1292 | 1294 | | |
| 1295 | + | |
| 1296 | + | |
1293 | 1297 | | |
1294 | 1298 | | |
1295 | 1299 | | |
| |||
2337 | 2341 | | |
2338 | 2342 | | |
2339 | 2343 | | |
| 2344 | + | |
| 2345 | + | |
| 2346 | + | |
| 2347 | + | |
| 2348 | + | |
| 2349 | + | |
| 2350 | + | |
| 2351 | + | |
| 2352 | + | |
2340 | 2353 | | |
2341 | 2354 | | |
2342 | 2355 | | |
| |||
Lines changed: 7 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
120 | 122 | | |
121 | | - | |
| 123 | + | |
122 | 124 | | |
123 | 125 | | |
124 | 126 | | |
| |||
Lines changed: 36 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
3 | 9 | | |
4 | 10 | | |
5 | 11 | | |
6 | 12 | | |
7 | 13 | | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
8 | 18 | | |
9 | | - | |
| 19 | + | |
10 | 20 | | |
11 | 21 | | |
12 | 22 | | |
13 | 23 | | |
14 | 24 | | |
15 | | - | |
16 | | - | |
17 | | - | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
18 | 28 | | |
19 | 29 | | |
20 | 30 | | |
| |||
23 | 33 | | |
24 | 34 | | |
25 | 35 | | |
26 | | - | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
27 | 39 | | |
28 | 40 | | |
| 41 | + | |
29 | 42 | | |
30 | 43 | | |
31 | 44 | | |
| 45 | + | |
32 | 46 | | |
33 | 47 | | |
34 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
35 | 53 | | |
36 | 54 | | |
37 | 55 | | |
38 | 56 | | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
39 | 61 | | |
40 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
41 | 72 | | |
0 commit comments