Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

JDFS

Joinc Distributed File System이다. 오브젝트 스토리지를 위한 분산 파일 시스템과 블럭 스토리지를 위한 분산 파일 시스템을 구현한다.

HDFS의 문제점

  • 일반 파일 시스템에 마운트 해서 사용 할 수 없다. ls, copy, rm 과 같은 일반적인 파일 시스템 작업을 할 수 없다. 이 작업을 위해서는 FUSE와 같은 고수준 파일 시스템이 필요하다.
  • HDFS는 불변 파일(Immutable file)만 저장된다. 이미 저장된 파일은 수정 할 수 없다.
  • 파일 시스템의 네임스페이스를 네임 노드의 메모리에 관리한다. 많은 수의 파일을 저장하기 위해서는 많은 메모리가 필요하다.
  • 네임 노드에 문제가 발생하면 서비스가 중단 된다.
  • 데이터에 대한 복제본을 만들어서 데이터의 가용성을 높인다. 복제본의 갯수만큼 스토리지가 증가한다.

이러한 문제를 해결해야 겠다.

  • 네임노드도 분산하자.
  • MR 보다 빠르게 데이터를 읽고 쓸수 있어야 한다.
  • POSIX 레이어를 쉽게 올릴 수 있어야 한다.
  • 파일 수정 할 수 있어야 한다.
  • 장애내성을 가져야 한다.
  • 파일 특성에 따라서 다른 블럭 사이즈를 가질 수 있어야 한다.
  • 분산 읽기/쓰기.

JDFS-Object Storage

 JDFS 개요

블럭 기반 분산

파일시스템은 일정한 크기의 블럭으로 구성된다. 파일을 업로드 할 경우, 연속된 key 값을 가지는 일련의 블럭이 만들어 진다. 블럭은 jump consistent hash 함수 hash(key, bucket_num)으로 분산이 된다. 예를 들어 블럭 크기가 16M 이고 160M짜리 파일을 업로드 한다면 가정해보자.
  1. 16M 짜리 10개의 블럭으로 나뉜다.
  2. JDFS는 10개의 블럭에 일련의 Key를 할당한다. 첫번재 블럭이 50이었다면 50, 51 ... 59가 할당될 것이다.
  3. JDFS는 각 블럭이 어느 노드에 분산해야 할지 hash 함수를 이용해서 빠르게 확인 할 수 있다.
  4. 클라이언트는 쓰레드를 돌려서, 파일을 동시에 업로드 한다. : 업로드 작업의 분산, 동시 분할 업로드
다운로드는 아래와 같이 진행된다.
  1. hash 함수를 돌려서 key를 찾는다. 이제 파일 블럭이 저장된 노드의 배열을 계산 할 수 있다. 이 배열은 저장된 블럭 순서대로 정렬돼 있다.
  2. 클라이언트는 쓰레드를 돌려서, 파일을 동시에 다운로드 한다.
파일의 첫 번째 블럭의 노드위치는 이다. 나머지 노드는 Key++ 연산을 하면 된다. 따라서 파일의 크기와 브럭 사이즈를 알고 있다면 아래와 같은 코드로 파일이 위치한 연속된 노드의 배열을 계산할 수 있다.
func GetBlockArray(fileName string, fileSize int64) {
    k := GetKey(filename)
    v := Hash(k, NODENUM)
    Blocks := filesize / BLOCKSIZE 
    BlockList := [Blocks]int{}

    for i := 0 ; i < fileSize / BLOCKSIZE ; i++ {
        v := Hash(k+i, NODENUM)
        BlockList[i] = v
    }
    // {firstNode, SecondNode, ThirdNode, ...} 
}
이제 첫 번째 블럭이 저장된 노드에 파일의 블럭리스트 정보를 포함하는 메타파일을 만든다.
필드 설명
Seqid 전체 클러스터에서 유일한 번호, inode의 역할을 한다
Fsize 파일 크기
BlockSize BlockSize를 다이나믹하게 설정 할 수 있을 것이다.
NodeList 노드의 목록이 저장된다.
compression 오브젝트 단위로 압축 할 수 있다.
encrypt 오브젝트 단위로 암호화 할 수 있다.
이제 각 노드에 블럭을 저장하면 된다. 저장해야 노드의 위치와 순서를 알고 있기 때문에, 동시에 블럭을 쓸 수 있다. 파일을 찾기 위해서는 노드의 위치와 순서 그리고 노드에서의 파일의 위치를 알고 있어야 한다. 노드에서의 파일 위치는 Seqnum으로 알 수 있다.

Replication

 Replication

블럭이 저장된 노드를 기준으로 가상의 리플리카 존을 만들고, 각 존에 복제본을 저장한다. 복제본의 위치는 mod 연산으로 찾을 수 있다.

메타파일의 분산

오브젝트 하나에 하나의 메타파일이 만들어진다. 메타파일은 파일의 첫번째 블럭의 헤더 혹은 별도의 파일로 존재한다. 메타파일을 따로 분리하는게 구현에 편하겠지만, 이 경우 파일의 갯수가 늘어날 것이다. 첫번재 블럭의 헤더에 두는 게 좋을 것 같다. 메타 정보를 저장하는 헤더는 가변크기를 가지도록 해야 할 것이다.

네임의 분산과 복제

파일은 이름을 가지며, 특정 디렉토리에 위치한다. 분산된 각 파일들의 이름과 디렉토리 정보를 가지고 있어야 한다. 네임정보는 노드에 분산이 되며, 복제가 된다.
  1. 테넌트 단위로 분산 : 하나의 노드에 문제가 생기더라도 해당 노드에 있는 테넌트에만 문제가 국한된다.
  2. 복제 : 네임정보는 파일블럭과 마찬가지로 분산된다.
유저(테넌트) 단위로 관리를 한다. 아래와 같은 구성을 가진다.

 네임노드의 분산

아래와 같이 복제한다.

 네임노드의 복사

Hash 함수를 이용하면, 유저의 메타정보를 저장하는 파일과 복제정보를 저장하는 파일이 위치하는 노드의 목록을 계산 할 수 있다. 유저가 API를 이용해서 원본에 CRUD를 하면, 원본 API 서버가 나머지 API-Server의 API를 호출하는 것으로 서로 동기화 한다.

Tree 구조의 표현

일반적인 데이터베이스 시스템으로 트리 구조를 표현하기 위해서 사용 할 수 있는 방법은 대략 4가지가 있다.
  1. Adjacency list
  2. Path enumeration
  3. Nested sets
  4. Closure table
Adjacency List가 가장 무난하다. 대략 아래와 같은 구조를 가진다. 게시판에서 코멘트 트리를 표현하기 위해서 사용하기도 한다.
Directory_ID Parent_ID Name Path
1 0 /
2 1 home /home
3 1 usr /usr
4 2 yundream /home/yundream
파일은 다른 테이블에 저장한다.
File_ID Directori_ID Name Path
1 4 hello.c /home/yundream/hello.c
2 4 readme.md /home/yundream/readme.md

POSIX Layer

POSIX Layer를 올릴 수 있을 것 같다.

분산 운영체제

참고