题目

你有10亿个url,每个url对应一个非常大的网页。你怎么检测重复的网页?

解答

  1. 网页大,数量多,要把它们载入内存是不现实的。 因此我们需要一个更简短的方式来表示这些网页。而hash表正是干这事的。 我们将网页内容做哈希,而不是url,这里不同url可能对应相同的网页内容。
  2. 将每个网页转换为一个哈希值后,我们就得到了10亿个哈希值, 很明显,两两对比也是非常耗时的O(n2 )。因此我们需要使用其它高效的方法。

根据以上分析,我们可以推出满足条件的以下算法:

  1. 遍历网页,并计算每个网页的哈希值。
  2. 检查哈希值是否已经在哈希表中,如果是,说明其网页内容是重复的,输出其url。 否则保存url,并将哈希值插入哈希表。

通过这种方法我们可以得到一组url,其对应的网页内容都是唯一的。但有一个问题, 一台计算机可以完成以上任务吗?

  1. 一个网页我们要花费多少存储空间?

    • 每个网页转换成一个4字节的哈希值
    • 假设一个url平均是30个字符,那我们至少需要30个字节
    • 因此对应一个url,我们一共要用掉34个字节
  2. 34字节 * 10亿 = 31.6GB。很明显,单机的内存是无法搞定的。

我们要如何解决这个问题?

  1. 我们可以将这些数据分成多个文件放在磁盘中,分次载入内存处理。 这样一来我们要解决的就是文件的载入/载出问题。
  2. 我们可以通过哈希的方式将数据保存在不同文件,这样一来,大小就不是问题了, 但存取时间就成了问题。硬盘上的哈希表随机读写要耗费较多的时间, 主要花费在寻道及旋转延迟上。关于这个问题, 可以使用电梯调度算法来消除磁头在磁道间的随机移动,以此减少消耗的时间。
  3. 我们可以使用多台机器来处理这些数据。这样一来,我们要面对的就是网络延迟。 假如我们有n台机器。
    • 首先,我们对网页做哈希,得到一个哈希值v
    • v%n 决定这个网页的哈希值会存放在哪台机器
    • v/n 决定这个哈希值存放在该机器上哈希表的位置

给定100亿个网址,如何检测出重复的文件?这里所谓的“重复”是指两个URL完全相同。

解法:

100亿个网址(URL)要占用多少空间呢?如果每个网址评价长度为100个字符,每个字符占4字节,则这份100亿个网址的列表要占用约4TB。在内存中可能放不下这么多的数据。

不过,不妨假设一下,这些数据奇迹般的放进了内存,毕竟先求解简化的题目是很有用的做法。对于此题的简化版,只要创建一个散列表,若在网址列表中找到某个URL,就映射为true。(另一种做法是对列表进行排序,找出重复项,这需要额外耗费一些时间,但几乎无优点可言)

至此,我们得到此题简化版的解法,那么,假设我们手上有4000GB的数据,而且无法全部放进内存,该怎么办?到也好办,我们可以将部分数据存储至磁盘,或者将数据分拆到多台机器上。

解法1:存储至磁盘

若将所有数据存储在一台机器上,可以对数据进行两次扫描。第一次扫描是将网址列表拆分为4000组,每组1GB。

简单的做法是将每个网址u存放在名为<x>.txt的文件中,其中x=hash(u)%4000。也就是说,我们会根据网址的散列值(除以分组数量取余数)分割这些网址。这样一来,所有散列值相同的网址都会位于同一文件。

第二次扫描,我们其实是在实现前面简化版问题的解法:将每个文件载入内存,创建网址的散列表,找出重复的。

解法2:多台机器

另一种解法的基本流程是一样的,只不过是要是有多台机器。在这种解法中,我们会将网址发送到机器x上,而不是存储至文件<x>.txt。使用多台机器有优点也有缺点。

主要优点是可以并行执行这些操作,同时处理4000个分组。对于海量数据,这么做就能迅速有效地解决问题。缺点是现在必须依靠4000台不同的机器,同时要做到操作无误。这可能不太现实(特别是对于数据量更大、机器更多的情况),我们需要开始考虑如何处理机器故障。此外,设计那么多机器,无疑大幅增加了系统的复杂性。

careercup-扩展性和存储限制10.6的更多相关文章

  1. careercup-扩展性和存储限制10.4

    题目 有一个数组,里面的数在1到N之间,N最大为32000.数组中可能有重复的元素(即有的元素 存在2份),你并不知道N是多少.给你4KB的内存,你怎么把数组中重复的元素打印出来. 解答 我们有4KB ...

  2. careercup-扩展性和存储限制10.3

    题目 给你一个文件,里面包含40亿个整数,写一个算法找出该文件中不包含的一个整数, 假设你有1GB内存可用. 如果你只有10MB的内存呢? 解答 我们先来做个算术题,40亿个整数大概有多大? * ^ ...

  3. OpenStack 企业私有云的若干需求(6):大规模扩展性支持

    本系列会介绍OpenStack 企业私有云的几个需求: 自动扩展(Auto-scaling)支持 多租户和租户隔离 (multi-tenancy and tenancy isolation) 混合云( ...

  4. 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  5. MySQL - 扩展性 3 负载均衡:眼花缭乱迷人眼

    负载均衡的基本思路很简单: 在一个服务器集群中尽可能地的平均负载量. 基于这个思路,我们通常的做法是在服务器前端设置一个负载均衡器.负载均衡器的作用是将请求的连接路由到最空闲的可用服务器上.如图 1, ...

  6. Atitit.软件架构高扩展性and兼容性原理与概论实践attilax总结

    Atitit.软件架构高扩展性and兼容性原理与概论实践attilax总结 1. 什么是可扩展的应用程序?1 2. 松耦合(ioc)2 3. 接口的思考 2 4. 单一用途&模块化,小粒度化2 ...

  7. jetbrick,新一代 Java 模板引擎,具有高性能和高扩展性

    新一代 Java 模板引擎,具有高性能和高扩展性. <!-- Jetbrick Template Engineer --> <dependency> <groupId&g ...

  8. Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文主要介绍一个支持图片自动预取.支持多种缓存算法的图片缓存的使用及功能.图片较大需要SD卡保存情况推荐使用ImageSDCardCache. 与Android LruCache相比主要特性:(1). ...

  9. Java并发编程:性能、扩展性和响应

    1.介绍 本文讨论的重点在于多线程应用程序的性能问题.我们会先给性能和扩展性下一个定义,然后再仔细学习一下Amdahl法则.下面的内容我们会考察一下如何用不同的技术方法来减少锁竞争,以及如何用代码来实 ...

随机推荐

  1. https、公钥、私钥白话解说

    原文 摘要:本文尝试一步步还原HTTPS的设计过程,以理解为什么HTTPS最终会是这副模样.但是这并不代表HTTPS的真实设计过程.在阅读本文时,你可以尝试放下已有的对HTTPS的理解,这样更利于“还 ...

  2. 模块与包&常用模块

    一.模块的使用 模块定义:一系列功能的集合体 分为三大类:1.自定义模块 2.内置模块(比如 time,os,sys) 3.第三方模块 模块的表现形式: 1.使用python编写的py文件 2.已被编 ...

  3. 10分钟学会Less开发环境搭建与初体验

    Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合(mixin).函数等功能,让 CSS 更易维护.方便制作主题.扩充. 今天看一下,10分钟能不能手把手快速教会你Le ...

  4. Java基础重点知识之欣欣向然

    题目: 第一题:二重循环: public class Text01 { //完成歌曲排序的效果 public static void main(String[] args) { String[] zi ...

  5. Web.py报错:OSError: No socket could be created -- (('0.0.0.0', 8080):

    web.py报错 Python代码: import web urls = ( '/(.*)', 'hello' ) app = web.application(urls, globals()) cla ...

  6. 完整SQL分页存储过程(支持多表联接)

    http://www.cnblogs.com/andiki/archive/2009/03/24/1420289.html Code/********************************* ...

  7. 佛系结对编程---四则运算(Core 第四组)

    ----by core 第四组 ( 邹卫其 范力 ) 一. 项目介绍 1. 能自动生成小学四则运算题目并给出答案,生成题目时可以选择下列参数:   1)生成题目数量   2)每道题目中运算数数量   ...

  8. 线程间协作:wait、notify、notifyAll

    线程间协作:wait.notify.notifyAll 在 Java 中,可以通过配合调用 Object 对象的 wait() 方法和 notify()方法或 notifyAll() 方法来实现线程间 ...

  9. C++11标准之右值引用(rvalue reference)

    1.右值引用引入的背景 临时对象的产生和拷贝所带来的效率折损,一直是C++所为人诟病的问题.但是C++标准允许编译器对于临时对象的产生具有完全的自由度,从而发展出了Copy Elision.RVO(包 ...

  10. [使用经验]cocostudio UI编辑器的裁剪

    日志-2015/03/16 描述:在程序使用UI编辑器导出文件的时候,该panel中大于panel的部分都没有显示出来,例如人物,一些特效等 原因:UI编辑器panel都勾上了裁剪 解决:在编辑器中把 ...