计算IP范围和时间范围内访问次数的有效方法

时间:2011-09-21 14:36:47

标签: c performance web-services algorithm

假设有一个流行的网络服务器,这个网络服务器的访问次数可以在一小时内成千上万,为了分析这些访问的统计属性,我们想知道特定的请求数量时间范围和IP范围。

例如,我们有以下格式的10个 12 请求:

(IP地址,访问时间)

假设我们想知道在下午2点和下午4点从IP范围[10.12.72.0,10.12.72.255]访问了多少次。

我能想到的唯一候选人是:

(1)使用B-TREE使用一维索引这个大数据集,例如在参数IP上构建B-TREE。使用这个B-TREE,我们可以快速获得来自任何特定IP范围的请求数量,但我们怎么能知道这些访问中有多少是在下午2点到下午4点之间?

(2)使用BITMAP,但与B-TREE类似,由于空间要求,BITMAP只能在一个维度上构建,例如IP地址,我们不知道在2p之间发出了多少这些请求。下午4点和下午4点。

有没有高效的算法,thx?查询数量可能非常大

3 个答案:

答案 0 :(得分:2)

您需要一个支持orthogonal range counting的数据结构。

答案 1 :(得分:2)

你的第一步是弄清楚你需要的精确度......

时间:

  • 你需要,毫秒,时间戳,或者,到时,是否足够好?
    • 自1970年以来的小时数可以容纳百万,3字节〜整数
    • 毫秒数,您需要8个字节〜长

IP:

  • 你的所有IP都是v4(4字节)还是v6(16字节)?
  • 您是否会按特定IP进行搜索,还是仅使用IP范围?
    • 如果是后者你可以为每个IP 123.123.123.X使用C类(3个字节)

假设:

  • 1小时时间精度足够
  • 3字节IP类C足够好

重新组织您的数据(2种可能的结构选择一种):

数据库:

  • 您可以使用关系数据库
    • 表:点击
      • IPClassC INT非集群索引
      • TimeHrsUnix INT NON-CLUSTERED INDEX
      • 计算BIGINT DEFAULT VALUE(1)

平面文件:

  • 您可以使用更多平面文件
    • 为日志中显示的每个C类IP(最多2 ^ 24)
    • 设置1个平面文件
      • 每个文件是8B(大int)* 1MB(1970年至2070年之间的小时)= 8MB大小

如何加载新数据结构:

数据库:

  • 解析您的日志(一次在内存中读取一行)
  • 将记录转换为3字节IP和3字节时间
  • 将您的IP类C转换为整数,将您的时间转换为整数
  • IF EXISTS(SELECT * FROM Hits,其中IPClassC = @IP和TimeHrsUnix = @Time)
    • UPDATE Hits SET Count = Count + 1 WHERE IPClassC = @IP AND TimeHrsUnix = @Time
  • 否则
    • INSERT INTO HIT VALUES(@ IP,@ Time)

平面文件:

  • 解析您的日志(一次在内存中读取一行)
  • 将记录转换为3字节IP和3字节时间
  • 将您的IP转换为字符串,将您的时间转换为整数
  • 如果File.Exist(IP)= False
    • File.Create(IP)
    • File.SetSize(IP,8 * 1000000)
  • CountBytes = File.Read(IP,8 * Time,8)
  • NewCount = Convert.ToLong(CountBytes)+ 1
  • CountBytes = Convert.ToBytes(NewCount)
  • File.Write(IP,CountBytes,8 * Time,8)

查询新数据结构:

数据库:

  • SELECT SUM(Count)FROM点击哪里IPClassC BETWEEN @IPFrom和@IPTo和TimeHrsUnix BETWEEN @TimeFrom AND @TimeTo

平面文件:

  • 总计= 0
  • 偏移= 8 * TimeFrom
  • Len =(8 * TimeTo) - 偏移
  • 对于IP = IPFrom To IPTo
    • 如果是File.Exist(IP.ToString())
      • CountBytes = File.Read(IP.ToString(),Offset,Len)
      • LongArray = Convert.ToLongArray(CountBytes)
      • 总计=总计+ Math.Sum(LongArray)
  • 下一个IP

一些额外提示:

  • 如果你去数据库路线,你可能需要为数据库文件使用多个分区
  • 如果您使用平面文件路径,您可能希望将查询分解为线程(假设您的SAS将处理带宽)。每个线程将处理该范围内的IP /文件的子集。一旦所有线程完成,每个线程的总数将相加。

答案 2 :(得分:0)

10 ^ 12是一个大数字(TERA) - 对于内存处理来说肯定太大了。 我会将其存储在具有星型模式的关系数据库中,使用时间维度,并按时间(例如小时波段),IP子网和您感兴趣的其他条件进行预聚合。