面试官要求我设计一个存储千兆字节数据的系统,系统也必须支持某种查询。
说明
在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)上进行查询时:
从时间设置中找到最接近的匹配,假设匹配为(t1',t2'),则所有有效访问时间将落入从t1'到t2'开始的集合部分; < / p>
对于时间集[t1':t2']中的每个访问时间t,执行hash(t)并找到t的ip_hastbl或url_hastbl,然后计算并记录给定ip或url出现的次数。
问题:
1.我的解决方案很愚蠢,希望你能给我另一个解决方案。
2.关于如何将大量记录存储在磁盘上,有什么建议吗?我想到了B树,但是如何使用它或者B-tree适用于这个系统?
答案 0 :(得分:11)
我相信面试官期待基于分布式计算的解决方案,特别是涉及“1000亿条记录”时。由于我对分布式计算的了解有限,我建议您研究Distributed Hash Table和map-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由于输入的大小(数十亿)。