inflxudb 实时数据库,用来存储大量的实时数据,经过测试十万条数据存储只需要七八十毫秒,速度非常快,查询速度也非常好,吞吐量极高,并且本身具有归档功能(即:编写cq连续查询,可以取一段时间的平均值,自动存储),这样为数据存储/统计,非常友好.
与传统数据库比较
绿色版,无须安装一件运行
链接:https://pan.baidu.com/s/1BxWXkgDhyOFWXbJ2C5nQ7g
提取码:o6l0
概念 MySQL InfluxDB
数据库(同) database database
表(不同) table measurement
列(不同) column tag(带索引的,非必须)、field(不带索引)、timestemp(唯一主键)
retention policy:数据存储策略(默认策略为autogen)InfluxDB没有删除数据操作,规定数据的保留时间达到清除数据的目的;
常用命令
-- 查看所有的数据库
show databases;
-- 使用特定的数据库
use database_name;
-- 查看所有的measurement
show measurements;
-- 查询10条数据
select*frommeasurement_namelimit10;
-- 数据中的时间字段默认显示的是一个纳秒时间戳,改成可读格式
precisionrfc3339;-- 之后再查询,时间就是rfc3339标准格式
-- 或可以在连接数据库的时候,直接带该参数
influx -precisionrfc3339
-- 查看一个measurement中所有的tag key
show tag keys
-- 查看一个measurement中所有的field key
show field keys
-- 查看一个measurement中所有的保存策略(可以有多个,一个标识为default)
show retention policies;
-- 查看当前数据库的Retention Policies
SHOW RETENTION POLICIESON"testDB"
-- 创建新的Retention Policies
CREATERETENTION POLICY"rp_name"ON"db_name"DURATION30d REPLICATION1DEFAULT
-- rp_name:策略名
-- db_name:具体的数据库名
-- 30d:保存30天,30天之前的数据将被删除
-- 它具有各种时间参数,比如:h(小时),w(星期)
-- REPLICATION 1:副本个数,这里填1就可以了
-- DEFAULT 设为默认的策略
-- 修改策略
ALTERRETENTION POLICY"2_hours"ON"telegraf"DURATION4h DEFAULT
-- 删除策略
dropretention POLICY"2_hours"ON"telegraf"
-- # 创建表
-- # 直接在插入数据的时候指定表名(weather就是表名)
insertweather,altitude=1000,area=北 temperature=11,humidity=-4
-- # 删除表
DROPMEASUREMENT"measurementName"
-- 显示用户
SHOW USERS
-- # 创建用户
CREATEUSER"username"WITH PASSWORD'password'
-- # 创建管理员权限的用户
CREATEUSER"username"WITH PASSWORD'password'WITH ALL PRIVILEGES
-- # 删除用户
DROPUSER"username"
-- 创建数据库
CREATEDATABASE mydb
-- 登陆
auth
用户名
密码
-- 插入数据
insertorders,phone=20website=90
-- 查询所有的cq
show continuous queries
-- 删除一个cq
DROPCONTINUOUS QUERY ON
默认端口8086
建表语句
createdatabase water_database
insert calculat_db,createTime="2020-08-20",dataName="A_por_6654"dataValue=23,reportTime="2020-08-20"
insert problem_db,problemName="A_S_234",problemValue=66itemMinValue=23,itemMaxValue=64
insert warndata_db,createTime="2020-08-20",dataName="A_por_6654"dataValue=16,itemWarnValueMin=20,itemWarnValueMax=53,areaCode="ZW001",areaName="中维",areaPointId="adfdsfduiedfijisf",deviceName="中维设备",content="xxx数据项低于最低阈值4"
CREATECONTINUOUS QUERY cq_1mONwater_databaseBEGINSELECTmean(dataValue)ASmeanValueINTOwater_database.rp_ten_year.cal_mean_dbFROMwater_database.rp_ten_year.calculat_dbGROUPBYtime(1m),dataName END
SELECTmean(dataValue)ASmeanValueINTOcal_mean_dbFROMcalculat_dbGROUPBYtime(1m),dataName
备注
1 也可以使用linux版的,没有什么差别,他如同大多数nosql数据一样,可以封装一个util 去操作它
2 其中归档功能必须是有实时数据后,才会触发归档(当时写好连续查询一直以为有问题,坑了我好久)
3 influxdb 的分页 SELECT * FROM "calculat_db" limit 20 OFFSET 0 ====>> limit 代表 每页条数 offset 代表 当前页码且从0 开始
下面分享下我项目中百度到的工具类
TsdbService
```
import com.jovision.sfwl.modules.datacenter.influxdb.bean.UniteMetricData;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.QueryResult;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public interface TsdbService {
void createDatabase(String database);
void dropDatabase(String database);
boolean databaseExist(String database);
void createRetentionPolicy();
void createRetentionPolicy(String database, String policyName, String duration, int replication, Boolean isDefault);
void dropRetentionPolicy();
void dropRetentionPolicy(String database, String retentionPolicy);
void createContinuousQuery(String measurement, String extendPolicy);
boolean continuousQueryExists(String measurement);
boolean continuousQueryExists(String database, String cqName);
void dropContinuousQuery(String databaseName, String cqName);
boolean measurementsExists(String measurement);
boolean measurementsExists(String database, String measurement);
QueryResultquery(String command);
QueryResultdataQuery(String command);
void insert(Point point1);
void insert(String measurement, TimeUnit timeUnit, UniteMetricData data);
void batchInsert(BatchPoints batchPoints);
PointpointBuilder(String measurement,
Map tags,
Map fields,
long time,
TimeUnit timeunit);
BatchPointsbuildBatchPoints();
BatchPointsbatchPointsBuilder(String database, InfluxDB.ConsistencyLevel level, TimeUnit precision);
BatchPointsbatchPointsBuilder(String database, InfluxDB.ConsistencyLevel level, TimeUnit precision, String retentionPolicy);
}
```
TsdbServiceImpl
```
import com.jovision.sfwl.modules.datacenter.influxdb.bean.UniteMetricData;
import org.influxdb.BatchOptions;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@Service("tsdbService")
public class TsdbServiceImplimplements TsdbService {
private static final Loggerlogger = LoggerFactory.getLogger(TsdbServiceImpl.class);
private static final InfluxDB.ConsistencyLevelCONSISTENCY_LEVEL = InfluxDB.ConsistencyLevel.ANY;
private static final TimeUnitPRECESION = TimeUnit.SECONDS;
@Value("${tsdb.server.url}")
private Stringurl;
/**
* 用户名
*/
@Value("${tsdb.server.username}")
private Stringusername;
/**
* 密码
*/
@Value("${tsdb.server.password}")
private Stringpassword;
/**
* 数据库
*/
@Value("${tsdb.server.database}")
private Stringdatabase;
/**
* 保留策略
*/
@Value("${tsdb.server.retentionpolicy}")
private StringretentionPolicy;
private InfluxDBinfluxDB;
@PostConstruct
public void init() {
/* List serverAddressList = new ArrayList<>();
for (String host : hosts.split(",")) {
serverAddressList.add(String.format("%s:%s", host, port));
}
influxDB = InfluxDBFactory.connect(serverAddressList, username, password);
*/
influxDB = InfluxDBFactory.connect(url, username, password);
try {
// 如果指定的数据库不存在,则新建一个新的数据库,并新建一个默认的数据保留规则
if (!this.databaseExist(database)) {
createDatabase(database);
createRetentionPolicy();
}
}catch (Exception e) {
// 该数据库可能设置动态代理,不支持创建数据库
logger.error("[TsdbService] occur error when init tsdb, err msg: {}", e);
}finally {
influxDB.setRetentionPolicy(retentionPolicy);
}
influxDB.setLogLevel(InfluxDB.LogLevel.NONE);
// Flush every 1000 Points, at least every 100ms
// bufferLimit represents the maximum number of points can stored in the retry buffer
// exceptionHandler represents a consumer function to handle asynchronous errors
// threadFactory represents the ThreadFactory instance to be used
influxDB.enableBatch(BatchOptions.DEFAULTS
.actions(1000)
.flushDuration(100)
.bufferLimit(10)
.exceptionHandler((points, e) -> {
List target =new ArrayList<>();
points.forEach(target::add);
String msg = String.format("failed to write points:%s\n", target.toString().substring(0, 10000));
logger.error(msg, e);
})
.threadFactory(
Executors.defaultThreadFactory()
));
}
/**
* 测试连接是否正常
*
* @return true 正常
*/
public boolean ping() {
boolean isConnected =false;
Pong pong;
try {
pong =influxDB.ping();
if (pong !=null) {
isConnected =true;
}
}catch (Exception e) {
e.printStackTrace();
}
return isConnected;
}
@Override
public void createDatabase(String database) {
influxDB.query(new Query("CREATE DATABASE " + database, ""));
}
@Override
public void dropDatabase(String database) {
influxDB.query(new Query("DROP DATABASE " + database, ""));
}
@Override
public boolean databaseExist(String database) {
return influxDB.databaseExists(database);
}
@Override
public void createRetentionPolicy() {
String command = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s DEFAULT",
"default_policy", database, "90d", 3);
this.query(command);
}
/**
* @return void
* @Description
* @Author 寂寞旅行
* @Date 10:48 2020/8/20
* @Param [database, policyName, duration, replication, isDefault]
* 数据库 策略名 时间 1 是否为默认策略
**/
@Override
public void createRetentionPolicy(String database, String policyName, String duration, int replication, Boolean isDefault) {
String sql = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s ", policyName,
database, duration, replication);
if (isDefault) {
sql = sql.concat(" DEFAULT");
}
this.query(sql);
}
@Override
public void dropRetentionPolicy() {
this.dropRetentionPolicy(database, retentionPolicy);
}
@Override
public void dropRetentionPolicy(String database, String retentionPolicy) {
String sql = String.format("DROP RETENTION POLICY %s ON %s", retentionPolicy, database);
this.query(sql);
}
@Override
public void createContinuousQuery(String measurement, String extendPolicy) {
String cqName = String.format("cq_%s", measurement);
String originMeasurement = String.format("%s.%s.%s", database, retentionPolicy, measurement);
String cqMeasurement = String.format("%s.%s.%s_hour", database, extendPolicy, measurement);
String sql = String.format("CREATE CONTINUOUS QUERY \"%s\" ON %s RESAMPLE EVERY 1h FOR 2h BEGIN SELECT MEAN(*) INTO %s FROM %s GROUP BY time(1h),* FILL(none) END",
cqName, database, cqMeasurement, originMeasurement);
this.query(sql);
}
@Override
public boolean continuousQueryExists(String measurement) {
String cqName = String.format("cq_%s", measurement);
return continuousQueryExists(database, cqName);
}
@Override
public boolean continuousQueryExists(String database, String cqName) {
String sql ="SHOW CONTINUOUS QUERIES";
QueryResult result = query(sql);
List seriesList = result.getResults().get(0).getSeries();
if (seriesList !=null) {
for (QueryResult.Series series : seriesList) {
if (database.equals(series.getName())) {
List> continuousQueryList = series.getValues();
if (continuousQueryList ==null) {
return false;
}else {
for (List queryResult : continuousQueryList) {
if (cqName.equals(queryResult.get(0))) {
return true;
}
}
}
}
}
}
return false;
}
@Override
public void dropContinuousQuery(String databaseName, String cqName) {
String sql = String.format("DROP CONTINUOUS QUERY %s ON %s", cqName, databaseName);
QueryResult result = query(sql);
}
@Override
public boolean measurementsExists(String measurement) {
return measurementsExists(database, measurement);
}
@Override
public boolean measurementsExists(String database, String measurement) {
String sql = String.format("SHOW MEASUREMENTS ON %s", database);
QueryResult result = query(sql);
if (result !=null) {
List seriesList = result.getResults().get(0).getSeries();
if (seriesList !=null) {
QueryResult.Series series = seriesList.get(0);
List> valueList = series.getValues();
for (List value : valueList) {
if (measurement.equals(value.get(0))) {
return true;
}
}
}
}
return false;
}
@Override
public QueryResultquery(String command) {
return influxDB.query(new Query(command, database));
}
@Override
public QueryResultdataQuery(String command) {
return influxDB.query(new Query(command, database), TimeUnit.MILLISECONDS);
}
@Override
public void insert(Point point1) {
influxDB.write(point1);
}
@Override
public void insert(String measurement, TimeUnit timeUnit, UniteMetricData data) {
timeUnit = timeUnit ==null ? TimeUnit.MILLISECONDS : timeUnit;
Point point = pointBuilder(measurement, data.getTags(), data.getFields(), data.getTimestamp(), timeUnit);
influxDB.write(database, retentionPolicy, point);
}
@Override
public void batchInsert(BatchPoints batchPoints) {
influxDB.write(batchPoints);
}
@Override
public PointpointBuilder(String measurement,
Map tags,
Map fields,
long time,
TimeUnit timeunit) {
Point point = Point.measurement(measurement).time(time, timeunit).tag(tags).fields(fields).build();
return point;
}
@Override
public BatchPointsbuildBatchPoints() {
return this.batchPointsBuilder(database, CONSISTENCY_LEVEL, PRECESION);
}
@Override
public BatchPointsbatchPointsBuilder(String database, InfluxDB.ConsistencyLevel level, TimeUnit precision) {
return batchPointsBuilder(database, level, precision, null);
}
@Override
public BatchPointsbatchPointsBuilder(String database, InfluxDB.ConsistencyLevel level, TimeUnit precision, String retentionPolicy) {
return BatchPoints.database(database).consistency(level).precision(precision).retentionPolicy(retentionPolicy).build();
}
}
```
UniteMetricData
```
import lombok.Data;
import java.util.Map;
@Data
public class UniteMetricData {
private static final long serialVersionUID =8968059029015805484L;
private Maptags;
private Mapfields;
private long timestamp;
public UniteMetricData(Map tags, Map fields, long timestamp) {
this.tags = tags;
this.fields = fields;
this.timestamp = timestamp;
}
public MapgetTags() {
return tags;
}
public void setTags(Map tags) {
this.tags = tags;
}
public MapgetFields() {
return fields;
}
public void setFields(Map fields) {
this.fields = fields;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
```
linux下安装
```
wget https://dl.influxdata.com/influxdb/releases/influxdb-1.5.3.x86_64.rpm
sudo yum localinstall influxdb-1.5.3.x86_64.rpm
```
安装好后更改influx.conf配置 使其加入用户认证过程
vim ****influx.conf
更改 auth-enabled-false 改为 auth-enabled = true
保存退出(esc +:wq )
然后启动ifnlux
```
sudo service influxdb start
```