[server] Update Tablet Server to use per-table/partition remote data directory
- Dominant language
- Java
- Stars
- 2.1k
- Forks
- 625
- Avg merge
- 3d 14h
- Merged PRs (30d)
- 97
Description
## Search before asking
- [x] I searched in the [issues](https://github.com/apache/fluss/issues) and found nothing similar.
## Description
**Task Overview:**
With each table and partition now carrying a dedicated `remoteDataDir` in their metadata, the Tablet Server must be updated to use these per-entity directories instead of the single cluster-level `remote.data.dir` when performing remote log tiering and KV snapshot operations.
This task propagates `remoteDataDir` through the entire Tablet Server data path: from replica creation to remote log segment uploading/deletion and KV snapshot management.
**Purpose:**
- Make the Tablet Server actually write remote log segments and KV snapshots to the directory assigned to each table/partition at creation time.
- Remove all shared `FsPath`/`FileSystem` fields that were derived from the global config; instead compute paths on demand from the per-replica `remoteDataDir`.
- Maintain backward compatibility with existing persisted `RemoteLogManifest` and `RemoteLogSegment` data that was written before this change (no `remote_log_dir` field present).
**Scope:**
### 1. Replica — carry remoteDataDir
- **`Replica`**: Add `remoteDataDir` field and `getRemoteDataDir()` getter. Remove the stale `remoteKvDir` field; it is now computed on-demand from `remoteDataDir`.
### 2. ReplicaManager — resolve remoteDataDir at replica creation
- **`ReplicaManager`**:
- Add helper `getRemoteDataDir(TableBucket, PhysicalTablePath, TableRegistration)`:
- For partitioned tables: calls `getPartitionRegistration(zkClient, physicalTablePath)` and returns `partitionRegistration.getRemoteDataDir()`.
- For non-partitioned tables: returns `tableRegistration.remoteDataDir`.
- In `maybeCreateReplica()`: fetch `TableRegistration` and `SchemaInfo` separately via `getTableRegistration()` / `getSchemaInfo()`, resolve `remoteDataDir`, and pass it to the `Replica` constructor.
- In remote fetch path: derive `remoteLogDir` from `FlussPaths.remoteLogDir(replica.getRemoteDataDir())` instead of the former `remoteLogManager.remoteLogDir()`.
- In replica deletion: pass `replica.getRemoteDataDir()` to `kvManager.deleteRemoteKvSnapshot()`.
### 3. TabletManagerBase — static ZK helper methods
- **`TabletManagerBase`**: Extract `getTableRegistration(ZooKeeperClient, TablePath)` and `getPartitionRegistration(ZooKeeperClient, PhysicalTablePath)` as public static helpers. Refactor `getTableInfo()` to delegate to these methods.
### 4. KvManager — on-demand remoteKvDir
- **`KvManager`**: Remove the `remoteKvDir` / `remoteFileSystem` fields from the constructor. `deleteRemoteKvSnapshot()` now accepts `String remoteDataDir` and computes `FlussPaths.remoteKvDir(remoteDataDir)` locally per call.
### 5. SnapshotContext — on-demand remoteKvDir
- **`DefaultSnapshotContext`** / **`SnapshotContext`**: Remove `getRemoteKvDir()` method; compute `remoteKvDir` from `remoteDataDir` on demand inside the snapshot workflow.
### 6. RemoteLogManager — per-replica remoteLogDir
- **`RemoteLogManager`**: Remove the `remoteLogDir()` method. Each operation (load manifest, delete log) now receives or computes `remoteLogDir` from `FlussPaths.remoteLogDir(replica.getRemoteDataDir())`.
- Construct `RemoteLogTablet` with the resolved `remoteLogDir`.
- Backward-compat backfill: if a deserialized `RemoteLogManifest` has a `null` `remoteLogDir`, call `manifest.newManifest(remoteLogDir)` to fill it before use.
### 7. RemoteLogManifest — carry remoteLogDir
- **`RemoteLogManifest`**: Add `remoteLogDir` field. Add `newManifest(FsPath remoteLogDir)` that reconstructs the manifest (and all contained `RemoteLogSegment` entries) with the supplied `remoteLogDir` for the backward-compat backfill path.
- **`RemoteLogSegment`**: Add `remoteLogDir` field to `Builder` and the main class; used by `DefaultRemoteLogStorage` to obtain the correct `FileSystem` per segment.
### 8. RemoteLogManifestJsonSerde — backward-compatible serialization
- **`RemoteLogManifestJsonSerde`**: Serialize `remote_log_dir` both at the manifest level and per-segment level. On deserialization, treat the field as optional (`null` if absent) to stay compatible with manifests written by older versions.
### 9. DefaultRemoteLogStorage — per-path FileSystem
- **`DefaultRemoteLogStorage`**: Remove the shared `FileSystem` field. Each I/O operation (`upload`, `delete`, `open`) now resolves `FileSystem` from the specific `FsPath` of the segment or manifest path being operated on. Rename `getRemoteLogDir()` to `getDefaultRemoteLogDir()`.
### 10. FlussPaths — String-based path helpers
- **`FlussPaths`**: Add `remoteLogDir(String remoteDataDir)` and `remoteKvDir(String remoteDataDir)` overloads that accept a raw directory string rather than requiring a full `Configuration` object.
## Willingness to contribute
- [x] I'm willing to submit a PR!
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with Replica and ReplicaManager to trace how remoteDataDir is resolved and carried into the Tablet Server path. Then follow the listed KvManager, SnapshotContext, RemoteLogManager, RemoteLogManifest, RemoteLogSegment, RemoteLogManifestJsonSerde, DefaultRemoteLogStorage, and FlussPaths changes. Done means remote logs and KV snapshots use per-table or per-partition directories, while older manifests remain readable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, data-engineering, distributed-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100