Spark
Batch ingestion of data into Apache Pinot using Apache Spark.
Pinot supports Apache Spark 3.x as a processor to create and push segment files to the database. Pinot distribution is bundled with the Spark code to process your files and convert and upload them to Pinot.
To set up Spark, do one of the following:
Use the Spark-Pinot Connector. For more information, see the ReadMe.
Follow the instructions below.
You can follow the local install guide to build Pinot from source. The resulting JAR file can be found in pinot/target/pinot-all-${PINOT_VERSION}-jar-with-dependencies.jar
If you do build Pinot from Source, you should consider opting into using the build-shaded-jar jar profile with -Pbuild-shaded-jar. While Pinot does not bundle spark into its jar, it does bundle certain hadoop libraries.
Next, you need to change the execution config in the job spec to the following:
# executionFrameworkSpec: Defines ingestion jobs to be running.
executionFrameworkSpec:
# name: execution framework name
name: 'spark'
# segmentGenerationJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface.
segmentGenerationJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.spark3.SparkSegmentGenerationJobRunner'
# segmentTarPushJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface.
segmentTarPushJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.spark3.SparkSegmentTarPushJobRunner'
# segmentUriPushJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface.
segmentUriPushJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.spark3.SparkSegmentUriPushJobRunner'
#segmentMetadataPushJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface
segmentMetadataPushJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.spark3.SparkSegmentMetadataPushJobRunner'
# extraConfigs: extra configs for execution framework.
extraConfigs:
# stagingDir is used in distributed filesystem to host all the segments then move this directory entirely to output directory.
stagingDir: your/local/dir/stagingSpark job specs can filter input paths with includeFileNamePattern and excludeFileNamePattern. Both properties accept Java NIO glob: and regex: patterns; see File name patterns for working examples and path-normalization details.
Required jars and plugins.dir
pinot-all-*-jar-with-dependencies.jar does not bundle Spark or Hadoop batch-ingestion plugins. Those live under plugins-external/ in the binary distribution (see pinot-assembly.xml). You must put them on the Spark classpath and point plugins.dir at directories that contain them.
To run Spark ingestion you need:
pinot-alljar — underlib/in the packagepinot-batch-ingestion-spark-3shaded plugin jar — underplugins-external/pinot-batch-ingestion/pinot-batch-ingestion-spark-3/Any other plugins your job uses (record readers, file systems) — under
plugins/(for examplepinot-avro,pinot-parquet,pinot-s3)
plugins.dir accepts a semicolon-separated list of directories. Include both plugins and plugins-external so record readers and the Spark batch runners load correctly:
Put the Spark batch plugin and pinot-all on the driver (and executor) classpath with spark.driver.extraClassPath / spark.executor.extraClassPath:
The complete local-mode spark-submit command:
Ensure environment variables PINOT_ROOT_DIR and PINOT_VERSION are set properly.
Note: You should change the master to yarn and deploy-mode to cluster for production environments.
Running on YARN
The example below uses YARN with client deploy mode so the Spark driver can read the unpacked Pinot distribution referenced by plugins.dir. Before running it:
Build Pinot from source with option
-DuseProvidedHadoopKeep the unpacked Pinot distribution available on the submit host.
Copy the ingestion spec YAML to S3, HDFS, or another location accessible through
--files.Add the Spark batch plugin and
pinot-allthrough--jarsso Spark distributes them to executors.Point the driver and executor classpaths at the distributed jar names.
For YARN cluster deploy mode, the driver runs remotely. You must separately distribute and unpack the plugins and plugins-external directories, then set plugins.dir to paths that exist in the remote driver container.
Example
FAQ
Q - I am getting the following exception - Class has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
Since 0.8.0 release, Pinot binaries are compiled with JDK 11. If you are using Spark along with Hadoop 2.7+, you need to use the Java8 version of Pinot. Currently, you need to build jdk 8 version from source.
Q - I am not able to find pinot-batch-ingestion-spark jar.
Since Pinot 0.10.0, the Spark batch plugin is located under plugins-external/pinot-batch-ingestion/ in the binary distribution (in older versions it lived under plugins/). Current Spark 3 builds ship pinot-batch-ingestion-spark-3-*-shaded.jar.
Q - Spark is not able to find the jars leading to java.nio.file.NoSuchFileException
This means the classpath for spark job has not been configured properly. If you are running spark in a distributed environment such as Yarn or k8s, make sure both spark.driver.extraClassPath and spark.executor.extraClassPath are set. Also, the jars in driver.extraClassPath should be added to --jars argument in spark-submit so that spark can distribute those jars to all the nodes in your cluster. You also need to take provide appropriate scheme with the file path when running the jar. In this doc, we have used local:// but it can be different depending on your cluster setup.
Q - Spark job failing while pushing the segments.
It can be because of misconfigured controllerURI in job spec yaml file. If the controllerURI is correct, make sure it is accessible from all the nodes of your YARN or k8s cluster.
Q - My data gets overwritten during ingestion.
Set segmentPushType to APPEND in the tableConfig.
If already set to APPEND, this is likely due to a missing timeColumnName in your table config. If you can't provide a time column, use our segment name generation configs in ingestion spec. Generally using inputFile segment name generator should fix your issue.
Q - I am getting java.lang.RuntimeException: java.io.IOException: Failed to create directory: pinot-plugins-dir-0/plugins/*
Removing -Dplugins.dir=... from spark.driver.extraJavaOptions can fix this when the plugin jars are already on the Spark classpath via extraClassPath and --jars. Prefer pointing plugins.dir at real local paths that exist on the driver (plugins and plugins-external under the distribution).
Q - Getting Class not found: exception (for example SparkSegmentGenerationJobRunner)
The Spark/Hadoop batch runners are not inside pinot-all. Confirm that:
extraClassPathfor both driver and executors includes the shaded jar underplugins-external/pinot-batch-ingestion/pinot-batch-ingestion-spark-3/That same jar is listed in
--jarsfor cluster modeplugins.dirincludes${PINOT_DISTRIBUTION_DIR}/plugins-external(semicolon-separated withpluginsif you also need record readers / file-system plugins fromplugins/)The job spec uses the Spark 3 package:
org.apache.pinot.plugin.ingestion.batch.spark3.*
Last updated
Was this helpful?

