아이스버그 네시(Nessie) 통합

아이스버그 네시(Nessie) 통합 (Iceberg Nessie Integration)

아이스버그는 iceberg-nessie 모듈을 통해 Nessie와의 통합을 제공해요. 이 문서에서는 Nessie와 함께 아이스버그를 사용하는 방법을 알려드릴게요. Nessie는 아이스버그 위에 다중 테이블 트랜잭션, git 같은 연산(브랜치, 태그, 커밋), 하이브 같은 메타스토어 기능을 추가로 제공해요.

출처: 문서

본문

아이스버그는 iceberg-nessie 모듈을 통해 Nessie와의 통합을 제공해요. 이 섹션에서는 Nessie와 함께 아이스버그를 사용하는 방법을 설명해요. Nessie는 아이스버그 위에 몇 가지 핵심 기능을 제공해요.

  • 다중 테이블 트랜잭션 (multi-table transactions)
  • git 같은 연산 (예: 브랜치, 태그, 커밋)
  • 하이브 같은 메타스토어 기능

Nessie에 대한 자세한 내용은 Project Nessie 문서를 참고해주세요. Nessie는 서버를 실행해야 해요. Nessie 서버를 시작하는 방법은 시작하기(Getting Started) 문서를 참고해주세요.

Nessie 카탈로그 활성화 (Enabling Nessie Catalog)

iceberg-nessie 모듈은 0.11.0 버전부터 모든 버전의 스파크와 플링크 런타임에 번들돼 있어요. Nessie(spark-3.5 사용)와 아이스버그를 시작하려면 프로세스에 아이스버그 런타임만 추가하면 돼요. 예: spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.11.0.

스파크 SQL 확장 (Spark SQL Extensions)

Nessie SQL 확장은 아래처럼 Nessie 레포지토리를 관리하는 데 사용할 수 있어요. Spark 3.5(scala 2.12) 예시:

bin/spark-sql 
  --packages "org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.11.0,org.projectnessie.nessie-integrations:nessie-spark-extensions-3.5_2.12:0.105.3"
  --conf spark.sql.extensions="org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,org.projectnessie.spark.extensions.NessieSparkSessionExtensions"
  --conf <other settings>

Nessie SQL 확장에 대한 자세한 내용은 Nessie SQL extension 문서를 참고해주세요.

Nessie 카탈로그 (Nessie Catalog)

0.11.0 릴리스에서 도입된 주요 기능 중 하나는 스파크와 플링크에서 커스텀 카탈로그로 쉽게 상호작용하는 것입니다. 아이스버그에 커스텀 카탈로그를 추가하는 방법은 스파크 구성과 플링크 구성 문서를 참고해주세요.

Nessie 카탈로그를 사용하려면 다음 속성이 필요해요.

  • warehouse. 대부분의 다른 카탈로그처럼 warehouse 속성은 이 카탈로그가 테이블을 저장할 파일 경로예요.
  • uri. Nessie 서버 기본 uri예요. 예: http://localhost:19120/api/v2.
  • ref (선택). 작업할 Nessie 브랜치 또는 태그예요.

자바에서 직접 실행하면 다음과 같아요.

Map<String, String> options = new HashMap<>();
options.put("warehouse", "/path/to/warehouse");
options.put("ref", "main");
options.put("uri", "https://localhost:19120/api/v2");
Catalog nessieCatalog = CatalogUtil.loadCatalog("org.apache.iceberg.nessie.NessieCatalog", "nessie", options, hadoopConfig);

스파크에서는:

conf.set("spark.sql.catalog.nessie.warehouse", "/path/to/warehouse");
conf.set("spark.sql.catalog.nessie.uri", "http://localhost:19120/api/v2")
conf.set("spark.sql.catalog.nessie.ref", "main")
conf.set("spark.sql.catalog.nessie.type", "nessie")
conf.set("spark.sql.catalog.nessie", "org.apache.iceberg.spark.SparkCatalog")
conf.set("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,org.projectnessie.spark.extensions.NessieSparkSessionExtensions")

플링크에서 Python API로는 이렇게 보여요 (추가 세부사항은 여기에서 찾을 수 있어요):

import os
from pyflink.datastream import StreamExecutionEnvironment
from pyflink.table import StreamTableEnvironment

env = StreamExecutionEnvironment.get_execution_environment()
iceberg_flink_runtime_jar = os.path.join(os.getcwd(), "iceberg-flink-runtime-1.11.0.jar")
env.add_jars("file://{}".format(iceberg_flink_runtime_jar))
table_env = StreamTableEnvironment.create(env)

table_env.execute_sql("CREATE CATALOG nessie_catalog WITH ("
                      "'type'='iceberg', "
                      "'type'='nessie', "
                      "'uri'='http://localhost:19120/api/v2', "
                      "'ref'='main', "
                      "'warehouse'='/path/to/warehouse')")

위에서 nessie라는 이름 자체에는 특별한 것이 없어요. 스파크 카탈로그는 어떤 이름이든 가질 수 있고, 중요한 부분은 type 또는 catalog-impl에 대한 설정과 Nessie를 올바르게 시작하는 데 필요한 구성이에요. Nessie 카탈로그를 가지면 전체 Nessie 레포지토리에 접근할 수 있어요. 그런 다음 브랜치에 대한 create/delete/merge 연산을 수행하고 브랜치에서 커밋을 수행할 수 있어요. Nessie 카탈로그의 각 아이스버그 테이블은 임의 길이의 네임스페이스와 테이블 이름(예: data.base.name.table)으로 식별돼요. 이런 네임스페이스는 여기에 언급된 것처럼 명시적으로 만들어야 해요.

Nessie가 활성화된 아이스버그 테이블의 모든 트랜잭션은 Nessie에서 단일 커밋이에요. Nessie 커밋은 임의의 수의 테이블에 대한 임의의 수의 작업을 포함할 수 있지만, 아이스버그에서는 현재 사용 가능한 단일 테이블 트랜잭션 집합으로 제한돼요.

병합, 커밋 로그 보기, diff 같은 추가 연산은 자바의 NessieClient와 직접 상호작용하거나 Python 클라이언트 또는 CLI를 사용해서 수행해요. CLI에 대한 자세한 내용은 Nessie CLI 문서를, Nessie 기능에 대한 더 완전한 설명은 Spark Guide를 참고해주세요.

Nessie와 아이스버그 (Nessie and Iceberg)

대부분의 경우 Nessie는 아이스버그에 대해 다른 카탈로그와 똑같이 동작해요. 즉 테이블 집합의 논리적 구성을 제공하고 트랜잭션에 원자성을 제공해요. 하지만 Nessie를 사용하면 다른 흥미로운 가능성도 열려요. Nessie를 아이스버그와 함께 사용하면 모든 아이스버그 트랜잭션이 Nessie 커밋이 돼요. 이 이력은 브랜치 간에 나열(리스트), 병합, 체리픽(cherry-pick)할 수 있어요.

느슨하게 결합된 트랜잭션 (Loosely coupled transactions)

브랜치를 만들고 그 브랜치에서 일련의 연산을 수행하면 다중 테이블 트랜잭션에 가까워질 수 있어요. 새로 만든 브랜치에서 일련의 커밋을 수행하고, 그다음 main 브랜치로 원자적으로 병합할 수 있어요. 이렇게 하면 일련의 연결된 변경들이 main 브랜치에 동시에 노출되는 것처럼 보여요. 다운스트림 소비자들은 여러 트랜잭션이 한꺼번에 나타나는 것을 보겠지만, 이는 데이터베이스에서 진정한 다중 테이블 트랜잭션은 아니에요. 효과적으로는 여러 커밋의 패스트포워드 병합(git 용어로)이고, 브랜치의 각 연산은 그 자체로 별개의 트랜잭션이자 커밋이에요. 이는 모든 변경이 같은 커밋에 있는 실제 다중 테이블 트랜잭션과는 달라요. 하지만 여러 애플리케이션이 브랜치 수정에 참여하고, 이 분산된 트랜잭션 집합을 다운스트림 사용자에게 동시에 노출할 수 있게 해줘요.

실험 (Experimentation)

테이블에 대한 변경은 main으로 병합하기 전에 브랜치에서 테스트할 수 있어요. 이는 스키마 진화나 파티션 진화 같은 큰 변경을 수행할 때 특히 유용해요. 파티션 진화를 브랜치에서 수행하고, 병합하기 전에 변경 사항(예: 성능 벤치마크)을 테스트할 수 있어요. 이는 다운스트림 사용 사례를 방해하지 않고 온라인 테이블 수정과 테스트를 수행하는 데 큰 유연성을 제공해요. 변경이 잘못됐거나 성능이 좋지 않다면 병합하지 않고 브랜치를 삭제할 수 있어요.

추가 사용 사례 (Further use cases)

Nessie 기능에 대한 추가 설명은 Nessie 문서를 참고해주세요.

위험 (Danger)

nessie를 사용할 때 아이스버그에서 일반적인 테이블 유지보수는 복잡해요. 테이블 유지보수를 수행하기 전에 관리 서비스(Management Services) 문서를 참고해주세요.

예시 (Example)

Nessie와 아이스버그가 함께 동작하는 다양한 예시는 Nessie Demos repo를 참고해주세요.

향후 개선 사항 (Future Improvements)

  • 아이스버그 다중 테이블 트랜잭션. 같은 트랜잭션에서 여러 아이스버그 테이블을 변경, 격리 수준 등

더 알아보기 (Learn more)