시계열 데이터베이스 Time series DB

ansunny1170·2022년 3월 28일
0

단순참조

목록 보기
9/23
post-thumbnail

# influxDB 참고 영상

참조: 엑셈 웨비나 시계열 데이터베이스 'influxDB'

# 단어집 keyward


bucket - 시계열 데이터가 저장되는 명명된 위치
field - RDB unindexed columns과 유사
line protocol - influxDB에 point를 쓰기 위한 텍스트 기반 형식
measurement - RDB table에 해당
tag(string type) - RDB indexed columns과 유사

point - 단일 행의 레코드를 가진 SQL 데이터베이스와 유사, 단일 필드 모음으로 구성되고 각 point는 그 자체로 고유하게 식별
timestamp - point에 관련된 날짜와 시간, influxDB의 timestamps는 항상 나노세컨드 단위의 unix time 값으로 저장( ex 1561681930000000000ns <-> 2019-06-28T00:32:10Z)
retention policy(rp) - 데이터를 사용할 수 있는 기간 혹은 시간 지정

  • database를 사용할 때는 use <database 명>을 입력해서 선택후 measurements를 확인하거나, data row를 검색해야 한다.

  • Line protocl을 보면 가장 앞의 단어는 <measurements 명>이다.

  • tag와 field 구분은 공백으로 한다.

## tag 및 field 확인

tag는 오로지 string 타입만 가능
show tag keys
field는 다양한 타입의 값을 가질 수 있음
show field keys

## data 백업, 삭제 및 복구

30분
시계열 데이터를 저장하고 백업하는게 좋다.
influxd backup -portable - database <database 명> <백업경로 ex /tmp/backup>
백업을 했다면 measurements와 database를 순서대로 지워주자
drop measurement <measurements 명>
제대로 지워졌는지 확인
show mesasurements
database를 지운다
drop database <database 명>
제대로 지워졌는지 확인
show database
나중에 다시 데이터 확인해야 할 때 복구하면 된다.
influxd restore -potable -db <database 명> <백업경로 ex /tmp/backup>

## data file db에 저장

40분
#DDL - 관련 database를 만들고 있으면 무시
#DML - 관련 database 및 line protocol 형식의 데이터를 포함하는 형식이다.

입력방법

# DDL
CREATE DATABASE : market

# DML

# CONTEXT-DATABASE: market

파일 데이터를 db에 저장한다.
path: 데이터가 있는 경로
database: load할 influxDB의 데이터베이스명(파일 내 CREATE 데이터베이스 문이 있을 시 생략 가능)
precicsion: 시간의 단위(s, ns등)
influx -import -path=ticker_data.txt -database=market -precision=s
홈디렉토리에 있을 때는 파일명만 입력한다.

데이터베이스 및 measurements 확인
show databases
use <데이터베이스 명>
show measurements

## 데이터 보존 정책

### retention policy(rp, 보존 정책)

데이터를 사용할 수 있는 기간 혹은 시간을 지정

오래된 데이터는 rp를 설정해서 자동 삭제 시켜야함

duration: influxDB가 데이터를 보관하는 기간
replication factor: 클러스터에 저장된 데이터의 복사본 수 (단일서버는 1로 지정되어있음)
shard grops: 샤드와 샤드의 논리적 컨테이너로 실제 데이터가 들어 있음
shard group duration: 샤드 그룹에 의해 보호되는 시간 범위

보존 정책 확인, 데이터 베이스의 retention policy를 조회
show retention policies on <database 명>
rp가 정의되지 않은 경우 기본 rp(autogen)가 적용
autogen은 복제 수가 1이고(무한대), 샤드 그룹 기간이 7일이고 무한대의 지속기간을 가짐

rp생성
rp이름: exem_rp
database: market
duration: 365일(1년)
replication: 1(단일서버이므로)
shard duration: 2주
create retention policy exem_rp on market duration 365d replication 1 shard duration 2w default

### retention policy 수정

alter retention policy exem_rp on market duration 4w shard duration 30m default
수정할 rp명: exem_rp
market 데이터베이스의 duration을 4주, shard duration을 30분으로 rp를 수정한는 작업
show retention policies on market

### retention policy 삭제

Drop retention policy exem_rp on market
database 생성시 최초의 rp 즉, autogen은 남아있을 수 있다. 대신 default = false로 되어 있다.

exem_rp의 rp를 삭제하였지만 설정은 따로 변경해줘야 한다.
바로 select * from <measurement 명> 하면 rp가 없다고 ERR발생한다.
alter retention policy autogen on market default
이렇게 하면 autogen default가 true로 된다.
그리고 select ... 하면 정상 가능

# InfluxDB 시작

## 세팅방법-1 (InfluxDB 실행파일 설치)

참조: influx 설치
https://portal.influxdata.com/downloads/

wget https://dl.influxdata.com/influxdb/releases/influxdb-1.8.10_windows_amd64.zip -UseBasicParsing -OutFile influxdb-1.8.10_windows_amd64.zip
Expand-Archive .\influxdb-1.8.10_windows_amd64.zip -DestinationPath 'C:\Program Files\InfluxData\influxdb\'

influxd.exe를 cli로 실행시키고 동시에 influx.exe를 더블클릭하여 실행하였더니 cmd가 실행되었다.
show databases를 사용하니 정상 작동한다.

## 세팅방법-2 (docker InfluxDB image 사용)

참조: docker image file(influxDB)
자세한 사용방법은 위 사이트를 참고하자
사용한 버전은 1.8.10버전이다.

특이한 점이 있는데 volumes에서 influxdb.conf파일은 저렇게 설정해서는 가져올 수가 없다.
테스트한 끝에 이해한 바로는 influxdb.conf파일안에 /var/lib/influxdb의 폴더 및 파일들에 대해 세팅한 내용이 이미 있어서 두 번째 볼륨은 안가져 오는 것이다.(정확히 어떻게 표현해야 할지 모르겠다.) 순서를 바꿔도 똑같다.

나는 docker exec ... bash로 image파일에 접근하여 influxdb.conf파일을 직접 cp명령오로 복사해 왔다. 그리고나서 해보니 정상적으로 나머지 볼륨을 진행한다.

docker-compose.yaml

influxdb: 
    image: influxdb:1.8.10 
    # container_name: influx
    ports: 
      # - '8086:8086'
      - '8087:8086'
    networks:
      - monitoring 
      # - webnet 
    # environment: 
    #   - INFLUXDB_DB=backend
    #   # - INFLUXDB_USER=telegraf
      # - INFLUXDB_ADMIN_ENABLED=true
      # - INFLUXDB_ADMIN_USER=admin 
      # - INFLUXDB_ADMIN_PASSWORD=admin    
    tty: true
    stdin_open: true
    volumes: 
      - ./influx/config:/etc/influxdb
      - ./influxdb:/var/lib/influxdb 

이렇게 세팅하고 docker-compose.yaml 파일을 실행시키면 된다.
docker-compose up -d influxdb
1. -d는 백그라운드 실행
2. influxdb는 해당 서비스만 선택해서 실행하는 것이다.
docker-compose ps
현재 띄운 서비스 확인
docker-compose down
up시킨 서비스 내려놓기

## 코드세팅

const express = require('express');
const http = require('http');

const mqtt = require('mqtt');
const Influx = require('influx');

const dotenv = require('dotenv');

const app = express();

// const client = mqtt.connect('mqtt://220.90.129.47:1883');
// const client = mqtt.connect('mqtt://220.90.129.60:1883');
const client = mqtt.connect('mqtt://localhost');
client.subscribe('#');

const influx = new Influx.InfluxDB({
  host: process.env.TSDB_HOST,
  port: process.env.TSDB_PORT,
  database: process.env.TSDB_DATABASE,
  schema: [
    {
      measurement: 'plcdata',
      fields: {
        // DataTime: Influx.FieldType.DataTime,
        Start: Influx.FieldType.BOOLEAN,
        No1PartsError: Influx.FieldType.BOOLEAN,
        No1_Action: Influx.FieldType.BOOLEAN,
        No2_Action: Influx.FieldType.BOOLEAN,
        No3Ready: Influx.FieldType.BOOLEAN,
        ColorSensor: Influx.FieldType.BOOLEAN,
        VisionSensor: Influx.FieldType.INTEGER,
        Reset: Influx.FieldType.BOOLEAN,
        no1_on_off: Influx.FieldType.BOOLEAN,
        no2_on_off: Influx.FieldType.BOOLEAN,
        no3_on_off: Influx.FieldType.BOOLEAN,
        sensor1_on_off: Influx.FieldType.BOOLEAN,
        sensor2_on_off: Influx.FieldType.BOOLEAN,
        No1Delay: Influx.FieldType.INTEGER,
        No1Count: Influx.FieldType.INTEGER,
        No2Count: Influx.FieldType.INTEGER,
        No3Count: Influx.FieldType.INTEGER,
        lamp_green: Influx.FieldType.BOOLEAN,
        lamp_yellow: Influx.FieldType.BOOLEAN,
        lamp_red: Influx.FieldType.BOOLEAN,
        No3Motor1: Influx.FieldType.INTEGER,
        No3Motor2: Influx.FieldType.INTEGER,
        No1ChipFull: Influx.FieldType.BOOLEAN,
        No2Chip: Influx.FieldType.BOOLEAN,
        No2CubeFull: Influx.FieldType.BOOLEAN,
        No2InPoint: Influx.FieldType.BOOLEAN,
        No2OutPoint: Influx.FieldType.BOOLEAN,
        No2Sol: Influx.FieldType.BOOLEAN,
        No2SolAction: Influx.FieldType.BOOLEAN,
        No2BackToSquare: Influx.FieldType.BOOLEAN,
        No2Mode: Influx.FieldType.BOOLEAN,
        No3Chip: Influx.FieldType.BOOLEAN,
        VisionCmdMemory: Influx.FieldType.BOOLEAN,
        No3DiceReading: Influx.FieldType.INTEGER,
        Emergency: Influx.FieldType.BOOLEAN,
        OutputLimit: Influx.FieldType.INTEGER,
        DiceValue: Influx.FieldType.INTEGER,
        DiceComparisonValue: Influx.FieldType.INTEGER,
        ColorSensorSensing: Influx.FieldType.BOOLEAN,
        No3Gripper: Influx.FieldType.BOOLEAN,
      },
      tags: ['DataTime'],
      // tags: ['temp', 'temp1'],
    },
  ],
});

influx
  .getDatabaseNames()
// eslint-disable-next-line consistent-return
  .then((names) => {
    if (!names.includes('backend')) {
      console.log(`My database names are: ${names.join(', ')}`);
      console.log('there is no database');
      return influx.createDatabase('backend');
    }
  })
  /* .then(() => {
    http.createServer(app).listen(3000, () => {
      // console.log(`My database names are2: ${names.join(', ')}`);
      console.log('Listening on port 3000');
    });
  }) */
  .catch((err) => {
    console.error('Error creating Influx database!');
    console.log(({ err }));
  });

client.on('message', (topic, payload) => {
  console.log(`0: ${topic}: ${payload}`);
  // console.log(`1: ${topic}: ${JSON.stringify(payload)}`);
  // console.log(`2: ${topic}: ${JSON.parse(payload).tags}`);
  // console.log(`3: ${topic}: ${JSON.parse(payload).Wrapper}`);
  // console.log(`4: ${topic}: ${JSON.parse(payload).Wrapper[1].tagId}`);
  // console.log(`5: ${topic}: ${JSON.parse(payload).Wrapper[1].name}`);

  const keys = [];
  const values = [];
  let tags = {};
  let fields = {};

  for (let i = 0; i < JSON.parse(payload).Wrapper.length; i += 1) {
    keys[i] = JSON.parse(payload).Wrapper[i].name;
    values[i] = JSON.parse(payload).Wrapper[i].value;
    console.log(i, JSON.parse(payload).Wrapper.length, keys[i], values[i]);
  }
  console.log('keys: ', keys);
  console.log('values: ', values);

  for (let i = 0; i < keys.length; i += 1) {
    if (keys[i] === 'DataTime') {
      tags = {
        [keys[i]]: values[i],
      };
    } else {
      fields = {
        ...fields,
        [keys[i]]: values[i],
      };
    }
    console.log(i, keys.length);
    console.log('tags: ', tags);
    console.log('fields: ', fields);
  }

  influx.writePoints([
    {
      measurement: 'plcdata',
      tags,
      fields,
    },
  ], {
    // database: 'backend',
    // retentionPolicy: '1d',
    precision: 's', // 정밀도 (s)초
  }).catch((error) => {
    console.error(`Error saving data to InfluxDB! ${error.stack}`);
  });
});

## InfluxDB studio (UI)

참조: InfluxDB Studio - github
참조: Getting started with InfluxDB Part 1: Installation

# docker-compose 사용 방법

## docker-compose 설치

참조: Nirsa - [Docker CE] Centos 7 docker-compose 설치

Centos7 docker-compose 설치 방법 이고 root 계정으로 진행해야 한다. (root계정이 아닐 시 sudo 사용)

curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 

# 바이너리 실행 권한 부여 chmod +x /usr/local/bin/docker-compose 

# docker-compose 설치되었는지 확인 docker-compose --version

만약 바이너리 실행 권한 부여할 때의 명령(chmod ~)이 실패 했다면 아래와 같이 심볼릭 링크 설정을 해주시면 된다.

ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

## docker-compose 명령어

  • 버전 확인
    docker-compose --version
  • 컨테이너를 생성 및 실행
    docker-compose up
    docker-compose up <옵션> <서비스명>
옵션설명
-d백그라운드 실행
--no-deps링크 서비스 실행하지 않음
--build이미지 빌드
-t타임아웃을 지정(기본 10초)

참고로 특정 서비스들의 경우 백그라운드로 실행하지 않으면 컨테이너가 생성 및 실행되며 바로 종료될 수 있다.

  • 현재 동작중인 컨테이너들의 상태를 확인
    docker-compose ps

  • 컨테이너들의 로그를 출력
    docker-compose logs

  • docker-compose up 명령어를 이용해 생성 및 실행된 컨테이너에서 임의의 명령을 실행하기 위해 사용
    컨테이너들을 모두 삭제할 경우 docker-compose start가 아닌, docker-compose up으로 다시 컨테이너들을 생성 해주어야 한다.
    docker-compose run

만약 특정 서비스에서 /bin/bash를 실행시켜 쉘 환경으로 진입하고 싶다면 아래와 같은 명령어를 이용하면 된다. 참고로 서비스명과 컨테이너명은 다르다.

서비스명은 docker-compose.yml의 services: 밑에 작성한 서비스 이름

# docker-compose run <서비스명> <명령>
docker-compose run redis /bin/bash
  • 여러개의 서비스 또는 특정 서비스를 시작 / 정지 / 일시정지 / 재시작을 할 수 있다
    docker-compose (start / stop / pause / unpause / restart)
# 서비스 시작
docker-compose start
# 서비스 정지
docker-compose stop
# 서비스 일시 정지
docker-compose pause
# 서비스 일시 정지 해제
docker-compose unpause
# 서비스 재시작
docker-compose restart

각각의 설정 뒤에 서비스명을 붙이면 특정 서비스만 제어할 수 있다. (ex. docker-compose restart <서비스명>)

  • docker-compose로 생성한 컨테이너들을 일괄 삭제 (삭제 전, 관련 컨테이너들을 종료 시켜두어야 한다.)
    docker-compose rm
  • 실행중인 컨테이너를 강제로 정지
    docker-compose kill
    -s옵션을 사용하여 시그널을 지정해줄 수 있는데, 아래 코드에서는 SIGINT를 사용 하였다. -s 옵션을 사용하지 않고 docker-compose kill만 사용할 경우 SIGKILL 이 전송 된다.

kill 뒤에 서비스를 지정하여 특정 서비스만 kill할 수 있다.

# docker-compose kill <옵션>
docker-compose kill -s SIGINT
  • 네트워크 정보, 볼륨, 컨테이너들을 일괄 정지 및 삭제 처리
    docker-compose down
    만약 docker-compose down --rmi all 명령을 사용한다면 모든 이미지까지 삭제 한다.

  • 서비스 프라이빗 포트 번호의 설정을 확인할 수 있다.

# docker-compose port <서비스명> <프라이빗 포트 번호>
docker-compose port nginx 80
  • docker-compose 구성 파일의 내용을 확인할 수 있다. docker-compose.yml의 내용을 출력 해주므로 많이 쓸일은 없다.
    docker-compose config

## influxdb cli 사용위치 접근 법

docker exec -it <container name> bash
influx 를 입력하면 cli를 사용하는 위치로 이동하게 된다.
show databases - database 보기
drop database <database 명>

이렇게 하면 된다.

profile
공정 설비 개발/연구원에서 웹 서비스 개발자로 경력 이전하였습니다. Node.js 백엔드 기반 풀스택 개발자를 목표로 하고 있습니다.

0개의 댓글