我在求职面试中得到了这个:
让我们假设您完成了任务:编写一个模块,在输入中,网站访问者的无限IP地址流将是 导演。
在任何时刻模块应该能够快速回答,如何 收集了许多唯一用户(唯一性由IP指定 地址)。你会如何形容解决这个问题的方法(详见) 条件是:
a)它需要获得确切数量的唯一身份访问者
b)可接受的小误差不大于3-4%的近似值
您在这里看到了什么解决方案?我发现了几个关于流算法的白皮书,但我不知道它是否适用于这种情况:
http://www.cs.berkeley.edu/~satishr/cs270/sp11/rough-notes/Streaming.pdf http://en.wikipedia.org/wiki/Count-distinct_problem
答案 0 :(得分:1)
您找到的解决方案绝对适用
对于(a)我会有一个总计唯一IP的计数器,并且会创建一个Hash,其中密钥是IP地址,你需要存储每个IP地址si 这样,无论何时收到IP,您都会检查它是否已经存在于Hash中,如果不是,则将其存储在那里并将计数器增加一个。
另一方面,对于(b)我会在IP上使用Hashing函数来进一步压缩它们,然后将它们插入更小或更有效的Hash。这样就存在碰撞的概率,但你也获得了一些表现。
答案 1 :(得分:1)
有2 ^ 32个唯一的IPv4地址。
因此,实现一个2 ^ 32个布尔值的数组,其索引对应于IP地址。每次访问时都会:
ip_index = convert_ip_to_32bit_integer(ip)
if !seen[ip_index]:
seen[ip_index] = true
nos_unique_visitors++
这需要2 ^ 29字节的内存(即0.5Gb),假设你每个字节打包1个布尔值。
答案 2 :(得分:1)
如果您只需处理32位IPv4地址,则可以使用2 32 位(半千兆位)的位向量的简单解决方案(由@Stephen C提出) )。有了它,您可以保持唯一地址的精确计数。
但是现在,有必要考虑128位IPv6地址,这是一个太大的命名空间,无法使用位向量。但是,如果您只需要近似计数,则可以使用Bloom filter,每个条目需要k
位,以获得与预期误报数相关的一些小k
值准备接受。误报将导致唯一的IP地址不计数,因此误报的比例大致是计数的预期不准确度。
正如链接的维基百科页面所提到的,每个条目使用10位预计会将误报百分比保持在不到1%;使用8 GB内存,您可以维护一个Bloom过滤器,其中包含大约680亿个条目。
答案 3 :(得分:0)
假设没有IPV6地址,则使用4字节255.255.255.255对IPV4地址进行编码。这给了我们32位。
您可以使用具有32个级别的二叉树来存储IP地址,这将告诉您树中是否存在ip,快速轻松地插入,... 然后,查找ip的操作数量近似接近32 * 2.
您可能更喜欢使用具有8个级别的Trie树,每个级别存储4位。最大操作次数,操作次数为8 * 16。
这将比允许存储器用于完整阵列更便宜,并且Trie也可以用于IPV6而成本更低。