我有一个调度成功和失败事件的类,我需要维护一个关于该类最后X秒内的平均失败次数/事件总数的统计数据.
我正在考虑使用循环链表并为每个事件附加成功或失败节点.然后计算列表中的故障节点数与总节点数,但这有两个主要缺点:
我需要不断扩大/缩小列表大小以考虑"最后X秒"要求(每秒事件数可以更改)
我需要不断循环遍历列表并计算所有事件(可能很昂贵,因为我每秒可能会有100个这样的事件)
有没有人知道从最近X秒收到的样本列表中计算平均值的另一种方法?
您应该使用采样频率(a-la MRTG).假设您只需要一秒精度并保持过去一分钟的平均值,您将拥有一个固定的表,其中包含过去60秒(包括当前的60秒)的60个条目.并且还保持目前的全球进入.
每个条目包含一个平均值和一些事件.两个值的每个条目从0开始.
当您收到新事件时,您可以更改当前和全局条目:
average = ((number * average) + 1) / (number + 1) number = number + 1
在每个采样间隔,您使用最旧的条目更改全局条目:
global.average = ((global.number * global.average) - (oldest.number * oldest.average)) / (global.number - oldest.number) global.number = global.number - oldest.number
然后将最旧的条目重置为0并开始将其用作当前条目.
您可以使用队列,这将允许您将新事件添加到队列的末尾,并从队列的开头删除过期事件,假设事件按时间顺序添加.例如,在Java中,您可以使用a LinkedList
或者ArrayDeque
两者来实现Queue
接口.
如果未按时间顺序添加事件,则可以使用优先级队列.元素将按其时间戳排序,并且最高优先级元素(即删除的下一个元素)将是具有最小时间戳的元素.在Java中,此数据结构由提供PriorityQueue
.
我们可以保留两个计数器,一个用于事件总数,另一个用于成功事件的数量,而不是定期计算事件.每当我们从队列中添加或删除事件时,这些计数器都会更新.