210 lines
4.7 KiB
Go
210 lines
4.7 KiB
Go
package engine
|
||
|
||
import (
|
||
"context"
|
||
"sort"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// Engine 定义存储引擎的通用接口
|
||
type Engine interface {
|
||
// 生命周期管理
|
||
Open() error
|
||
Close() error
|
||
|
||
// 数据操作
|
||
Write(ctx context.Context, points []DataPoint) error
|
||
Query(ctx context.Context, query Query) (QueryResult, error)
|
||
|
||
// 管理功能
|
||
Compact() error
|
||
Cleanup() error
|
||
|
||
// 监控和统计
|
||
Stats() EngineStats
|
||
}
|
||
|
||
// DataPoint 表示一个时序数据点
|
||
type DataPoint struct {
|
||
Timestamp int64
|
||
Value float64
|
||
Labels map[string]string
|
||
Metadata map[string]interface{} // 可选的元数据
|
||
}
|
||
|
||
// GetSeriesID 从标签生成序列ID
|
||
func (p DataPoint) GetSeriesID() string {
|
||
// 如果没有标签,返回默认ID
|
||
if len(p.Labels) == 0 {
|
||
return "default_series"
|
||
}
|
||
|
||
// 获取所有标签的键,并排序
|
||
keys := make([]string, 0, len(p.Labels))
|
||
for k := range p.Labels {
|
||
keys = append(keys, k)
|
||
}
|
||
|
||
// 按字典序排序键
|
||
sort.Strings(keys)
|
||
|
||
// 构建序列ID
|
||
var sb strings.Builder
|
||
for i, k := range keys {
|
||
if i > 0 {
|
||
sb.WriteString(",")
|
||
}
|
||
sb.WriteString(k)
|
||
sb.WriteString("=")
|
||
sb.WriteString(p.Labels[k])
|
||
}
|
||
|
||
return sb.String()
|
||
}
|
||
|
||
// QueryType 定义查询类型
|
||
type QueryType string
|
||
|
||
const (
|
||
QueryTypeRaw QueryType = "raw" // 原始数据查询
|
||
QueryTypeLatest QueryType = "latest" // 最新值查询
|
||
QueryTypeAggregate QueryType = "aggregate" // 聚合查询
|
||
QueryTypeValueDuration QueryType = "value_duration" // 值持续时间查询
|
||
)
|
||
|
||
// AggregateType 定义聚合类型
|
||
type AggregateType string
|
||
|
||
const (
|
||
AggregateTypeAvg AggregateType = "avg"
|
||
AggregateTypeSum AggregateType = "sum"
|
||
AggregateTypeMin AggregateType = "min"
|
||
AggregateTypeMax AggregateType = "max"
|
||
AggregateTypeCount AggregateType = "count"
|
||
)
|
||
|
||
// Query 表示查询请求
|
||
type Query struct {
|
||
Type QueryType
|
||
StartTime int64
|
||
EndTime int64
|
||
Tags map[string]string
|
||
Limit int
|
||
AggregateType AggregateType // 用于聚合查询
|
||
}
|
||
|
||
// QueryResult 表示查询结果
|
||
type QueryResult []SeriesResult
|
||
|
||
// SeriesResult 表示单个序列的查询结果
|
||
type SeriesResult struct {
|
||
SeriesID string
|
||
Points []DataPoint
|
||
}
|
||
|
||
// EngineStats 存储引擎统计信息
|
||
type EngineStats struct {
|
||
// 基本统计
|
||
PointsCount int64 // 数据点总数
|
||
SeriesCount int64 // 序列总数
|
||
LastWriteTime time.Time // 最后写入时间
|
||
|
||
// 性能指标
|
||
WriteLatency time.Duration // 平均写入延迟
|
||
QueryLatency time.Duration // 平均查询延迟
|
||
|
||
// 资源使用
|
||
MemoryUsage int64 // 内存使用量(字节)
|
||
DiskUsage int64 // 磁盘使用量(字节)
|
||
|
||
// 引擎特定指标
|
||
CompactionCount int64 // 压缩次数
|
||
LastCompaction time.Time // 最后压缩时间
|
||
WriteErrors int64 // 写入错误次数
|
||
QueryErrors int64 // 查询错误次数
|
||
}
|
||
|
||
// WriteBufferHandler 定义写入缓冲区处理器接口
|
||
type WriteBufferHandler interface {
|
||
WriteToBuffer(point DataPoint) error
|
||
FlushBuffer() error
|
||
ValidatePoint(point DataPoint) error // 新增方法,只检查不写入
|
||
}
|
||
|
||
// WriteBuffer 实现写入缓冲区
|
||
type WriteBuffer struct {
|
||
handler WriteBufferHandler
|
||
buffer []DataPoint
|
||
size int
|
||
}
|
||
|
||
// NewWriteBuffer 创建新的写入缓冲区
|
||
func NewWriteBuffer(handler WriteBufferHandler, size int) *WriteBuffer {
|
||
bufferCap := size
|
||
if bufferCap < 0 {
|
||
bufferCap = 0
|
||
}
|
||
return &WriteBuffer{
|
||
handler: handler,
|
||
buffer: make([]DataPoint, 0, bufferCap),
|
||
size: size,
|
||
}
|
||
}
|
||
|
||
// Write 写入数据点到缓冲区
|
||
func (b *WriteBuffer) Write(point DataPoint) error {
|
||
// 如果缓冲区大小为0,直接写入并返回
|
||
if b.size <= 0 {
|
||
if err := b.handler.WriteToBuffer(point); err != nil {
|
||
return err
|
||
}
|
||
return b.handler.FlushBuffer()
|
||
}
|
||
// 先验证数据点是否可写入(不实际写入)
|
||
if err := b.handler.ValidatePoint(point); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 如果缓冲区已满,先刷新
|
||
if len(b.buffer) >= b.size {
|
||
if err := b.Flush(); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 添加到缓冲区
|
||
b.buffer = append(b.buffer, point)
|
||
|
||
// 如果缓冲区已满,立即刷新
|
||
if len(b.buffer) >= b.size {
|
||
return b.Flush()
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// Flush 刷新缓冲区
|
||
func (b *WriteBuffer) Flush() error {
|
||
if len(b.buffer) == 0 {
|
||
return nil
|
||
}
|
||
|
||
// 批量写入
|
||
for _, point := range b.buffer {
|
||
if err := b.handler.WriteToBuffer(point); err != nil {
|
||
// 即使出错也清空缓冲区,避免重复处理错误数据
|
||
b.buffer = b.buffer[:0]
|
||
// 尝试调用刷新方法,但优先返回写入错误
|
||
_ = b.handler.FlushBuffer()
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 清空缓冲区
|
||
b.buffer = b.buffer[:0]
|
||
|
||
// 调用处理器的刷新方法
|
||
return b.handler.FlushBuffer()
|
||
}
|