Hadoop

Hadoop

Apache Hadoop을 이용해 Apache Pinot에 배치 수집을 수행하는 방법을 다루는 페이지예요.

출처: Hadoop

본문

Pinot은 Apache Hadoop을 프로세서로 사용해 세그먼트 파일을 생성하고 데이터베이스에 푸시하는 것을 지원해요. Pinot 배포판에는 파일을 처리하고 Pinot으로 변환·업로드하는 Hadoop 배치 수집 플러그인이 번들되어 있어요.

로컬 설치 가이드를 따라 소스에서 Pinot을 빌드할 수 있어요. 결과 JAR 파일은 pinot/target/pinot-all-${PINOT_VERSION}-jar-with-dependencies.jar에서 찾을 수 있어요.

{% hint style="info" %} pinot-all-*-jar-with-dependencies.jar는 Hadoop 배치 수집 플러그인을 포함하지 않습니다. 그 플러그인은 바이너리 배포판의 plugins-external/pinot-batch-ingestion/pinot-batch-ingestion-hadoop/ 아래에 패키징됩니다. Hadoop 클래스패스에 넣고 plugins.dir에 plugins-external을 포함해야 합니다. {% endhint %}

다음으로 잡 스펙의 실행 설정을 다음과 같이 바꿔야 해요:

# executionFrameworkSpec: Defines ingestion jobs to be running.
executionFrameworkSpec:

    # name: execution framework name
  name: 'hadoop'

  # segmentGenerationJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface.
  segmentGenerationJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.hadoop.HadoopSegmentGenerationJobRunner'

  # segmentTarPushJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface.
  segmentTarPushJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.hadoop.HadoopSegmentTarPushJobRunner'

  # segmentUriPushJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface.
  segmentUriPushJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.hadoop.HadoopSegmentUriPushJobRunner'

  # segmentMetadataPushJobRunnerClassName: class name implements org.apache.pinot.spi.ingestion.batch.runner.IngestionJobRunner interface.
  segmentMetadataPushJobRunnerClassName: 'org.apache.pinot.plugin.ingestion.batch.hadoop.HadoopSegmentMetadataPushJobRunner'

    # 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/staging

Hadoop 잡 스펙은 includeFileNamePattern과 excludeFileNamePattern으로 입력 경로를 필터링할 수 있어요. 두 속성 모두 Java NIO glob: 및 regex: 패턴을 받아요; 동작 예시와 경로 정규화 세부 사항은 File name patterns 참고.

여기에서 샘플 잡 스펙을 확인할 수 있어요.

마지막으로 다음 명령으로 hadoop 잡을 실행해요:

export PINOT_VERSION=1.4.0 #set to the Pinot version you have installed
export PINOT_DISTRIBUTION_DIR=${PINOT_ROOT_DIR}/build/

HADOOP_BATCH_PLUGIN=${PINOT_DISTRIBUTION_DIR}/plugins-external/pinot-batch-ingestion/pinot-batch-ingestion-hadoop/pinot-batch-ingestion-hadoop-${PINOT_VERSION}-shaded.jar
PINOT_ALL_JAR=${PINOT_DISTRIBUTION_DIR}/lib/pinot-all-${PINOT_VERSION}-jar-with-dependencies.jar

# plugins.dir accepts a semicolon-separated list. Include plugins (record readers, FS) and plugins-external (Hadoop batch runners).
export HADOOP_CLIENT_OPTS="-Dplugins.dir=${PINOT_DISTRIBUTION_DIR}/plugins;${PINOT_DISTRIBUTION_DIR}/plugins-external -Dlog4j2.configurationFile=${PINOT_DISTRIBUTION_DIR}/conf/pinot-ingestion-job-log4j2.xml"
export HADOOP_CLASSPATH="${HADOOP_BATCH_PLUGIN}:${PINOT_ALL_JAR}:${HADOOP_CLASSPATH}"

hadoop jar \
        ${PINOT_ALL_JAR} \
        org.apache.pinot.tools.admin.PinotAdministrator \
        LaunchDataIngestionJob \
        -jobSpecFile ${PINOT_DISTRIBUTION_DIR}/examples/batch/airlineStats/hadoopIngestionJobSpec.yaml

환경 변수 PINOT_ROOT_DIR과 PINOT_VERSION이 올바르게 설정되었는지 확인하세요.

{% hint style="warning" %} Hadoop 러너에 대한 ClassNotFoundException은 보통 plugins-external이 plugins.dir에서 빠졌거나 셰이딩된 pinot-batch-ingestion-hadoop-*-shaded.jar가 HADOOP_CLASSPATH에 없다는 뜻입니다. pinot-all만으로는 충분하지 않습니다. {% endhint %}

세그먼트 생성 전 데이터 전처리

세그먼트를 생성하고 Pinot으로 푸시하기 전에 데이터를 다듬어야(파티셔닝, 정렬, 리사이징 등) 한다는 요청을 종종 봐요.

입력 데이터가 AVRO든 ORC 포맷이든, SegmentPreprocessingJob이라는 MapReduce 잡이 이 용도에 가장 적합해요.

SegmentPreprocessingJob을 사용하는 방법은 아래 예시를 참고하세요.

Hadoop 속성에서 이 잡을 활성화하려면 다음을 설정:

enable.preprocessing = true
preprocess.path.to.output = <output_path>

테이블 설정에서 MR 잡에서 활성화할 연산을 preprocessing.operations로 지정하고, 그 연산들에 대한 정확한 설정을 지정해요:

{
    "OFFLINE": {
        "metadata": {
            "customConfigs": {
                “preprocessing.operations”: “resize, partition, sort”, // To enable the following preprocessing operations
                "preprocessing.max.num.records.per.file": "100",       // To enable resizing
                "preprocessing.num.reducers": "3"                      // To enable resizing
            }
        },
        ...
        "tableIndexConfig": {
            "aggregateMetrics": false,
            "autoGeneratedInvertedIndex": false,
            "bloomFilterColumns": [],
            "createInvertedIndexDuringSegmentGeneration": false,
            "invertedIndexColumns": [],
            "loadMode": "MMAP",
            "nullHandlingEnabled": false,
            "segmentPartitionConfig": {       // To enable partitioning
                "columnPartitionMap": {
                    "item": {
                        "functionName": "murmur",
                        "numPartitions": 4
                    }
                }
            },
            "sortedColumn": [                // To enable sorting
                "actorId"
            ],
            "streamConfigs": {}
        },
        "tableName": "tableName_OFFLINE",
        "tableType": "OFFLINE",
        "tenants": {
            ...
        }
    }
}

preprocessing.num.reducers

최소 리듀서 수. 선택 사항. 파티셔닝이 비활성화되고 리사이징이 활성화될 때 사용해요. 이 파라미터는 Pinot에 대한 작은 입력 파일이 너무 많아서 Pinot 서버가 너무 많은 작은 세그먼트를 보유해 스레드가 너무 많아지는 경우를 피하기 위한 것이에요.

preprocessing.max.num.records.per.file

리듀서당 최대 레코드 수. 선택 사항. preprocessing.num.reducers와 달리, 이 파라미터는 Pinot에 대한 큰 입력 파일이 너무 적어 쿼리 시 멀티스레딩의 이점을 놓치는 경우를 피하기 위한 것이에요. 설정하지 않으면 각 리듀서가 최종적으로 하나의 출력 파일을 생성해요. 설정하면(예: M), 원래 출력 파일이 여러 파일로 분할되고 각 새 출력 파일은 최대 M개의 레코드를 포함해요. 파티셔닝이 활성화되었는지 여부는 무관해요.

이 MR 잡에 대한 자세한 내용은 이 문서를 참조하세요.

더 알아보기 (Learn more)