zoukankan      html  css  js  c++  java
  • Hadoop学习之路(一)理论基础和逻辑思维

    三个题目

    第一题

    问题描述

    统计出当前这个一行一个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

  • 相关阅读:
    【网络与系统安全】20179209 利用metasploit对windows系统的渗透
    2017-2018-1 20179209《Linux内核原理与分析》第五周作业
    【网络与系统安全】20179209 木马的利用
    2017-2018-1 20179209《Linux内核原理与分析》第四周作业
    【网络与系统安全】20179209 wireshark和nmap实验
    2017-2018-1 20179209《Linux内核原理与分析》第三周作业
    20179209课后作业之od命令重写
    ORA-12505 错误解决
    linux_memcached_memcachedb
    linux_jvm_jmap_dump内存分析
  • 原文地址:https://www.cnblogs.com/qingyunzong/p/8487180.html
Copyright © 2011-2022 走看看