[Flink] Kvscan flink integration#3383
Conversation
ddb782e to
ecdb181
Compare
|
|
||
| - This is a **bounded** read. The source finishes once all buckets have been drained and does not continue reading the change-log. | ||
| - On task restart, each bucket is rescanned from scratch. Progress within a scan session is not checkpointed, because an expired or invalidated server-side session cannot be resumed from a mid-point. | ||
| - The feature is disabled by default (`false`). Without it, unbounded (streaming) reads on primary-key tables work as usual; bounded reads require the data-lake integration to be enabled. |
There was a problem hiding this comment.
When disabled, unbounded (streaming) reads on primary-key tables continue to work as usual. Bounded reads require data-lake integration unless server-side KV scanning is enabled.
| ``` | ||
|
|
||
| ### Limit Read | ||
| The Fluss source supports limiting reads for both primary-key tables and log tables, making it convenient to preview the latest `N` records in a table. |
There was a problem hiding this comment.
making it easy to preview the latest N records in a table.
|
@binary-signa Thank you for your comments... Addressed! |
|
@polyzos I had a look at the PR and can confirm that bounded reads via the Table API work as expected. # FlussSourceBuilder.java
if (bounded && !(lakeEnabled && fullStartup)) {
...
}The following patch addresses the issue and also adds a test case to cover this scenario. Quick example to reproduce create a primary key table with datalake option disabled CREATE DATABASE cdstream_db;
CREATE TABLE `fluss_catalog`.`cdstream_db`.`timeseries_norm` (
`streamId` INT NOT NULL,
`vector` ARRAY<DOUBLE>,
`firstTimestamp` TIMESTAMP(3),
`lastTimestamp` TIMESTAMP(3),
`lastUpdateTime` TIMESTAMP(3),
CONSTRAINT `PK_streamId` PRIMARY KEY (`streamId`) NOT ENFORCED
)
COMMENT 'This is the normalized timeseries table'
WITH (
'bootstrap.servers' = 'coordinator-server:9123',
'bucket.key' = 'streamId',
'bucket.num' = '2',
'table.datalake.enabled' = 'false',
'table.datalake.format' = 'paimon'
)Then try bounded read via DataStream API it will throw import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.data.RowData;
import org.apache.fluss.config.Configuration;
import org.apache.fluss.flink.source.FlussSource;
import org.apache.fluss.flink.source.deserializer.RowDataDeserializationSchema;
public class FlussDataStreamBoundedReadKvBatch {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// env.setRuntimeMode(RuntimeExecutionMode.STREAMING);
Configuration conf = new Configuration();
conf.setBoolean("client.scanner.kv.server-side.enabled", true);
var source = FlussSource.<RowData>builder()
.setBootstrapServers("localhost:9122")
.setDatabase("cdstream_db")
.setTable("timeseries_norm")
.setDeserializationSchema(new RowDataDeserializationSchema())
.setBounded()
.setFlussConfig(conf)
.build();
DataStream<RowData> stream = env.fromSource(source, WatermarkStrategy.noWatermarks(), "BoundedFlussKvSource");
stream.print();
env.execute("BoundedFlussKvJob");
}
} |
|
@binary-signal yes I need to find some time to rebase, and after we also need to introduce partition pruning and predicate pushdown tot Datastream. I have tickets to track these |
962a847 to
9bec12b
Compare
fresh-borzoni
left a comment
There was a problem hiding this comment.
@polyzos Thank you for the PR, left a couple of comments, PTAL
| } | ||
|
|
||
| @Test | ||
| void testKvBatchScanOnPkTable() throws Exception { |
There was a problem hiding this comment.
All KV tests write each key exactly once, so a log read would return the same rows and still pass. Shall we add an update + a delete before the scan, so the test can tell KV state from the changelog?
| } else { | ||
| splits = this.getLogSplit(null, null); | ||
| } | ||
| splits = generateFlussOnlyBatchSplits(kvBatchEnabled); |
There was a problem hiding this comment.
With lake enabled but no lake snapshot yet, flag off reads the whole log, so updates and deletes come back as extra rows (-U/+U/-D), and SELECT * returns the history, not the table.
Shall we KV-scan PK tables here regardless of the flag or fail? Silently wrong rows as the default seems wrong. WDYT?
| .withDescription( | ||
| "Master switch for using the server-side KV scan in bounded reads " | ||
| + "of primary-key tables. When true, bounded primary-key reads " | ||
| + "scan the current KV state directly via the server-side KV scan. " |
There was a problem hiding this comment.
"scan the current KV state directly" reads as if the flag forces a KV scan, but when a lake snapshot exists the union read still wins and the flag is never consulted and it only really applies when there's no lake data yet.
Shall we add "has no effect when a lake snapshot already exists" or smth similar? Same- in options.md.
|
@fresh-borzoni Thank you for your review and comments. |
#3126 extended the java client to support kvscan for the live rocksdb table.
This PR integrates that functionality inside the flink connector
Introduces
KvBatchSplitandKvBatchSplitStateas a new split type in the Flink source, enabling the connector to perform bounded full-table scans on primary-key tables via the server-side KV scan API (FIP-17), rather than reading from snapshots.