用于跟踪过去X小时数据的数据结构

时间:2014-03-27 20:09:24

标签: performance algorithm caching

我正在实时获取用户事件日志流(大约每秒100个日志,用户基础10M +)。每个日志都有一个时间戳和一个用户名。对于每个用户名,我想跟踪过去X小时的事件数。这样做有效的数据结构是什么?它怎么可以存储?

我正在考虑移动平均算法,但不确定如何将窗口限制为X小时?

任何帮助表示感谢。

修改

所以我真正需要的是各种缓存,它可以让我在指定的时间段内查找每个用户的事件数。不知道我能负担得起多么昂贵的计算。

目的是异常检测,并查找每个传入日志消息/用户名的编号,然后检查该用户是否低于/高于某个阈值。

实施

基于@ Dgrin91的建议解决方案,这是Java中的一个有效实现。尽管它对我的用例非常具体,但也许其他人可能会发现它很有用。

https://gist.github.com/anonymous/9931570

1 个答案:

答案 0 :(得分:1)

如果您不介意自己构建它,这是我想到的快速解决方案 -

维护两个数组,数组的每个元素都代表一个时间单位(比如1分钟)。每个数组的大小为X(您要存储的时间长度)。来自某一分钟的所有消息都会进入相应的元素(根据您喜欢的数据结构)。首先填充一个数组。每分钟你切换到下一个元素。当你点击第一个数组的末尾时,你移动到第二个数组。但是,您现在开始删除第一个数组前面的元素(为下一个循环做准备)。当您到达第二个数组的末尾时,您的第一个数组将清除并准备好发送消息。这个循环可以永远持续下去。

就效率而言,这似乎非常好。它基本上只是一个数组查找,它是O(1)。空间效率也很小。你实际上并没有存储2个完整的数组,"垃圾收集器"你实施的任何时候都将它保持在1。

样机代码 -

Array Arr1 = new Array(X);
Array Arr2 = new Array(X);
Time startTime = CurrentTime();
int count = 0;
Set users = new Set();

void OnMessageRecieved(Message message){
    Users.get(message.user).insert(message);
}

void insert(Message m){
    Time currentTime = CurrentTime();
    int iter = currentTime-startTime;
    if(iter>2*X){
        startTime=CurrentTime;
        iter=0;
    }
    if(iter>X){
        iter-=X;
        arr2[iter]+=message;
    }
    else{
        arr1[iter]+=message;
    }
    count++;
}

然后为旧日志提供单独的清理线程。该线程的核心代码将类似于 -

void run(){
    while(true){
        Time currentTime = CurrentTime();
        int size = currentArray[currentTime-x].size;
        currentArray[currentTime-x].reset();
        count-=size;
        sleep(60);
    }
}
相关问题