gotidb/examples/engine/multi_engine.go

264 lines
7.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"context"
"fmt"
"log"
"os"
"time"
"git.pyer.club/kingecg/gotidb/pkg/engine"
"git.pyer.club/kingecg/gotidb/pkg/engine/file"
"git.pyer.club/kingecg/gotidb/pkg/engine/memory"
)
func main() {
// 创建引擎注册表
registry := engine.NewEngineRegistry()
// 注册内存引擎和文件引擎
memory.Register(registry)
file.Register(registry)
// 创建临时目录用于文件引擎
tempDir, err := os.MkdirTemp("", "gotidb_example_*")
if err != nil {
log.Fatal("Failed to create temp dir:", err)
}
defer os.RemoveAll(tempDir)
// 创建内存引擎配置
memConfig := engine.NewEngineConfig().
WithMaxRetention(24 * time.Hour).
WithMaxPoints(1000)
// 创建文件引擎配置
fileConfig := engine.NewEngineConfig()
fileConfig.SetFileConfig(&engine.FileEngineConfig{
DataDir: tempDir,
SegmentSize: 1024 * 1024, // 1MB
CompactWindow: time.Hour,
MaxSegments: 10,
UseCompression: true,
CompressionLevel: 6,
})
// 创建内存引擎和文件引擎实例
memEng, err := registry.Create("memory", memConfig)
if err != nil {
log.Fatal("Failed to create memory engine:", err)
}
fileEng, err := registry.Create("file", fileConfig)
if err != nil {
log.Fatal("Failed to create file engine:", err)
}
// 打开引擎
if err := memEng.Open(); err != nil {
log.Fatal("Failed to open memory engine:", err)
}
defer memEng.Close()
if err := fileEng.Open(); err != nil {
log.Fatal("Failed to open file engine:", err)
}
defer fileEng.Close()
// 演示不同场景下的引擎使用
// 场景1高频写入短期存储 - 使用内存引擎
fmt.Println("\n=== 场景1高频写入短期存储内存引擎===")
demoHighFrequencyWrites(memEng)
// 场景2长期存储历史数据查询 - 使用文件引擎
fmt.Println("\n=== 场景2长期存储历史数据查询文件引擎===")
demoHistoricalData(fileEng)
// 场景3聚合查询性能对比
fmt.Println("\n=== 场景3聚合查询性能对比 ===")
demoAggregationComparison(memEng, fileEng)
// 打印引擎统计信息
printEngineStats("Memory Engine", memEng)
printEngineStats("File Engine", fileEng)
}
// 演示高频写入场景
func demoHighFrequencyWrites(eng engine.Engine) {
start := time.Now()
count := 1000
// 批量写入数据
var points []engine.DataPoint
for i := 0; i < count; i++ {
points = append(points, engine.DataPoint{
DeviceID: "sensor001",
MetricCode: "temperature",
Labels: map[string]string{
"location": "room1",
"floor": "1st",
},
Value: 25.5 + float64(i%10),
Timestamp: time.Now().Add(time.Duration(i) * time.Millisecond).UnixNano(),
})
}
if err := eng.WriteBatch(context.Background(), points); err != nil {
log.Printf("Failed to write batch: %v", err)
return
}
duration := time.Since(start)
fmt.Printf("写入 %d 个数据点耗时: %v (%.2f points/sec)\n",
count, duration, float64(count)/duration.Seconds())
// 查询最新数据
query := engine.NewQueryBuilder().
ForMetric("temperature").
WithTag("location", engine.OpEqual, "room1").
Build()
query.Type = engine.QueryTypeLatest
result, err := eng.Query(context.Background(), query)
if err != nil {
log.Printf("Failed to query latest data: %v", err)
return
}
if tsResult, ok := result.(*engine.TimeSeriesResult); ok {
fmt.Printf("最新数据点: %.2f (时间: %v)\n",
tsResult.Points[0].Value,
time.Unix(0, tsResult.Points[0].Timestamp).Format(time.RFC3339))
}
}
// 演示历史数据存储和查询场景
func demoHistoricalData(eng engine.Engine) {
// 写入跨越多个时间段的数据
now := time.Now()
var points []engine.DataPoint
for i := 0; i < 24; i++ {
points = append(points, engine.DataPoint{
DeviceID: "sensor002",
MetricCode: "power",
Labels: map[string]string{
"device": "solar_panel",
"unit": "watts",
},
Value: 100 + float64(i*50),
Timestamp: now.Add(time.Duration(-i) * time.Hour).UnixNano(),
})
}
if err := eng.WriteBatch(context.Background(), points); err != nil {
log.Printf("Failed to write historical data: %v", err)
return
}
// 查询24小时内的数据
query := engine.NewQueryBuilder().
ForMetric("power").
WithTimeRange(now.Add(-24*time.Hour).UnixNano(), now.UnixNano()).
WithTag("device", engine.OpEqual, "solar_panel").
Build()
result, err := eng.Query(context.Background(), query)
if err != nil {
log.Printf("Failed to query historical data: %v", err)
return
}
if tsResult, ok := result.(*engine.TimeSeriesResult); ok {
fmt.Printf("24小时内的数据点数量: %d\n", len(tsResult.Points))
if len(tsResult.Points) > 0 {
fmt.Printf("最早数据点: %.2f (时间: %v)\n",
tsResult.Points[0].Value,
time.Unix(0, tsResult.Points[0].Timestamp).Format(time.RFC3339))
fmt.Printf("最新数据点: %.2f (时间: %v)\n",
tsResult.Points[len(tsResult.Points)-1].Value,
time.Unix(0, tsResult.Points[len(tsResult.Points)-1].Timestamp).Format(time.RFC3339))
}
}
}
// 演示聚合查询性能对比
func demoAggregationComparison(memEng, fileEng engine.Engine) {
// 准备测试数据
now := time.Now()
var points []engine.DataPoint
for i := 0; i < 1000; i++ {
points = append(points, engine.DataPoint{
DeviceID: "sensor003",
MetricCode: "cpu_usage",
Labels: map[string]string{
"host": "server1",
},
Value: float64(30 + (i % 40)),
Timestamp: now.Add(time.Duration(-i) * time.Minute).UnixNano(),
})
}
// 写入两个引擎
if err := memEng.WriteBatch(context.Background(), points); err != nil {
log.Printf("Failed to write to memory engine: %v", err)
return
}
if err := fileEng.WriteBatch(context.Background(), points); err != nil {
log.Printf("Failed to write to file engine: %v", err)
return
}
// 创建聚合查询
query := engine.NewQueryBuilder().
ForMetric("cpu_usage").
WithTimeRange(now.Add(-24*time.Hour).UnixNano(), now.UnixNano()).
WithTag("host", engine.OpEqual, "server1").
WithAggregation(engine.AggAvg, 1*time.Hour).
Build()
// 测试内存引擎聚合性能
memStart := time.Now()
memResult, err := memEng.Query(context.Background(), query)
if err != nil {
log.Printf("Memory engine aggregation failed: %v", err)
return
}
memDuration := time.Since(memStart)
// 测试文件引擎聚合性能
fileStart := time.Now()
fileResult, err := fileEng.Query(context.Background(), query)
if err != nil {
log.Printf("File engine aggregation failed: %v", err)
return
}
fileDuration := time.Since(fileStart)
// 打印性能对比
fmt.Printf("内存引擎聚合查询耗时: %v\n", memDuration)
fmt.Printf("文件引擎聚合查询耗时: %v\n", fileDuration)
if memAgg, ok := memResult.(*engine.AggregateResult); ok {
fmt.Printf("内存引擎聚合组数: %d\n", len(memAgg.Groups))
}
if fileAgg, ok := fileResult.(*engine.AggregateResult); ok {
fmt.Printf("文件引擎聚合组数: %d\n", len(fileAgg.Groups))
}
}
// 打印引擎统计信息
func printEngineStats(name string, eng engine.Engine) {
stats := eng.Stats()
caps := eng.Capabilities()
fmt.Printf("\n=== %s 统计信息 ===\n", name)
fmt.Printf("数据点总数: %d\n", stats.PointsCount)
fmt.Printf("最后写入时间: %v\n", stats.LastWriteTime.Format(time.RFC3339))
fmt.Printf("支持压缩: %v\n", caps.SupportsCompression)
fmt.Printf("支持持久化: %v\n", caps.SupportsPersistence)
fmt.Printf("支持复制: %v\n", caps.SupportsReplication)
fmt.Printf("最大并发写入: %d\n", caps.MaxConcurrentWrites)
}