设计一个支持海量数据存储和查询的系统

时间:2011-09-15 03:01:13

标签: c algorithm data-structures

面试官要求我设计一个存储千兆字节数据的系统,系统也必须支持某种查询。

说明

在IDC中生成大量记录,每条记录由URL,访问URL的IP以及访问发生的时间组成。该记录可能被声明为这样的结构,但我不确定应该选择哪种数据类型来代表它们:

struct Record {
    url;  //char *
    IP;   //int?
    visit_time;   //time_t or simply a number?
}

要求:

设计一个存储1000亿条记录的系统,系统至少支持2种查询:

  

首先,给定时间段(t1,t2)和IP,查询此IP在给定时间段内访问了多少URL。

     

其次,给定一个时间段(t1,t2)和一个网址,查询该网址被访问过的次数。

我被绊倒了,这是我的愚蠢解决方案:

分析:

因为每个查询都是在给定的时间段 执行 ,所以:

1. 创建一个,将所有访问时间放入集合中,并根据从旧到最新的时间值保持集合的顺序。

2.使用hash(visit_time)作为密钥创建哈希表 ,此哈希表称为time-hash-table,然后是特定桶中的每个节点 有两个指针分别指向另外两个哈希表。

3. 另外2个哈希表将是 ip-hash-table url-hash-table

  

ip-hash-table使用hash(ip)作为密钥,同一ip-hash-table中的所有ips具有相同的访问时间;

     

url-hash-table使用hash(url)作为密钥,同一url-hash-table中的所有url都具有相同的访问时间。

如下图所示:

time_hastbl
  []
  []
  []-->[visit_time_i]-->[visit_time_j]...[visit_time_p]-->NIL
  []                     |          |
  []               ip_hastbl       url_hastbl
                      []               []
                      :                :
                      []               []
                      []               []

因此,在(t1,t2)上进行查询时:

  1. 从时间设置中找到最接近的匹配,假设匹配为(t1',t2'),则所有有效访问时间将落入从t1'到t2'开始的集合部分; < / p>

  2. 对于时间集[t1':t2']中的每个访问时间t,执行hash(t)并找到t的ip_hastbl或url_hastbl,然后计算并记录给定ip或url出现的次数。

  3. 问题:

    1.我的解决方案很愚蠢,希望你能给我另一个解决方案。

    2.关于如何将大量记录存储在磁盘上,有什么建议吗?我想到了B树,但是如何使用它或者B-tree适用于这个系统?

4 个答案:

答案 0 :(得分:11)

我相信面试官期待基于分布式计算的解决方案,特别是涉及“1000亿条记录”时。由于我对分布式计算的了解有限,我建议您研究Distributed Hash Tablemap-reduce(并行查询处理)

答案 1 :(得分:2)

在我看来,创建一个B +树,使用时间作为关键,帮助您在磁盘的给定时间段(t1,t2)内快速找到记录范围。然后使用(t1,t2)期间的记录分别构建IP和URL哈希表。

答案 2 :(得分:2)

老问题,但最近碰到了所以这里有一些其他的事情要考虑:

您需要考虑的是除了列出的要求之外的一些非常简单的边界限制,假设您没有其他索引:

  

首先,给定时间段(t1,t2)和IP,查询此IP在给定时间段内访问了多少URL。

如果您有10k用户,那么在最坏的情况下,您可以预期在时间窗口中扫描所有记录将导致仅需要返回(平均)访问的10k记录。

  

其次,给定一个时间段(t1,t2)和一个网址,查询该网址被访问过的次数。

根据您在系统中有多少网址说1000,这再次意味着简单的扫描会导致扫描的1000条记录中有999条未被返回。

假设您只有100,000个唯一的URL,您可以大大减少数据库占用的空间(通过使用guid / int外键),这也意味着在100Bn记录上访问平均URL的次数为1M次。 / p>

即使有这一切,它也完全没有告诉我们,因为我们没有关于记录在给定搜索时间内如何按时间聚集的数字/统计数据。我们每秒收到1000页请求并搜索12个月的时间范围,或者我们每秒收到100个请求并搜索1小时的时间段(360k请求)。

假设100Bn代表12个月的数据,即每秒3170个请求。这听起来合理吗?

为什么这很重要?因为它突出了你在答案中忽略的一个关键因素。

在过去12个月中有100Bn记录,这意味着在12个月内您将有200Bn记录要处理。如果1000亿条记录是20年,那么这不是一个问题,未来5年你可能会再增加25-30亿条记录......但你现有的数据不太可能在这么长的时间内完成。

您的解决方案只回答方程式的一侧(读取数据),您不会考虑编写那么多数据的任何复杂性。绝大多数情况下,您将数据插入到您创建的任何数据存储中,它是否能够每秒处理恒定的3k插入请求?

如果插入3k记录,并且每条记录只是3x 64位整数,表示时间(以刻度表示),IP地址和URL的外键。那么只有~75kb / s的写入数据,维护得很好。如果假设每个URL都是唯一的,那么由于IO速度(忽略空间要求),您很容易遇到性能问题。

面试官有兴趣看到的另一件事是你对支持IPv6的想法。

最后,如果您提供了类似于您的解决方案,那么面试官应该问一个后续问题。 “如果我现在想知道特定IP地址上次访问特定网址的时间,您的系统将如何执行?”

是的,如果您不了解MapReduce和其他分布式处理查询系统,那么您的查询系统应该是合理的答案。

答案 3 :(得分:0)

它将是一个间隔树,它也是一个B树。间隔树,因为所有查询仅以时间间隔输入,而B-Tree由于输入的大小(数十亿)。