본문 바로가기
개발관련 자료

인플럭스DB(InfluxDB) #6 - In-Memory Indexing과 TSM(Time-Structured Merge Tree)

by jinu957 2020. 6. 11.
728x90

 

이번 포스팅은 요즘 핫한 InfluxDB에 대하여 작성하도록 하겠습니다.

InfluxDB 역시 작년 기상청 프로젝트에서 전국에서 관측되는 데이터를 효과적으로 처리하기 위하여 검토되었고 그때 자료조사를 한 내용입니다.

 

순서는 

 

2020/06/11 - [개발관련 자료] - InfluxDB #1 - 개요 및 특징

2020/06/11 - [개발관련 자료] - InfluxDB #2 - 주요 개념

2020/06/11 - [개발관련 자료] - InfluxDB #3 - 용어 정리

2020/06/11 - [개발관련 자료] - InfluxDB #4 - SQL DB와 비교

2020/06/11 - [개발관련 자료] - InfluxDB #5 - Schema설계 및 데이터Layout

2020/06/11 - [분류 전체보기] - InfluxDB #6 - In-Memory Indexing과 TSM(Time-Structured Merge Tree)

2020/06/11 - [개발관련 자료] - InfluxDB #7 - TSI(Time Series Index) 개요

2020/06/11 - [개발관련 자료] - InfluxDB #8 - TSI(Time Series Index) 세부 정보

2020/06/11 - [개발관련 자료] - InfluxDB #9 - Linux CentOS 설치

2020/06/12 - [개발관련 자료] - InfluxDB #10 - 사용법

 

으로 진행되며 도입 검토 차원에서 이루어진 조사라서 실무적용 보다는 InfluxDB란 어떤 것인지 파악하는 정도로만 생각하시면 될듯합니다.

 


 

1. InfluxDB 스토리지 엔진과 TSM(Time-Structured Merge Tree)

 

  • InfluxDB 스토리지 엔진은 LSM 트리와 매우 유사합니다.
  • 그것은 미리 쓰기 로그와 LSM 트리의 SSTables 개념이 유사한 읽기 전용 데이터 파일 모음을 가지고 있습니다.
  • TSM 파일에는 정렬·압축된 시리즈 데이터가 들어있습니다.
  • InfluxDB  블록에 대해 shard 만듭니다.
  • 예를 들어 보존 기간이 제한되지 않은 보존 정책이 있는 경우 7 단위로 차단 목록이 생성됩니다.
  • 이러한  조각은 기본 저장소 엔진 데이터베이스에 매핑됩니다.
  • 이러한  데이터베이스에는 고유한 WAL  TSM 파일이 있습니다.

 

 

2. Storage engine

 

  • 스토리지 엔진은 여러 구성 요소를 함께 묶고 시리즈 데이터를 저장하고 쿼리하기 위한 외부 인터페이스를 제공합니다.
  • 각각 특정 역할을 수행하는 여러 구성 요소로 이루어져 있습니다.

      - In-Memory Index:  메모리 인덱스는 측정, 태그  시리즈에 빠르게 액세스   있는 샤드(shard) 공유 인덱스입니다. 인덱스는 엔진에서 사용하지만, 저장소 엔진 자체에만 국한되지는 않습니다.

 

      - WAL: WAL 쓰기에 최적화된 저장 형식으로 내구성이 있지만 쉽게 쿼리  수는 없습니다. WAL 대한 쓰기는 고정된 크기의 세그먼트에 추가됩니다.

 

      - Cache: 캐시는 WAL 저장된 데이터의 메모리  표현입니다. 런타임시 조회되고 TSM 파일에 저장된 데이터와 병합됩니다.

 

      - TSM Files: TSM 파일은 압축  시리즈 데이터를 컬럼 형식으로 저장합니다.

 

      - FileStore: FileStore 디스크의 모든 TSM 파일에 대한 액세스를 조정합니다. 기존 파일이 대체   TSM 파일이 자동 설치되고       이상 사용되지 않는 TSM 파일은 제거됩니다.

 

      - Compactor: Compactor  최적화  Cache  TSM 데이터를  읽기 최적화된 형식으로 변환합니다.  작업은 시리즈를 압축하고, 삭제된 데이터를 제거하고, 인덱스를 최적화하고, 작은 파일을   파일로 결합하는 방식으로 수행됩니다.

 

      - Compaction Planner: 압축 계획은 압축을 위해 준비된 TSM 파일을 판별하고 여러 동시 압축이 서로 간섭하지 않도록 합니다.

 

      - Compression: 압축은 특정 데이터 유형에 대한 다양한 인코더  디코더에 의해 처리됩니다. 일부 인코더는 상당히 정적이며 항상 동일한 유형의 같은 방식으로 인코딩됩니다. 다른 인코더는 데이터의 모양에 따라 압축 전략을 전환합니다.

 

      - Writers/Readers:  파일 유형(WAL 세그먼트, TSM 파일, 삭제 표시 )에는 형식 작업을 위한 작성자  독자가 있습니다.

 

 

3. WAL(Write Ahead Log)

 

  • WAL 여러 개의 파일로 구성되어 있습니다.
  • (_000001.wal) 파일 번호는 단조롭게 증가하며 WAL 세그먼트라고합니다.
  • 세그먼트의 크기가 10MB 도달하면 세그먼트가 닫히고  세그먼트가 열립니다.
  •  WAL 세그먼트는 여러 개의 압축 블록을 저장하고 삭제합니다.
  • 쓰기가 들어 오면  포인트에 일련번호를 붙이고, Snappy 사용하여 압축되어 WAL 파일에 기록됩니다.
  • 파일은 fsync되고, 성공이 반환되기 전에 데이터는 메모리  인덱스에 추가됩니다.
  • 높은 처리 성능을 달성하려면 batch point 함께 사용해야 합니다.(최적의 배치 크기는 배치  5,000-10,000 포인트)
  • WAL  항목은 항목 유형(쓰기 또는 삭제) 나타내는 단일 바이트, 압축된 블록의 길이에 대한 4바이트의 uint32, 압축된 블록과 함께 TLV(Type-length-value)표준을 따릅니다.

 

 

4. Cache

 

  • 캐시는 현재 WAL 저장된 모든 데이터 포인트의 메모리  사본입니다.
  • 포인트는 ,  측정, 태그 세트  고유 필드로 구성됩니다.
  •  필드는 고유한 시간 순서대로 유지됩니다. 캐시 데이터는 메모리에 있는 동안 압축되지 않습니다.
  • 스토리지 엔진에 대한 쿼리는 캐시의 데이터를 TSM 파일의 데이터와 병합합니다.
  • 쿼리는 쿼리 처리  캐시에서 만들어진 데이터의 복사본에 대해 실행됩니다.
  •  방법은 쿼리가 실행되는 동안에는 결과에 영향을 주지 않습니다.
  • 캐시로 전송된 삭제(Deletes) 주어진  또는 지정된 키의 특정 시간 범위를 지웁니다.
  • 캐시는 스냅샷 동작에 대한  가지 컨트롤을 제공합니다.
  •  가지 가장 중요한 컨트롤은 메모리 제한입니다.
  • lower bound cache-snapshot-memory-size 넘으면 TSM 파일에 대한 스냅샷을 트리거하고 해당 WAL 세그먼트를 제거합니다. 
  • 또한, upper bound cache-max-memory-size 초과하면 캐시가 새로운 쓰기를 거부하게 됩니다.
  • 이러한 구성은 메모리 부족 상황을 방지하고 인스턴스가 유지할  있는 것보다 빠르게 데이터를 쓰는 클라이언트에게 억압을 가하는  유용합니다. 메모리 임계값에 대한 검사는 모든 쓰기에서 발생합니다.
  • 다른 스냅샷 컨트롤은 시간 기반입니다.
  • 유휴 임계값 cache-snapshot-write-cold-duration 지정된 간격 내에 쓰기를 수신하지 않는 경우 캐시가 TSM 파일에 스냅샷 하도록 합니다.
  • 메모리  캐시는 디스크의 WAL 파일을 다시 읽음으로써 재시작  다시 생성됩니다.

 

 

5. TSM 파일

 

  • TSM 파일은 메모리 맵핑  읽기 전용 파일의 콜렉션입니다.
  •  파일의 구조는 LevelDB 또는 다른 LSM Tree 변형의 SSTable 매우 유사하게 보입니다.

      - TSM 파일은 Header, Blocks, Index  Footer  부분으로 구성됩니다.

Header

5 bytes

Blocks

N bytes

Index

N bytes

Footer

4 bytes

      - 헤더는 파일 형식과 버전 번호를 식별하는 Magic 번호입니다.

  Header

 Magic

4 bytes

Version

1 byte

      - 블록은 CRC32 체크섬  데이터 쌍의 시퀀스입니다. 블록 데이터는 파일에 불투명합니다. CRC32 블록 레벨 오류 감지에 사용됩니다. 블록의 길이는 색인에 저장됩니다.

Blocks

Block 1

Block 2

 Block N

CRC

4 bytes

 Data

N bytes

CRC

4 bytes

Data

N bytes

CRC

 4 bytes

Data

N bytes

      - 블록 다음에는 파일의 블록 Index 있습니다. Index 키에 의해 사전식으로 순서화된 색인 항목의 순서로 구성됩니다.

      - 키에는 측정 이름, 태그 세트  하나의 필드가 포함됩니다.

      - 포인트  여러 필드는 TSM 파일에 다중 색인 항목을 작성합니다.

      -  색인 항목은 Key 길이와 Key, 블록 유형 (float, int, bool, string)   키에 이어지는 색인 블록 항목 수의 순서로 시작됩니다.

      -  인덱스 블록 항목은 블록의 최소  최대 시간, 블록이 위치한 파일의 오프셋  블록의 크기로 구성됩니다.

      - 키가 들어있는 TSM 파일의  블록에 대해 하나의 인덱스 블록 항목이 있습니다.

      - 인덱스 구조는 모든 블록에 효율적으로 액세스   있을  아니라 주어진 키에 액세스하는 것과 관련된 비용을 결정할  있습니다.

      - 키와 타임스탬프가 주어지면 파일에 해당 타임스탬프의 블록이 포함되어 있는지 확인할  있습니다.

      - 블록을 검색하기 위해 블록이 상주하는 위치와 읽어야 하는 데이터의 양을 결정할 수도 있습니다.

      - 블록 크기를 알면 IO문을 효율적으로 프로비저닝   있습니다.

 Index  

Key Len

2 bytes

Key

N bytes

Type

1 byte

Count

2 bytes

Min Time

8 bytes

Max Tim

8 bytes

Offset

8 bytes

Size

4 bytes

.......

      - 마지막 섹션은 인덱스 시작 오프셋을 저장하는 Footer입니다.

Footer

Index Ofs

8 bytes

 

 

6. Compression

 

  • 쿼리    블록을 압축하여 저장 공간과 디스크 IO 줄입니다.
  • 블록은 주어진 시리즈와 필드에 대한 타임스탬프와 값을 포함합니다.
  •  블록은 압축된 타임스탬프 다음에 압축된 값이 오는 1바이트 헤더를 가집니다.

Type

1 Bytes

Len

VBytes

Timestamps

N Bytes

Values    

N Bytes

  • 타임스탬프와 값은 데이터 유형과 모양에 따라 인코딩을 사용하여 별도로 압축되고 저장됩니다.
  • 이들을 독립적으로 저장하면 타임스탬프 인코딩을 모든 타임스탬프에 사용할  있고 다른 필드 유형에 대해 다른 인코딩을 사용할  있습니다.
  • 예를 들어, 일부 포인트는 run-length 인코딩을 사용할  있지만 다른 포인트는 그렇지 않을  있습니다.
  •   유형에는 나머지 바이트에 대한 압축 유형을 나타내는 1바이트 헤더가 들어있습니다.
  • 4개의 상위 비트는 압축 유형을 저장하고 4개의 하위 비트는 필요한 경우 인코더가 사용합니다.
  • Timestamps

      - 타임스탬프 인코딩은 적응적이며, 인코딩된 타임스탬프의 구조를 기반으로 합니다.

      - 그것은 델타 인코딩, 스케일링  simple8b run-length 인코딩을 사용하여 압축의 조합을 사용하고, 필요하다면 압축하지 않아도 됩니다.

      - 타임스탬프 해상도는 가변적이지만 압축되지 않은 상태로 저장하려면 최대 8바이트가 필요한 나노초만큼 세분화될  있습니다.

      - 인코딩 중에 값은 먼저 델타 인코딩됩니다.

      -  번째 값은 시작 타임스탬프이며 후속 값은 이전 값과의 차이입니다.

      - 이것은 보통 값을 압축하기 쉬운 아주 작은 정수로 변환합니다.

      - 많은 타임스탬프 또한 단조롭게 증가하고 심지어  10초와 같이 시간의 경계에 있습니다.

      - 타임스탬프가  구조를 가질 , 10 인수인 최대 공약수로 조정됩니다.

      - 이것은 매우  정수 델타를 압축률이 작은 델타로 변환하는 효과가 있습니다.

      - 이러한 조정  값을 사용하여 모든 델타가 동일한 경우, 시간 범위는 run-length 인코딩을 사용하여 저장됩니다.

      - run-length 인코딩이 불가능하고 모든 값이 (1<<60)-1(nanosecond resolution에서 ~36.5) 미만인 경우 타임스탬프는 simple8b 인코딩을 사용하여 인코딩됩니다.

      - Simple8b 인코딩은 다중 정수를 단일 64비트 단어로 묶는 64비트 워드 정렬 정수 인코딩입니다.

      - 값이 최댓값을 초과하면 델타는 블록에 대해 각각 8바이트를 사용하여 압축되지 않은 상태로 저장됩니다.

      - 이후의 인코딩은 패치된 프레임 참조(PFOR) 같은 패치  구성표를 사용하여 outlier 보다 효과적으로 처리할  ​​있습니다.

 

  • Floats

      - 플로트는 Gorilla: A Fast, Scalable, In-Memory Time Series Database 논문의 구현을 사용하여 인코딩됩니다.

      - 인코딩은 연속된 값을 함께 XOR하여 값이 서로 가깝게 되면 작은 결과를 생성합니다. 

      - 델타는 제어 비트를 사용하여 저장되어 XOR 값에 선행0 후행0 표시합니다.

      - 우리의 구현은 종이에 설명된 타임스탬프 인코딩을 제거하고 float 값만 인코딩합니다.

      - 48바이트의 값과 타임스탬프가 21바이트/167비트 바로 아래로 압축됩니다.

 

전체 압축 알고리즘 시각화

 

  • Integers

      - 정수 인코딩은 압축되지 않은 데이터의  범위에 따라  가지 전략을 사용합니다.

      - 인코딩  값은 먼저 ZigZag 인코딩을 사용하여 인코딩됩니다.

      - 이는 양의 정수 범위에서 양수  음수 정수를 끼워 넣습니다. 예를 들어 [-2, -1, 0, 1] [3, 1, 0, 2] 됩니다.

      - 모든 ZigZag 인코딩 값이 (1<<60)-1보다 작으면 simple8b 인코딩을 사용하여 압축됩니다.

      - 값이 최댓값보다  경우 모든 값은 블록에 압축되지 않은 상태로 저장됩니다.

      - 모든 값이 동일하면, run-length 인코딩이 사용됩니다.

      - 이것은 자주 일정한 값에 대해  작동합니다.

 

  • Booleans

      - 부울은  부울이 1비트를 사용하는 간단한 비트 패킹 전략을 사용하여 인코딩됩니다. 인코딩  부울의 수는 블록의 시작 부분에 가변 바이트 인코딩을 사용하여 저장됩니다.

 

  • Strings

      - 문자열은 Snappy 압축을 사용하여 인코딩합니다.  문자열은 연속적으로 압축되며 하나의  블록으로 압축됩니다.

 

 

7. Compactions

  • 압축은 쓰기 최적화된 형식으로 저장된 데이터를 읽기 최적화된 형식으로 데이터 이전을 반복하는 프로세스입니다. 샤드가 글쓰기에 hot 상태일  일어나는 여러 단계의 압축이 있습니다.

 

  • Snapshots

      - 캐시  WAL 값은 TSM 파일로 변환되어 WAL 세그먼트에서 사용되는 메모리  디스크 공간을 확보해야 합니다.

      - 이러한 압축은 캐시 메모리  시간 임계값을 기반으로 발생합니다.

 

  • Level Compactions

      - 레벨 압축(레벨1-4) TSM 파일이 커짐에 따라 발생합니다.

      - TSM 파일은 스냅샷에서 레벨1 파일로 압축됩니다.

      - 멀티 레벨1 파일이 압축되어 레벨2 파일이 생성됩니다.

      - 파일이 레벨4 도달하고 TSM 파일의 최대 크기에 도달할 때까지 프로세스가 계속됩니다.

      - 삭제, 인덱스 최적화 압축 또는 전체 압축을 실행해야 하는 경우가 아니면 압축되지 않습니다.

      - 하위 레벨 압축은 블록 압축 해제  결합과 같은 CPU 집중적인 활동을 피하는 전략을 사용합니다.

      - 보다 높은 수준의( 빈번한) 압축은 블록을 완전히 다시 압축하여 압축 비율을 높이기 위해 블록을 다시 결합합니다.

 

  • Index Optimization

      - 레벨4 TSM 파일이 많이 누적되면 내부 인덱스가  커지고 액세스하는  많은 비용이 듭니다.

      - 색인 최적화 압축은 일련의 색인을 하나의 TSM 파일로 정렬하여 일련의 색인을 새로운 TSM 파일 세트로 분할합니다.

      - 색인 최적화 전에는  TSM 파일에는 대부분의 또는 모든 시리즈에 대한 포인트가 들어 있으므로 각각에는 동일한 시리즈 색인이 들어있습니다. 

      - 색인 최적화 후에는  TSM 파일에 시리즈에 대한 최소한의 포인트가 들어있으며, 파일 간에는 시리즈 중복이 거의 없습니다.

      - 따라서  TSM 파일에는 전체 시리즈 목록의 사본 대신 작은 고유한 시리즈 색인이 있습니다.

      - 또한, 특정 시리즈의 모든 포인트는 여러 TSM 파일에 분산되어 있지 않고 TSM 파일에 인접해 있습니다.

 

  • Full Compactions

      - 전체 압축은 샤드가 장기간 쓰기가 차가워지거나 샤드에서 삭제된 경우 실행됩니다.

      - 전체 압축은 최적의 TSM 파일 세트를 생성하고 레벨  색인 최적화 압축의 모든 최적화를 포함합니다.

      - 조각이 완전히 압축되면 새로운 쓰기 또는 삭제가 저장되지 않으며 다른 압축이 실행되지 않습니다.

 

 

8. Writes

 

  • 쓰기는 현재 WAL 세그먼트에 추가되며 캐시에도 추가됩니다.
  •  WAL 세그먼트는 최대 크기를 가집니다.
  • 현재 파일이 가득 차면  파일로 roll over 씁니다.
  • 캐시는 크기가 제한되어 있습니다.
  • 스냅샷이 만들어지고 캐시가 너무  차있을  WAL 압축이 시작됩니다.
  • 인바운드 쓰기 속도가 일정 기간 WAL 압축률을 초과하면 캐시가 가득 차게 되어 스냅샷 프로세스가 중단될 때까지 새로운 쓰기가 실패합니다.
  • WAL 세그먼트가 채워지고 닫히면 Compactor 캐시를 스냅샷하고  TSM 파일에 데이터를 기록합니다.
  • TSM 파일이 성공적으로 기록되고 작성  fsync되면, FileStore 의해 로드되고 참조됩니다.

 

 

9. Updates

 

  • 업데이트(이미 존재하는 지점에 대해  새로운 값을 ) normal write 같이 발생합니다.
  • 캐시  값은 기존 값을 덮어쓰므로 newer writes 우선합니다.
  • 쓰기가 이전 TSM 파일의  포인트를 겹쳐  경우, 포인트는 조회 런타임에서 병합되고 newer writes 우선됩니다.

 

 

10. Deletes

 

  • 삭제는 측정 항목 또는 시리즈에 대해 WAL 삭제 항목을 쓰고 캐시  FileStore 업데이트하여 발생합니다.
  • 캐시는 모든 관련 항목을 제거합니다.
  • FileStore 관련 데이터가 들어있는  TSM 파일에 대해 tombstone 파일을 작성합니다.
  • 이러한 tombstone 파일은 시작  삭제된 항목을 제거하기 위해 압축하는 동안뿐만 아니라 블록을 무시하기 위해 사용됩니다.
  • 부분적으로 삭제된 시리즈에 대한 조회는 압축이 TSM 파일에서 데이터를 완전히 제거할 때까지 query time 처리됩니다.

 

 

11. Queries

 

  • Query 스토리지 엔진에 의해 실행되면, 그것은 본질적으로 특정 시리즈   필드와 연관된 주어진 시간에 대한 탐색입니다.
  • 먼저 데이터 파일을 검색하여 검색어와 일치하는 시간 범위가 포함된 파일을 찾고 일치하는 시리즈를 포함합니다.
  • 데이터 파일을 선택하고 나면 시리즈  인덱스 항목의 파일에서 위치를 찾아야 합니다.
  •  TSM 색인에 대해 binary search 실행하여 색인 블록의 위치를 ​​찾습니다.
  • 일반적으로 블록은 여러 TSM 파일에서 겹치지 않으며 인덱스 항목을 선형으로 검색하여 읽을 시작 블록을 찾습니다.
  • 겹치는 시간 블록이 있는 경우 색인 항목이 정렬되어  새로운 쓰기가 우선 적용되고 쿼리 실행 중에 순서대로 블록을 처리할  ​​있습니다.
  • 인덱스 항목을 반복할  블록은 블록 섹션에서 순차적으로 읽혀집니다. 블록이 압축 해제되고 특정 지점을 찾습니다.

 

728x90

댓글