三个题目

第一题

问题描述

统计出当前这个一行一个IP的文件中,到底哪个IP出现的次数最多

解决思路

//必须要能读取这个内容  

        BufferedReader br = new BuffedReader(new FileInputStream(new File("c:/big.txt")));
// 每次读取一行
String line = null;
while( (line=br.readLine()) != null){
// 处理这读取到的一行内容的代码
} //最简单的一种思路: 初始化一个hashmap //hashmap中存储的键值对的 key : IP value : 次数 int count = 0; // 就是用来进行存储当前出现次数最多的那个IP的次数
String maxip = null;
Set<String> ips = hashmap.keySet();
for(String ip : ips){
int ipcount = hashmap.get(ip)
if(ipcount > count){
count = ipcount
maxip = ip;
}
}
System.out.println(maxip + " : " +count);

问题难点

1、当读取的文件的大小超过内存的大小时,以上的解决方案是不可行的。

2、假如说你的内存足够大,能装下这个文件中的所有ip,整个任务的执行效率会非常低,消耗的时间会非常的长。

  1GB -- 5分

  1TB --- 1024 * 5 分

3、最终整个任务就使用一台机器,那么最终整个任务执行完成所消耗的时间是和数据的大小成正比。提升服务器的执行性能来提高数据的处理速度。

    当前这一台机器的执行性能:          5分钟/GB

    提升服务器的执行性能: CPU :i3 ---> i7 1分钟/GB

在最开始的服务器领域:提升服务器对外提供服务的效率手段就是纵向提升服务器性能。理想是丰满的,现实是骨感的,但是服务器性能提升有瓶颈。

摩尔定律:每隔18-24个月,服务器的性能提升一倍。

如果说数据的增长是每隔18-24个月就增长一倍,工作量增加了一倍。工作效率也增加了一倍,那么最终完成同一个任务所花费的时间是一样的。

但是数据的增长速度是远远超过服务器性能的提升。在数据不断增长的情况下,单位时间内,服务器所需要处理的数据量是越来越大。

假如:

服务器的性能提升 速率 和 数据的增长速率一样: 在18-24个月
10GB --- 性能: 1分钟/GB --- 10分钟
20GB --- 性能: 1分钟/2GB --- 10分钟

假如:

服务器的性能提升 速率 和 数据的增长速率不一样: 在18-24个月
10GB --- 性能: 1分钟/GB --- 10分钟
100GB --- 性能: 1分钟/2GB --- 50分钟

最终的结论: 靠 纵向提升服务器性能的手段 在理论上有 瓶颈的。

最终解决方案:纵向不可取,所以采取横向扩展。

所谓的横向扩展:就是增加服务器的数量。

一个庞大的复杂任务就应该 平均分配给所有的服务器做处理

10GB 一台服务器 10分钟

100GB 一台服务器 100分钟

100GB 10台服务器 10分钟

10000GB 1000台 10分钟

在理论上 有上限么??没有

两种情况下:
1、在数据量比较小的情况下,单台服务器就可以再用户可接受的时限范围内完成任务。
2、当数据量变大时,如果用户也想在可接受的时限范围内完成任务,那么可行的方案就是进行服务器的横向扩展。

核心思想: 大事化小 分而治之
终极解决方案:
1、先把文件切碎成很多的小文件。
2、每一个服务器节点去处理一个小文件。
3、再把所有服务器的处理结果汇总到一起。
4、再把所有的数据合并到一起求出出现次数最多的那个ip。

只要是通过网络传输数据,就一定存在丢失数据的可能。

第二题

问题描述

在两个庞大文件中,文件也都是存储的URL地址(每行一个),比如文件名叫做file1和file2, 找出这两个文件中的交集(相同的URL)?

以上问题等同于SQL:select url from file1 a join file2 b on a.url = b.url

问题分析

概念:出现在在file1中的元素也出现在file2中。这些元素的集合就是交集

需求:求2个文件的交集

文件中的元素:URL

解决方案

1.当2个文件都比较小的时候

  步骤:

    1. 编写一个程序可以去读文件的内容,把文件中的所有元素都放置在一个set1中

        编写一个流处理取读取文件内容,逐行读取,每次读取到的一行放入set1中

    2. 运行相同的程序处理另外一个文件的内容,把文件中的所有元素都放置在一个set2中

    3. 先遍历一个集合,每次遍历出来的元素都去另外一个集合中判断存在不存在。如果存在,就是共同元素,这个共同元素就存储在某个集合中resultSet;如果不存在,就不是共同元素。

    4. 结果集:集合resultSet

2.当2个文件都比较大的时候

  第一种思路:采取跟第一个题目一样的大事化小的策略

  第二种思路:改良第一种思路。避免第一种思路中的很多无效匹配 a1 * a2

        必须做到合理的数据分区,数据分区的两种最基本的思路:

          1.先排序,然后分段==分区

          2.hash散列  --  求hash值,然后利用hash值求和分区个数的余数,如果余数相同,就证明这些元素在同一个分区中

        改良了实现思路之后,可以让原来应该执行16个小任务的大任务。只需要执行4个小任务即可。

终极解决方案:

1.先指定一个分区策略:hash散列

2.预估预估一下数据要被切分成多少个块,一定要保证两个文件切分出来的小文件个数成倍数

3.根据hash散列的策略,对两份文件分别进行操作

4.根据原来指定的策略,寻找对应的两个大文件中的对应小文件进行求交集操作

5.所有的结果,根本就不用再进行去重了。直接进行拼接即可。

学到的东西:

  整个大数据生态系统中的很多技术软件的底层处理数据的分区时,默认的策略都是hash散列。

第三题

问题描述

现在有一个非常庞大的URL库(10000E),然后现在还有一个URL,(迅速)判断这个URL是否在这个URL库中?

问题分析

需求:判断一个元素在不在某个集合中

解决方案

1、计数排序

1、初始化一个数组 数组的长度 就是 集合中元素的区间长度

2、遍历集合,把每个元素放入数组中 寻找对应的下标位置,找出值,然后重新设置成+1的值

3、按序遍历即可

array[0] = 1, array[1] = 2, array[2] = 0, array[3] = 3,

0 1 1 3 3 3

2、改进需求:

求出某个元素在不在这个数组(数据结构改良之前的集合)中

array[5] = count if count > 0

3、既然是判断存在不存在。

所以结果其实就是一个状态 : 要么存在 要么不存在

存在 : 1
不存在: 0

把int数组进化成 为位数组

优势:把数组所要消耗的内存降低到原来的 1/32

改良了之后这种数据结构: BitMap

真正的结构: 一个位数组 + 一个hash函数

4、BitMap再次进行进化

解决的问题: BitMap 中非常容易出现 hash碰撞的问题

咱们可以结合使用多个hash函数来搞定

缺点: 存在一定的误判率

1、如果这种数据结构(BloomFilter) 告诉你说你要验证的那个元素不在这个 BloomFilter 中
那就表示 这个元素一定不在这个 BloomFilter 中

2、如果它告诉你这个元素存在, 它告诉你的这个存在的结果 有可能是假的

真正的组成:

一个位数组 + 一组hash函数

如果要做工程实现:不管是什么变种的BloomFilter, 都一定要实现两个方法:

1、第一个方法是往BloomFilter中存入一个元素

2、第二个方法是验证一个元素是否在这个BloomFilter 中

误判率的估计:

1、位数组的长度 m

2、总元素的个数 n

3、hash函数的个数 k

hash函数的个数 并不是越多越好

在误判率最低的情况下。 这三个参数应该满足的一个公式: k = 0.7 * m / n

Hadoop学习之路(一)理论基础和逻辑思维的更多相关文章

  1. 阿里封神谈hadoop学习之路

    阿里封神谈hadoop学习之路   封神 2016-04-14 16:03:51 浏览3283 评论3 发表于: 阿里云E-MapReduce >> 开源大数据周刊 hadoop 学生 s ...

  2. 《Hadoop学习之路》学习实践

    (实践机器:blog-bench) 本文用作博文<Hadoop学习之路>实践过程中遇到的问题记录. 本文所学习的博文为博主“扎心了,老铁” 博文记录.参考链接https://www.cnb ...

  3. 小强的Hadoop学习之路

    本人一直在做NET开发,接触这行有6年了吧.毕业也快四年了(6年是因为大学就开始在一家小公司做门户网站,哈哈哈),之前一直秉承着学要精,就一直一门心思的在做NET(也是懒吧).最近的工作一直都和大数据 ...

  4. 我的hadoop学习之路

    Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS.HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上. Ha ...

  5. Linux学习笔记(Ubuntu操作系统)之hadoop学习之路

    1:检查虚拟机的ip命令:ifconfig 2:普通用户切换root用户命令:su 3:root用户切换普通用户命令:su 用户名 4:普通用户执行系统执行前面加命令:sudo 5:查询主机名命令:h ...

  6. Hadoop学习之路(十二)分布式集群中HDFS系统的各种角色

    NameNode 学习目标 理解 namenode 的工作机制尤其是元数据管理机制,以增强对 HDFS 工作原理的 理解,及培养 hadoop 集群运营中“性能调优”.“namenode”故障问题的分 ...

  7. Hadoop学习之路(十一)HDFS的读写详解

    HDFS的写操作 <HDFS权威指南>图解HDFS写过程 详细文字说明(术语) 1.使用 HDFS 提供的客户端 Client,向远程的 namenode 发起 RPC 请求 2.name ...

  8. Hadoop学习之路(五)Hadoop集群搭建模式和各模式问题

    分布式集群的通用问题 当前的HDFS和YARN都是一主多从的分布式架构,主从节点---管理者和工作者 问题:如果主节点或是管理者宕机了.会出现什么问题? 群龙无首,整个集群不可用.所以在一主多从的架构 ...

  9. Hadoop学习之路(二)Hadoop发展背景

    Hadoop产生的背景 1. HADOOP最早起源于Nutch.Nutch的设计目标是构建一个大型的全网搜索引擎,包括网页抓取.索引.查询等功能,但随着抓取网页数量的增加,遇到了严重的可扩展性问题—— ...

随机推荐

  1. 【转】Java 异步处理简单实践

    同步与异步 通常同步意味着一个任务的某个处理过程会对多个线程在用串行化处理,而异步则意味着某个处理过程可以允许多个线程同时处理. 异步通常代表着更好的性能,因为它很大程度上依赖于缓冲,是典型的使用空间 ...

  2. java网络编程(TCP详解)

    网络编程详解-TCP 一,TCP协议的特点              面向连接的协议(有发送端就一定要有接收端)    通过三次连接握手建立连接 通过四次握手断开连接 基于IO流传输数据 传输数据大小 ...

  3. COGS2608 [河南省队2016]无根树

    传送门 这题大概就是传说中的动态树形DP了吧,学习了一波…… 首先,对于没有修改的情况,不难想到树形DP,定义$f_i$表示强制必须选$i$且只能再选$i$的子树中的点的最优解,易得转移方程$f_i= ...

  4. Docker for Windows(一)下载与安装

    一.下载Docker for Windows 下载地址:Docker for Windows 下载完是一个安装程序,双击运行即可.注:如果您的系统不符合运行Docker for Windows的要求, ...

  5. 实现ListView的加载更多的效果,如何将按钮布局到始终在ListView的最后一行

    实现方式一:在代码中实现: 1,在一个布局中定义一个Button,在活动中加载Button的父布局, 例如:View bottomView = getLayoutInflater().inflate( ...

  6. Object hashcode

    java jvm怎么找到一个对象? 一个对象有一个独一无二的hashcode,这样就可以找到这个对象了. 但java 的hashcode 实现的不好,有可能两个不同的对象有一个相同的hashcode, ...

  7. springmvc源码解析-初始化

    1.      概述 对于Web开发者,MVC模型是大家再熟悉不过的了,SpringMVC中,满足条件的请求进入到负责请求分发的DispatcherServlet,DispatcherServlet根 ...

  8. hibernate中指定非外键进行关联

    /** * 上级资源 */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PARENT_ID", reference ...

  9. 洛谷P1064 金明的预算方案

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元钱就行”. ...

  10. C# 判断程序是否已经在运行

    方式1: /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static void Main() { //获取欲启 ...