大数据面试题分析

最近学习了hashtable的一点知识,发现可以用来解决大数据的一些问题。我们这里讲的大数据分析事实上并不是分布式和数据挖掘这些高深的概念,而是针对从从一个大文件或者一堆数据(内存放不下)中找出具有某种特点的数,这也是近年来各大公司经常考的问题


面试题1:给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?

解析100G的文件给我们的感觉是太大,我们的电脑内存一般都为4G左右所以不可能一次性把这么多的信息都加载到内存,所以就要进行切分成100份。IP地址是字符串太长,我们可以把它转化为整型%100,这样取模后的值都落在0-99的区间里,所取模后值相同的IP地址都被分配到同一个文件,这时我们就可以采用哈希表统计出每个文件中最多的那个IP地址,最后比较得到100个IP中最大的那个IP就可以了 。

面试题2:与上题条件相同,如何找到top K的IP?

解析看到求TOP K个IP就要立马反应到使用堆排序,这里的堆排序应该注意的是要建一个小堆,想一下我们建大堆的话只能保证堆顶元素为最大的,这样只能得到最大的那个IP。

面试题3:给定100亿个整数,设计算法找到只出现一次的整数

解析整数分为有符号和无符号两种,有符号数的取值为-2147483648~2147483648 是从-21亿到+21亿, 无符号数的范围为0~4294967296是从0到42亿,然而给了我们100亿个整数,要找出只出现一次的整数,所以我们还是要用到哈希表的思想,但我们最好不要定义一个整型数组,因为 42亿*4B  约为16G,这么大的数组我们再进行切分的话就太麻烦了,这里我们可以使用BitMap,用一个位来表示一个数存不存在,不存在表示为0,出现一次表示为1,出现一次以上用另一个位表示。这样就可以将数组的大小减为原来的16分之一。还遇到一个问题,就是到底怎么定义这个数组,正数好定义,负数的话我们可以用32位全1(-1)和它取异或取到和正数相同的位置,我们此时定义一个二维数组,一半表示正数一半表示负数,都位于同一行。此时我们使用1G的空间就可以解决这个问题了。

拓展:要是面试官问我这里只有500M或者更少的空间的话怎么做?

解析同样采用切分的思想,不过我觉得这里我们直接可以按数的范围直接切分。要是有500M 内存的话,我们就切一次就可以了,此时如果我们有50%的几率一次就找到这个只出现一次的数,效率可能更高。

面试题4:给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?

解析:这道题思路和上面的一样。

面试题5:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

解析这个问题和以上唯一 不同这道题是找不超过两次的整数,方法一样。

面试题6:给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集分别给出精确算法和近似算法!

解析求两个文件的交集,这种算法我们肯定要用到比较,如果我们把两个文件都均分为100份,拿一个文件里的一份分别与另一个文件里的100份分别比较一次的话效率 就太低了,我们可以借用第1道面试题的思维对它们进行取模,这样我们只要比较取模的为同一值的两个文件比较就可以了,如果相同则标记。

面试题7:如何扩展BloomFilter使得它支持删除元素的操作?

解析BloomFilter并不支持删除元素的操作,因为很可能产生哈希冲突(就是由不同的哈希函数算出的位置指向同一个位),这样改变一个位很可能会影响到其他元素的判断。这里我们可以按照和智能指针sharedptr的思想即“引用计数”来解决,我们添加一个count计数器,每当我们在这个位上表示一个元素时就让它count++,每删除一个涉及到这个位表示的元素时就让它count--,这样只当count为0时我们再对这一位置0,这样就完成了删除的操作。

面试题8:如何扩展BloomFilter使得它支持计数操作?

解析这道题思想和上一道题一样。

面试题9:给上千个文件,每个文件大小为1K—100M。给n个词,设计算法对每个词找到所有包含它的文件,你只有100K内存

解析我们可以使用布隆过滤器来判断一个文件是否包含这n个单词生成n个布隆过滤器放到外存,我们事先定义好一个包含这n个单词信息的文件info,每当我们在一个文件找到一个对应的单词就将这个文件的信息写入info对应单词的位置。我们只有100K内存,这100K内存我们一部分用来存放布隆过滤器一部分可以存放文件,因为文件最小都为100K,所以我们可以尝试把它切分为50K的小文件,每个文件标志好所属的大文件,这样我们每次读入一个布隆过滤器和一个小文件,如果这个文件有对应的单词则在info中标记所属大文件的信息,如果没有则读入下一个布隆过滤器,把所有布隆过滤器都使用后,再读下一个文件重复上述步骤直至把所有文件都遍历完。

面试题10:有一个词典,包含N个英文单词,现在任意给一个字符串,设计算法找出包含这个字符串的所有英文单词

解析首先判断一个单词是否包含一个字符串我们可以用strstr这个函数,对于这个问题,我觉得如果该字符串的前缀和要找的单词一样的话可以采用字典树来查找,但是N个英文单词我们可以假设它很大,我们把它放到一个文件里,每次只读出固定个数个单词进行判断。


总结:对于此类大数据问题我们一般都是采用哈希切分即模上一个数组的长度将数据分配到一个合理的位置,同时将一个大文件切分为小文件,这样特别方便将其与其他数进行比较例如对IP地址取整后进行哈希切分,或者对内部元素进行操作。使用BloomFilter可以进行判断元素在集合的存在与否。

面试题总结:

  1. 分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。分布式文件系统的设计基于客户机/服务器模式。

    [优点]

    支持超大文件 超大文件在这里指的是几百M,几百GB,甚至几TB大小的文件。

    检测和快速应对硬件故障在集群的环境中,硬件故障是常见的问题。因为有上千台服务器连接在一起,这样会导致高故障率。因此故障检测和自动恢复是hdfs文件系统的一个设计目标

    流式数据访问应用程序能以流的形式访问数据集。主要的是数据的吞吐量,而不是访问速度。

    简化的一致性模型 大部分hdfs操作文件时,需要一次写入,多次读取。在hdfs中,一个文件一旦经过创建、写入、关闭后,一般就不需要修改了。这样简单的一致性模型,有利于提高吞吐量。

    [缺点]

    低延迟数据访问如和用户进行交互的应用,需要数据在毫秒或秒的范围内得到响应。由于hadoop针对高数据吞吐量做了优化,牺牲了获取数据的延迟,所以对于低延迟来说,不适合用hadoop来做。

    大量的小文件Hdfs支持超大的文件,是通过数据分布在数据节点,数据的元数据保存在名字节点上。名字节点的内存大小,决定了hdfs文件系统可保存的文件数量。虽然现在的系统内存都比较大,但大量的小文件还是会影响名字节点的性能。

    多用户写入文件、修改文件Hdfs的文件只能有一次写入,不支持写入,也不支持修改。只有这样数据的吞吐量才能大。

    不支持超强的事务没有像关系型数据库那样,对事务有强有力的支持。
    详情查看:https://www.cnblogs.com/sxt-zkys/archive/2017/07/24/7229857.html

  2. Gangila不仅可以进行监控,也可以进行告警。(正确)
      Ganglia是UC Berkeley发起的一个开源集群监视项目,设计用于测量数以千计的节点。Ganglia的核心包含gmond、gmetad以及一个Web前端。主要是用来监控系统性能,如:cpu 、mem、硬盘利用率, I/O负载、网络流量情况等,通过曲线很容易见到每个节点的工作状态,对合理调整、分配系统资源,提高系统整体性能起到重要作用。ganglia 作为一款最常用的 Linux 环境中的监控软件,它擅长的的是从节点中按照用户的需求以较低的代价采集数据。但是 ganglia 在预警以及发生事件后通知用户上并不擅长。最新的 ganglia 已经有了部分这方面的功能。
      Nagios是一款开源的免费网络监视工具,能有效监控Windows、Linux和Unix的主机状态,交换机路由器等网络设备,打印机等。在系统或服务状态异常时发出邮件或短信报警第一时间通知网站运维人员,在状态恢复后发出正常的邮件或短信通知。
      通过将 Ganglia Nagios 组合起来,把 Ganglia 采集的数据作为 Nagios 的数据源,然后利用 Nagios 来发送预警通知,可以 完美的实现一整套监控管理的系统。 具体可以查看 完美集群监控组合 ganglia nagios。
    ps.云计算管理三大利器:Nagios、Ganglia和Splunk


  3. Block Size是不可以修改的。(错误)-----它是可以被修改的
    Hadoop的基础配置问件事hadoop-default.xml,默认建立一个job的时候会建立job的configuration,首先读入的是hadoop-default.xml的配置,然后再读hadoop-site.xml的配置(这个文件初始的时候配置为空),hadoop-site.xml中主要配置需要覆盖的hadoop-default.xml的系统级配置。具体配置可以参考下
    <property>
    <name>dfs.block.sizename>//block的大小,单位字节,后面会提到用处,必须是512的倍数,因为采用crc做文件完整性校验,默认配置512是checksum的最小单元
    <value>5120000value>
    property>

     ps.循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

  4. Nagios不可以监控hadoop集群,因为它不提供hadoop支持。(错误)
    nagios是集群监控工具,而且是云计算三大利器之一

  5. 如果namenode意外终止,secondarynamenode会接替他是集群继续工作。(错误)
    secondarynamenode是帮助恢复,而不是替代,如何恢复,可以查看hadoop根据secondarynamenode恢复namenode。在高可用集群中,一个namenode(active)死亡后,ZKFC(zookeeper控制器)仲裁将另一个standby-namenode启动,转换成active状态,集群继续正常工作。


  6. Cloudera CDH是需要付费使用的。(错误)

    第一套付费产品是 Cloudera Enterpris

  7. Hadoop是Java开发的,所以MapReduce只支持Java语言编写。(错误)
    rhadoop是用R语言开发的,MapReduce是一个框架,可以理解是一种思想,可以使用其他语言开发。

  8. 什么是Map/Reduce:
    MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)"和"Reduce(归约)",是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。它极大地方便了编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上。 当前的软件实现是指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(归约)函数,用来保证所有映射的键值对中的每一个共享相同的键组。
    概述
    1)MapReduce是一个 基于集群的高性能并行计算平台(Cluster Infrastructure)。它允许用市场上普通的商用服务器构成一个包含数十、数百至数千个节点的分布和并行计算集群。
    2)MapReduce是一个 并行计算与运行软件框架(Software Framework)。它提供了一个庞大但设计精良的并行计算软件框架,能自动完成计算任务的并行化处理,自动划分计算数据和计算任务,在集群节点上自动分配和执行任务以及收集计算结果,将数据分布存储、数据通信、容错处理等并行计算涉及到的很多系统底层的复杂细节交由系统负责处理,大大减少了软件开发人员的负担。
    3)MapReduce是一个 并行程序设计模型与方法(Programming Model & Methodology)。它借助于函数式程序设计语言Lisp的设计思想,提供了一种简便的并行程序设计方法,用Map和Reduce两个函数编程实现基本的并行计算任务,提供了抽象的操作和并行编程接口,以简单方便地完成大规模数据的编程和计算处理。
    实现:
    把一堆杂乱无章的数据按照某种特征归纳起来,然后处理并得到最后的结果。Map面对的是杂乱无章的互不相关的数据,它解析每个数据,从中提取出key和value,也就是提取了数据的特征。经过MapReduce的Shuffle阶段之后,在Reduce阶段看到的都是已经归纳好的数据了,在此基础上我们可以做进一步的处理以便得到结果。

  9. Hadoop支持数据的随机读写。(错误)
    lucene是支持随机读写的,而hdfs只支持随机读。但是Hbase可以来补救。Hbase提供随机读写,来解决Hadoop不能处理的问题。HBase 自底层设计开始即聚焦于各种可伸缩性问题:表可以很―高‖,有数十亿个数据行;也可以很―宽‖,有数百万个列;水平分区并在上千个普通商用机节 点上自动复制。表的模式是物理存储的直接反映,使系统有可能提高高效的数据结构的序列化、存储和检索。
    ps.Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。

  10. namenode负责管理metadata,client端每次读写请求,都会从磁盘中读取或则会写入 metadata 信息并反馈client 端。(错误)
    NameNode 不需要从磁盘读取 metadata,所有数据都在内存中,硬盘上的只是序列化的结果,只有每次namenode 启动的时候才会读取。

    1)文件写入Client NameNode 发起文件写入的请求。NameNode 根据文件大小和文件块配置情况,返回给 Client 它所管理部分 DataNode 的信息。Client 将文件划分为多个 Block,根据 DataNode 的地址信息,按顺序写入到每一个 DataNode 块中。

    2)文件读取Client NameNode 发起文件读取的请求。NameNode 返回文件存储的 DataNode 的信息。Client 读取文件信息。 
    ps.http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%8E%92%E8%A1%8C/9053.shtml

  11. datanode通过长连接与namenode保持通信。(正确)【答案有分歧,根据自己理解回答即可】

    长连接:Client 方与Server 方先建立通讯连接,连接建立后不断开,然后再进行报文发送和接收。这种方式下由于通讯连接一直存在,此种方式常用于点对点通讯。

    短连接:Client 方与Server 每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此种方式常用于一点对多点通讯,比如多个Client 连接一个Server。

  12. Hadoop自身具有严格的权限管理和安全措施保障集群正常运行。(错误) 

  13. slave节点要存储数据,所以它的磁盘越大越好。(错误)
    一旦slave节点宕机,数据恢复是一个难题。

  14. hadoop dfsadmin -report用于检测HDFS损坏块。(错误)
    hadoop dfsadmin -report可以用来查询集群的状况,可以快速定位出各个节点,HDFS的容量和使用量,以及每个节点的硬盘使用情况。当然这个也可以通过50070端口进行查看,但是这个命令更有利于我们利用脚本来监控dfs的使用状况

  15. Hadoop默认调度器策略为FIFO。(正确)【first input first output】
    FIFO是先入先出队列,是一种传统的按序执行的方法。

     

  16.  Hadoop集群三种作业调度算法介绍
    Hadoop集群中有三种作业调度算法,分别为FIFO公平调度算法计算能力调度算法
    先来先服务算法FIFO:FIFO比较简单,hadoop中只有一个作业队列,被提交的作业按照先后顺序在作业队列中排队,新来的作业插入到队尾。一个作业运行完后,总是从队首取下一个作业运行。这种调度策略的优点是简单、易于实现,同时也减轻了jobtracker的负担。但是它的缺点也是显然的,它对所有的作业都一视同仁,没有考虑到作业的紧迫程度,另外对小作业的运行不利。
    公平调度算法
    这种策略在系统中配置了任务槽,一个任务槽可以运行一个task任务,这些任务就是一个大的作业被切分后的小作业。当一个用户提交多个作业时,每个作业可以分配到一定的任务槽以执行task任务(这里的任务槽可以理解为可以运行一个map任务或reduce任务)。如果把整个hadoop集群作业调度跟操作系统的作业调度相比,第一种FIFO就相当于操作系统中早期的单道批处理系统,系统中每个时刻只有一道作业在运行,而公平调度相当于多道批处理系统,它实现了同一个时刻多道作业同时运行。由于linux是多用户的,若有多个用户同时提交多个作业会怎样?在这种策略中给每个用户分配一个作业池,然后给每个作业池设置一个最小共享槽个数,什么是最小共享槽个数呢?先要理解一个最小什么意思,最小是指只要这个作业池需要,调度器应该确保能够满足这个作业池的最小任务槽数的需求,但是如何才能确保在它需要的时候就有空的任务槽,一种方法是固定分配一定数量的槽给作业池不动,这个数量至少是最小任务槽值,这样只要在作业池需要的时候就分配给它就行了,但是这样在这个作业池没有用到这么多任务槽的时候会造成浪费,这种策略实际上是这样做的,当作业池的需求没有达到最小任务槽数时,名义上是自己的剩余的任务槽会被分给其他有需要的作业池,当一个作业池需要申请任务槽的时候若系统中没有了,这时候不会去抢占别人的(也不知道抢谁的啊),只要当前一个空的任务槽释放会被立即分配给这个作业池。

    在一个用户的作业池内,多个作业如何分配槽这个可以自行选择了,如FIFO。所以这种调度策略分为两级:

    第一级,在池间分配槽,在多用户的情况下,每个用户分配一个作业池。
    第二级,在作业池内,每个用户可以使用不同的调度策略。

     计算能力调度计算能力调度和公平调度有点类似,公平调度策略是以作业池为单位分配任务槽,而计算能力调度是以队列为单位分配tasktracker(集群中一个节点),这种调度策略配置了多个队列,每个队列配置了最小额度的tasktracker数量,同公平调度策略类似,当一个队列有空闲的tasktracker时,调度器会将空闲的分配给其他的队列,当有空闲的tasktracker时,由于这时候可能有多个队列没有得到最小额度的tasktracker而又在申请新的,空闲的tasktracker会被优先分配到最饥饿的队列中去,如何衡量饥饿程度呢?可以通过计算队列中正在运行的任务数与其分得的计算资源之间的比值是否最低来判断的,越低说明饥饿程度越高。

    计算能力调度策略是以队列的方式组织作业的,所以一个用户的作业可能在多个队列中,如果不对用户做一定的限制,很可能出现在多个用户之间出现严重不公平的现象。所以在选中新作业运行时候,还需要考虑作业所属的用户是否超过了资源的限制,如果超过,作业不会被选中。

    对于在同一个队列中,这种策略使用的是基于优先级的FIFO策略,但是不会抢占。

  17. 集群内每个节点都应该配 RAID,这样避免单磁盘损坏,影响整个节点运行。(错误 )

    hadoop 本身就具有冗余能力,所以如果不是很严格不需要都配备 RAID

    磁盘阵列(Redundant Arrays of Independent Disks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意。

     

    磁盘阵列是由很多价格较便宜的磁盘,组合成一个容量巨大的磁盘组,利用个别磁盘提供数据所产生加成效果提升整个磁盘系统效能。利用这项技术,将数据切割成许多区段,分别存放在各个硬盘上。

     

    磁盘阵列还能利用同位检查(Parity Check)的观念,在数组中任意一个硬盘故障时,仍可读出数据,在数据重构时,将数据经计算后重新置入新硬盘中。

  18. 因为HDFS有多个副本,所以namenode不存在单点问题。(错误)
    查看1
  19. 每个 map 槽就是一个线程。(错误)

    map 槽---->map slot。(org.apache.hadoop.mapred.TaskTracker.TaskLaucher.numFreeSlots)是一个逻辑值,而不是对应着一个县城或者进程。

  20. Mapreduce input split 就是一个 block。(错误) 

    InputFormat的数据划分、split调度、数据读取三个问题的浅析www.aboutyun.com/thread-6803-1-1.html

     

  21. Hadoop 环境变量中的 HADOOP_HEAPSIZE 用于设置所有 Hadoop 守护线程的内存。它默认是 200 GB。(错误) 

    hadoop 为各个守护进程(namenode,secondarynamenode,resourcemanager,datanode,nodemanager)统一分配的内存在 hadoop-env.sh 中设置,参数为 HADOOP_HEAPSIZE,默认为 1000M

  22. DataNode 首次加入cluster 的时候,如果log 中报告不兼容文件版本,那需要NameNode执行hdfs namenode -format操作格式化磁盘。(错误) 

    添加了一个新的标识符 ClusterID 用于标识集群中所有的节点。当格式化一个 Namenode,需要提供这个标识符或者自动生成。这个 ID 可以被用来格式化加入集群的其他 Namenode


你可能感兴趣的:(Hadoop)