참조: 엑셈 웨비나 시계열 데이터베이스 'influxDB'
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는 오로지 string 타입만 가능
show tag keys
field는 다양한 타입의 값을 가질 수 있음
show field keys
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>
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
데이터를 사용할 수 있는 기간 혹은 시간을 지정
오래된 데이터는 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
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
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 ... 하면 정상 가능
참조: 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를 사용하니 정상 작동한다.
참조: 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 - github
참조: Getting started with InfluxDB Part 1: Installation
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 --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 rm
docker-compose kill
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 config
docker exec -it <container name> bash
influx
를 입력하면 cli를 사용하는 위치로 이동하게 된다.
show databases
- database 보기
drop database <database 명>
이렇게 하면 된다.