파일 시스템

파일 시스템 (File Systems)

Flink의 파일 시스템 추상화와 구현, 영속성 보장, 파일 콘텐츠 갱신·덮어쓰기·스레드 안전성에 대해 설명해요.

출처: File Systems

본문

Flink는 org.apache.flink.core.fs.FileSystem 클래스를 통해 자체 파일 시스템 추상화를 가져요. 이 추상화는 다양한 유형의 파일 시스템 구현에 걸쳐 공통된 연산 집합과 최소한의 보장을 제공해요.

FileSystem이 제공하는 연산 집합은 다양한 파일 시스템을 지원하기 위해 상당히 제한적이에요. 예를 들어 기존 파일에 추가하거나 변경하는 것은 지원되지 않아요.

파일 시스템은 file://, hdfs:// 같은 파일 시스템 스킴(scheme) 으로 식별돼요.

Implementations

Flink는 다음 파일 시스템 스킴으로 파일 시스템을 직접 구현해요:

  • file — 머신의 로컬 파일 시스템.

다른 파일 시스템 유형은 Apache Hadoop이 지원하는 파일 시스템 제품군에 브리지하는 구현으로 접근돼요. 예시(불완전 목록):

  • hdfs: Hadoop Distributed File System
  • s3, s3n, s3a: Amazon S3 file system
  • gcs: Google Cloud Storage
  • ...

Flink는 클래스 경로에서 Hadoop File System 클래스를 찾고 유효한 Hadoop 구성을 찾으면 Hadoop의 파일 시스템을 투명하게 로드해요. 기본적으로 클래스 경로에서 Hadoop 구성을 찾아요. 또는 fs.hdfs.hadoopconf 구성 항목으로 커스텀 위치를 지정할 수 있어요.

Persistence Guarantees

FileSystemFsDataOutputStream 인스턴스는 애플리케이션의 결과와 내결함성·복구 모두를 위해 데이터를 영속적으로 저장하는 데 사용돼요. 따라서 이 스트림의 영속성 의미가 잘 정의되어야 하는 것이 중요해요.

Definition of Persistence Guarantees

두 요구사항이 충족되면 출력 스트림에 기록된 데이터가 영속적인 것으로 간주돼요:

  1. Visibility Requirement(가시성 요구사항): 파일에 접근할 수 있는 다른 모든 프로세스·머신·가상 머신·컨테이너 등이 절대 파일 경로가 주어졌을 때 데이터를 일관되게 볼 수 있음이 보장되어야 해요. 이 요구사항은 POSIX가 정의한 close-to-open 의미와 유사하지만, (절대 경로로) 파일 자체로 제한돼요.

  2. Durability Requirement(내구성 요구사항): 파일 시스템 특유의 durability/persistence 요구사항이 충족되어야 해요. 이것들은 특정 파일 시스템에 특화돼 있어요. 예를 들어 {@link LocalFileSystem}은 하드웨어와 운영체제 모두의 크래시에 대해 어떤 내구성 보장도 제공하지 않는 반면, 복제된 분산 파일 시스템(HDFS 같은)은 보통 n개의 동시 노드 장애가 있어도 내구성을 보장하며, 여기서 n은 복제 계수예요.

파일의 상위 디렉토리 갱신(디렉토리 내용을 나열할 때 파일이 나타나도록 하는 것)은 파일 스트림의 데이터가 영속적인 것으로 간주되기 위해 완료될 필요는 없어요. 이 완화는 디렉토리 내용에 대한 갱신이 eventual consistency(최종 일관성)뿐인 파일 시스템에 중요해요.

FSDataOutputStreamFSDataOutputStream.close() 호출이 반환되면 기록된 바이트에 대해 데이터 영속성을 보장해야 해요.

Examples

  • 내결함성 분산 파일 시스템의 경우, 데이터가 파일 시스템에 의해 수신·승인되면(보통 머신 쿼럼에 복제되어) 영속적인 것으로 간주돼요(durability requirement). 또한 절대 파일 경로는 잠재적으로 파일에 접근할 다른 모든 머신에 보여야 해요(visibility requirement).

    데이터가 스토리지 노드의 비휘발성 저장소에 도달했는지는 특정 파일 시스템의 구체적인 보장에 달려 있어요.

    파일의 상위 디렉토리에 대한 메타데이터 갱신은 일관된 상태에 도달할 필요는 없어요. 모든 노드에서 절대 경로로 파일에 접근하는 것이 가능한 한, 일부 머신은 상위 디렉토리 내용을 나열할 때 파일을 보고 다른 머신은 보지 못하는 것이 허용돼요.

  • 로컬 파일 시스템은 POSIX close-to-open 의미를 지원해야 해요. 로컬 파일 시스템에는 내결함성 보장이 없으므로 추가 요구사항이 존재하지 않아요.

    위의 내용은 특히 로컬 파일 시스템의 관점에서 데이터가 영속적인 것으로 간주될 때 데이터가 여전히 OS 캐시에 있을 수 있음을 의미해요. OS 캐시가 데이터를 잃게 하는 크래시는 로컬 머신에 치명적인 것으로 간주되며 Flink가 정의한 로컬 파일 시스템의 보장으로는 커버되지 않아요.

    즉 로컬 파일 시스템에만 기록된 계산 결과·체크포인트·세이브포인트는 로컬 머신의 장애로부터 복구 가능하다고 보장되지 않아, 로컬 파일 시스템은 프로덕션 설정에 부적합해요.

Updating File Contents

많은 파일 시스템은 기존 파일의 내용 덮어쓰기를 전혀 지원하지 않거나, 그 경우 갱신된 내용의 일관된 가시성을 지원하지 않아요. 그런 이유로 Flink의 FileSystem은 기존 파일에 추가(appending)하거나, 이전에 기록된 데이터가 같은 파일 안에서 변경될 수 있도록 출력 스트림 내에서 탐색(seeking)하는 것을 지원하지 않아요.

Overwriting Files

파일 덮어쓰기는 일반적으로 가능해요. 파일은 삭제 후 새 파일을 만들어 덮어써요. 그러나 일부 파일 시스템은 그 변경을 파일에 접근하는 모든 주체에게 동기적으로 보이게 할 수 없어요. 예를 들어 Amazon S3은 파일 교체의 가시성에서 eventual consistency만 보장해요: 일부 머신은 옛 파일을 보고, 일부 머신은 새 파일을 볼 수 있어요.

이 일관성 문제를 피하기 위해 Flink의 장애/복구 메커니즘 구현은 같은 파일 경로에 두 번 이상 쓰는 것을 엄격히 피해요.

Thread Safety

FileSystem 구현은 스레드 안전해야 해요: 같은 FileSystem 인스턴스는 Flink에서 여러 스레드에 걸쳐 자주 공유되며 입력/출력 스트림을 동시에 만들고 파일 메타데이터를 나열할 수 있어야 해요.

FSDataOutputStream 구현은 엄격히 스레드 안전하지 않아요. 스트림 인스턴스는 읽기·쓰기 연산 사이에 스레드 간에 전달되어서도 안 돼요. 스레드 간 연산의 가시성에 대한 보장이 없기 때문이에요(많은 연산이 메모리 펜스를 만들지 않아요).

더 알아보기 (Learn more)