// 时间窗口
var fiveMinAccMap = NewAccumulatorsMap(5 * time.Minute)
var tenMinAccMap = NewAccumulatorsMap(10 * time.Minute)
var fifteenMinAccMap = NewAccumulatorsMap(15 * time.Minute)
var thirtyMinAccMap = NewAccumulatorsMap(30 * time.Minute)
var oneHourAccMap = NewAccumulatorsMap(time.Hour)
// Accumulator 结构用于存储单个键的相关信息
type Accumulator struct {
sync.Mutex // 用于同步访问累加器
window *list.List // 双向链表,用于存储时间窗口内的值
total float64 // 窗口内的总增加量
max float64 // 窗口内的最大值
min float64 // 窗口内的最小值
windowSize time.Duration // 窗口大小
}
// NewAccumulator 创建一个新的增加量累加器实例
func NewAccumulator(windowSize time.Duration) *Accumulator {
return &Accumulator{
window: list.New(),
windowSize: windowSize,
max: math.Inf(-1),
min: math.Inf(1),
}
}
// AddAcc 增加一个新的值到累加器
func (acc *Accumulator) AddAcc(value float64, timestamp time.Time) {
acc.Lock()
defer acc.Unlock()
// 创建一个新的节点存储增加值和时间戳
_ = acc.window.PushFront(struct {
Value float64
Timestamp time.Time
}{Value: value, Timestamp: timestamp})
acc.total += value
// 移除过期项(超过时间窗口的项)
now := time.Now()
for e := acc.window.Back(); e != nil; {
entry := e.Value.(struct {
Value float64
Timestamp time.Time
})
if now.Sub(entry.Timestamp) > acc.windowSize {
acc.total -= entry.Value
next := e.Prev()
acc.window.Remove(e)
e = next
} else {
break
}
}
}
// MaxAcc 增加一个新的值到累加器
func (acc *Accumulator) MaxAcc(value float64, timestamp time.Time) {
acc.Lock()
defer acc.Unlock()
// 创建一个新的节点存储增加值和时间戳
_ = acc.window.PushFront(struct {
Value float64
Timestamp time.Time
}{Value: value, Timestamp: timestamp})
if value > acc.max {
acc.max = value
}
// 移除过期项(超过时间窗口的项)
now := time.Now()
for e := acc.window.Back(); e != nil; {
oldEntry := e.Value.(struct {
Value float64
Timestamp time.Time
})
if now.Sub(oldEntry.Timestamp) > acc.windowSize {
acc.total -= oldEntry.Value
// 检查移除的项是否是当前最大值,如果是则需要重新计算最大值
if oldEntry.Value == acc.max {
acc.recalculateMaxValue()
}
next := e.Prev()
acc.window.Remove(e)
e = next
} else {
break
}
}
}
// recalculateMaxValue 重新计算当前时间窗口内的最大值
func (acc *Accumulator) recalculateMaxValue() {
// 负无穷大
var maxValue = math.Inf(-1)
for e := acc.window.Front(); e != nil; e = e.Next() {
entry := e.Value.(struct {
Value float64
Timestamp time.Time
})
if entry.Value > maxValue {
maxValue = entry.Value
}
}
acc.max = maxValue // 更新累加器中的最大值
}
// MinAcc 增加一个新的值到累加器
func (acc *Accumulator) MinAcc(value float64, timestamp time.Time) {
acc.Lock()
defer acc.Unlock()
// 创建一个新的节点存储增加值和时间戳
_ = acc.window.PushFront(struct {
Value float64
Timestamp time.Time
}{Value: value, Timestamp: timestamp})
if value < acc.min {
acc.min = value
}
// 移除过期项(超过时间窗口的项)
now := time.Now()
for e := acc.window.Back(); e != nil; {
oldEntry := e.Value.(struct {
Value float64
Timestamp time.Time
})
if now.Sub(oldEntry.Timestamp) > acc.windowSize {
acc.total -= oldEntry.Value
// 检查移除的项是否是当前最大值,如果是则需要重新计算最小值
if oldEntry.Value == acc.min {
acc.recalculateMinValue()
}
next := e.Prev()
acc.window.Remove(e)
e = next
} else {
break
}
}
}
// recalculateMaxValue 重新计算当前时间窗口内的最小值
func (acc *Accumulator) recalculateMinValue() {
// 正无穷大
var minValue = math.Inf(1)
for e := acc.window.Front(); e != nil; e = e.Next() {
entry := e.Value.(struct {
Value float64
Timestamp time.Time
})
if entry.Value < minValue {
minValue = entry.Value
}
}
acc.min = minValue // 更新累加器中的最小值
}
// GetMaxValue 获取当前时间窗口内的最大值
func (acc *Accumulator) GetMaxValue() float64 {
acc.Lock()
defer acc.Unlock()
return acc.max
}
// GetMinValue 获取当前时间窗口内的最小值
func (acc *Accumulator) GetMinValue() float64 {
acc.Lock()
defer acc.Unlock()
return acc.min
}
// GetTotalIncrease 获取当前时间窗口内的总增加量
func (acc *Accumulator) GetTotalIncrease() float64 {
acc.Lock()
defer acc.Unlock()
return acc.total
}
// AccumulatorsMap 存储不同键的累加器Map
type AccumulatorsMap struct {
sync.RWMutex
accumulators map[string]*Accumulator
windowSize time.Duration
}
// NewAccumulatorsMap 创建一个新的时间窗口实例
func NewAccumulatorsMap(windowSize time.Duration) *AccumulatorsMap {
return &AccumulatorsMap{
accumulators: make(map[string]*Accumulator),
windowSize: windowSize,
}
}
// AddAccMap 增加一个新的值到累加器
func (am *AccumulatorsMap) AddAccMap(key string, value float64) {
am.Lock()
acc, exists := am.accumulators[key]
if !exists {
acc = NewAccumulator(am.windowSize)
am.accumulators[key] = acc
}
am.Unlock()
acc.AddAcc(value, time.Now())
}
// MaxAccMap 增加一个新的值到累加器
func (am *AccumulatorsMap) MaxAccMap(key string, value float64) {
am.Lock()
acc, exists := am.accumulators[key]
if !exists {
acc = NewAccumulator(am.windowSize)
am.accumulators[key] = acc
}
am.Unlock()
acc.MaxAcc(value, time.Now())
}
// MinAccMap 增加一个新的值到累加器
func (am *AccumulatorsMap) MinAccMap(key string, value float64) {
am.Lock()
acc, exists := am.accumulators[key]
if !exists {
acc = NewAccumulator(am.windowSize)
am.accumulators[key] = acc
}
am.Unlock()
acc.MinAcc(value, time.Now())
}
// GetTotalIncrease 获取key的当前时间窗口内的总增加量
func (am *AccumulatorsMap) GetTotalIncrease(key string) float64 {
am.RLock()
acc, exists := am.accumulators[key]
am.RUnlock()
if exists {
return acc.GetTotalIncrease()
}
return 0
}
// GetMax 获取key的当前时间窗口内的最大值
func (am *AccumulatorsMap) GetMax(key string) float64 {
am.RLock()
acc, exists := am.accumulators[key]
am.RUnlock()
if exists {
return acc.GetMaxValue()
}
return 0
}
// GetMin 获取key的当前时间窗口内的最小值
func (am *AccumulatorsMap) GetMin(key string) float64 {
am.RLock()
acc, exists := am.accumulators[key]
am.RUnlock()
if exists {
return acc.GetMinValue()
}
return 0
}
未经允许 禁止转载