背景:
原始数据是上线一条数据纪录,下线一条数据数据纪录。并且数据量巨大,每秒产生20K~50K条数据。
数据纪录格式为文本,大概是这样:        IP地址,端口号,时间,上线/下线现在需要当收到下线数据纪录时,找到之前的上线数据纪录。同时计算出该用户上网的时长。上网时间=下线时间-上线时间。
需要注意的问题:
1、上网时间可能会超过一周,因此前面上线纪录的数据需要保存较长时间,假设最长一周。
2、如何高效迅速的查到的对应的上线数据纪录,而不至于整个处理程序被堵塞。
3、按照IP地址、端口号来标识唯一一次用户上线行为,用户记录数最大可能会达到20M条纪录。假设可以全部放入内存中。
4、收到用户下线纪录后,完成上线时长的计算后,应该将内存中的相应上线纪录数据删除。删除也会有性能开销。请各位大牛给一些思路和方案,感觉应该有对应这个问题的数据结构和算法。谢谢!!!最多只能一次给100分,如果问题解决,可以另外开帖子散分。高性能计算算法内存

解决方案 »

  1.   

    这么大的数据量,你要放在内存里面的话,检索起来会很麻烦的,倒不如采用数据库来做。如果硬要自己实现的话,算法肯定很复杂,否则你的性能根本支持不了,可以考虑btree结构存储索引试试。不过因为你数据量太大了,放在内存中很难说,不过如果可以分布式倒是没有问题。
      

  2.   

    内存里只需要有每个用户最后一次上线的数据就可以了吧,每次有下线事件,则输出并消除这个上线数据
    这样在内存中储存时只需要一个map,key是用户id可以为 ip:port,数据为上线时间对于那个文件,可以用个watcher只观察modify这个事件,每此收到此事件获得新的文件大小,对比上次事件的大小只处理这两个事件变化的部分
      

  3.   

    大致同意。
    此外删除上线数据并不需要实时,开一个线程定时遍历并删除那些过期的map entry,好处是某些用户可能重复登陆,重复使用可减少GC。
    关于文件其实不需要watcher,既然数据量很大,那么就可以假设文件每时都在变化,一个定时检查器就足够了。整个程序的驱动器就像这里所说的LogView http://sunnylocus.iteye.com/blog/694666
      

  4.   

    缓存加数据库,以IP+端口号为id
    1. 数据库2个表,一个存储当前在线状态,一个存储历史上线与离线状态。
    2. 缓存例如1000个用户状态,缓存满了就写入数据库,这样用于减轻数据库访问压力。缓存有许多优秀的框架,直接用。
      

  5.   

    可以全部放内存? 就是说你内存够大? 
    那就都放HASHMAP好了 一开始初始化的时候开大点,以避免扩容带来的性能损耗。
      

  6.   

    这好比一个大session的功能,超时时间为1周,IP+端口号为唯一session好,上线的时候就相当于创建,下线注销,不过你的用户记录数最大可能会达到20M条,这倒是挺大的,具体多大我也没有什么概念,估计得50W条!
    当用户下线的时候,组织session(IP+端口号) 新开线程去查询和得到上线时间并把该用户的上线记录删除?这所有的逻辑都在一起了,处理起来估计效率有点慢吖!或者直接把数据丢给其他程序处理,主程序只做数据转发,开多个客户端处理,主程序和客户端程序用socket通讯?