시계열 데이터를 처리하는 InfluxDB에 대해서 알아보자
influxDB를 알아보기 전 시계열 데이터란?
시계열은 일정 기간 동안 수집되고 시간순으로 정렬된 데이터 요소의 모음입니다. 시계열의 주요 특징은 인덱싱되거나 시간 순서대로 나열된다는 것인데 그래서 그래프에 시계열 데이터를 시각화 할 때 중요한 축은 시간이 됩니다.
시계열 데이터는 다음과 같은 곳에서 사용될 수 있습니다.
- 기상 예보
- 주식
- 센서 데이터
- 일(월,연)간 구독자
- 서버 자원 모니터링 등등
요즘 들어 스마트 팩토리, 빅데이터, 코인, 주식 등이 핫한데 이런 데이터들의 특징은 시간순으로 인덱싱이 중요하고, 대용량 데이터라는 점입니다. 이러한 데이터들을 핸들링 하는 시계열 데이터베이스 중 InfluxDB가 도대체 어떠한 식으로 데이터를 처리하고 저장하여 빠른 속도를 낼 수 있는지 왜 이렇게 유명하고 많이들 사용하는지 알아보도록 하겠습니다.
influxDB란? (Data Principle)
influxdb는 시계열 데이터를 다룰 수 있는 가장 유명한 시계열 데이터베이스(time-series database)입니다. InfluxDB의 특징을 나열하면 다음과 같습니다.
- 시간순으로 구성된 값들의 집합(Point)들을 저장
- 수 초, 나노초의 엄청난 양의 데이터를 저장해야하기 때문에, 쓰기에 아주 특화됨
- 쿼리 및 쓰기 성능을 높이기 위해 업데이트 및 삭제 기능은 엄격하게 제한
- SQL과 유사한 InfluxQL을 제공
- Continuous Query 기능 제공
- Tag라는 것을 이용해 인덱싱 제공
- REST API 제공
Storage Engine
공식문서에서는 Storage Engine을 다음과 같이 설명합니다.
InfluxDB 스토리지 엔진은 다음을 보장합니다.
1. 데이터가 디스크에 안전하게 기록됩니다.
2. 쿼리된 데이터는 완전하고 올바르게 반환됩니다.
3. 데이터가 정확하고 성능이 우수합니다.
어떻게 위와 같이 설명할 수 있는지 내부구조를 살펴보겠습니다.
Writing Data (API → Disk)
스토리지 엔진은 HTTP API 요청을 수신한 시점부터 데이터를 처리합니다. Point들을 WAL에 기록함과 동시에 메모리 내 캐시에 기록시켜 즉시 쿼리할 수 있게 대비합니다. 메모리 내 캐시는 TSM 파일 형식으로 주기적으로 디스크에 기록됩니다. TSM 파일이 누적되면 스토리지 엔진은 누적된 파일을 더 높은 수준의 TSM 파일로 결합하고 압축합니다.
Write Ahead Log (WAL)
WAL은 스토리지 엔진이 다시 시작될 때 influxDB 데이터를 유지할 수 있게 내구성을 보장해줍니다. 예기치 않은 스토리지 엔진의 종료가 있을 경우 재시작 될 때 WAL과 Storage Engine의 Sync를 맞춰 데이터의 내구성을 보장합니다.
- 쓰기 요청은 WAL 파일의 끝에 추가
- 데이터는
fsync()
를 사용하여 디스크에 기록 - in-memory 캐시에 업데이트
- 데이터가 디스크에 성공적으로 기록되면 쓰기 요청이 성공했음을 확인하는 응답 표시
fsync()
는 파일을 가져와서 보류 중인 쓰기를 디스크까지 푸시합니다. 시스템 호출로서, fsync()
에는 계산 비용이 많이 들지만 데이터가 디스크에서 안전하다는 것을 보장하는 커널 컨텍스트 스위치가 있습니다.
스토리지 엔진이 다시 시작되면 WAL 파일을 인메모리 데이터베이스로 다시 읽어들입니다. 그런 다음 influxDB는 /read
엔드포인트에 대한 요청 응답.
캐시 (Cache)
캐시는 WAL에 저장된 데이터를 in-memory에 복제한 것이므로, WAL과 캐시는 별개의 엔티티며 서로 상호작용하지 않습니다.
- 키(measurement, tag set, unique fields)별로 구성된 포인트는 시간 순으로 저장됩니다.(압축 X)
- 스토리지 엔진이 재 시작될 때마다 WAL에서 가져와서 캐싱해둡니다. 쿼리를 하면 캐시에서 데이터를 조회하고 TSM 파일에 저장된 데이터와 병합됩니다. (데이터의 캐시를 오래 유지하고 싶다면 maxSize를 늘리면 됨)
- TSM 파일에 기록되고 있는 캐시 개체를 캐시 스냅샷이라고 합니다.
- 스토리지 엔진에 대한 쿼리는 캐시의 데이터를 TSM 파일의 데이터와
merge
(아래 TSM의 저장되는 형태를 보시면 이해가 가실겁니다)해서 응답합니다.
Time-Structured Merge Tree (TSM)
스토리지 엔진은 TSM 데이터 형식을 사용합니다. 대용량의 시계열 데이터를 효율적으로 압축, 저장하기 위해 field value를 series-key별로 그룹화한 다음 해당 field value를 시간별로 정렬합니다. (series-key는 measurement, tag key, tag value, field key를 의미합니다)
- TSM 형태로 저장하면 시리즈 키로 읽고 관련없는 데이터를 생략할 수 있으므로 쿼리 성능이 뛰어납니다.
- TSM 파일에 최종적으로 안전하게 저장되면
WAL
과캐시
가 지워집니다.
TSM 파일은 압축된 series data를 열 형식으로 저장합니다. 예를 들어 다음과 같은 데이터가 있다고 가정해봅시다.
measurement: weather
| timestamp | fields: wind_speed | fields: wind_direction |
| --------- | ------------------ | ---------------------- |
| 10:15 | 3.5 | 378 |
| 10:20 | 3.7 | 380 |
위 데이터는 실제로는 다음과 같이 TSM 형태로 디스크에 저장됩니다.
[measurement, tags, field key]
-----------------------------------
[weather, wind_speed]
10:15 , 3.5
10:20 , 3.7
[weather, wind_direction]
10:15 , 378
10:20 , 380
series-key(measurement, tag key, tag value, field key)별로 시간 순서대로 저장시킵니다. 그러니까 하나의 데이터가 총 2개의 TSM 데이터 셋으로 분리되어 저장된다고 생각하시면 편합니다.
Continuous Query & Retension Policy
influxdb의 핵심적인 기능 두가지입니다. 대용량의 시계열 데이터이다 보니까 저장공간 관리 측면과 데이터들을 효율적으로 관리할 수 있게 기능들을 제공해주는 것 같습니다.
Continous Query
influxdb는 데이터를 처리하여 새롭게 저장하는 Down Sampling(다운 샘플링)을 일정 주기마다 실행되도록 하는 기능인 Continuous Query를 제공하고 있습니다.
위 기능을 이용해서 일정 주기마다 데이터들을 다운 샘플링 하여 미리 데이터를 구성해두면 → 전체 데이터를 조회하는 것보다 훨씬 더 효율적이고 빠르게 쿼리하여 응답할 수 있습니다.
Retension Policy
대량의 데이터가 쌓이고 나중에 저장공간이 부족하여 데이터를 저장하지 못하면 큰일입니다. 시계열 데이터가 대량으로 쌓이기 때문에 influxdb에서는 이 보존 정책을 제공하고 있습니다. (기본값: 영구저장)
기본 값은 영구적으로 계속 저장하는 방식으로 설정됩니다. 그렇기 때문에 보존 정책을 설정하여 오래된 데이터를 관리해주는 것이 좋습니다.
안그러면 데이터가 엄청나게 쌓여서 저장공간 부족하면 influxdb 죽습니다..
테이블 구조
RDB | InfluxDB |
---|---|
database | influxdb instance |
Table | measurement |
column | key |
indexed column | tag key (only String) |
unindexed column | field key |
row | point |
Database
In InfluxDB 2.2, a database represents the InfluxDB instance as a whole.
influxDB 2.2에서는 전체 influxDB 인스턴스를 하나의 데이터베이스로 본다고 합니다.
Measurement
- measurement는 RDB에서 Table과 같습니다.
- 어떤 값이 측정되는지에 대해 나타내는 지표가 됩니다. (예를들어, 위 테이블처럼 인구조사에 대해서 데이터를 수집한다면, measurement는 인구조사(census)가 되겠죠)
TimeStamp
- 시계열 데이터베이스에서 가장 중요한 키값인
_time
컬럼에 저장되는 값입니다. 당연히 인덱싱이 됩니다. - Timestamp는 RFC 3339(for example:
2020-01-01T00:00:00.00Z
)을 사용합니다.
Field Key, Field Value
(Required) 필수값입니다. 실제 저장하려는 키/값을 field에 넣으면 됩니다.
- Field는 Tag와 다르게 인덱싱이 안됩니다. 그렇기 때문에 Field를 이용해 필터링을 걸면 성능 저하가 심하기 때문에 인덱싱이 필요하다면 Tag를 사용하시길 바랍니다.
Tag Key, Tag Value
(Optional) 필수값은 아니지만 인덱싱이 되기 때문에 Tag를 넣어서 쿼리 성능을 높이는 것이 베스트입니다.
- Tag Key는 여러개를 설정할 수 있습니다.
- 일반적으로 쿼리를 위한 메타데이터들을 저장합니다. (예: 지역, 타입 등등)
- Tag Key는 무조건 String형입니다.
REFERENCES
- https://docs.influxdata.com/influxdb/v2/reference/internals/storage-engine
- https://docs.influxdata.com/influxdb/v2.2/reference/key-concepts/data-elements/
- https://docs.influxdata.com/influxdb/v2/reference/key-concepts/design-principles/
- https://docs.influxdata.com/influxdb/v2.2/reference/syntax/line-protocol/#elements-of-line-protocol
- https://musma.github.io/2019/07/08/getting-started-with-influxdb-time-series-database.html
- https://mangkyu.tistory.com/190
- https://www.youtube.com/watch?v=a00l1GxJszM
- https://musma.github.io/2019/07/08/getting-started-with-influxdb-time-series-database.html
- https://narup.tistory.com/169
- https://andro-jinu.tistory.com/entry/InfluxDB2?category=924198
- https://velog.io/@jee-9/InfluxDB가-무엇인가-1