你不知道的BAT大数据面试题


1、kafka的message包括哪些信息一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成。当magic的值为1的时候,会在magic和crc32之间多一个字节的数据:attributes(保存一些相关属性,比如是否压缩、压缩格式等等);如果magic的值为0,那么不存在attributes属性
body是由N个字节构成的一个消息体,包含了具体的key/value消息2、怎么查看kafka的offset0.9版本以上,可以用最新的Consumer client客户端,有consumer.seekToEnd() / consumer.position()可以用于得到当前最新的offset:3、hadoop的shuffle过程一、Map端的shuffle
  Map端会处理输入数据并产生中间结果,这个中间结果会写到本地磁盘,而不是HDFS。每个Map的输出会先写到内存缓冲区中,当写入的数据达到设定的阈值时,系统将会启动一个线程将缓冲区的数据写到磁盘,这个过程叫做spill。
  在spill写入之前,会先进行二次排序,首先根据数据所属的partition进行排序,然后每个partition中的数据再按key来排序。partition的目是将记录划分到不同的Reducer上去,以期望能够达到负载均衡,以后的Reducer就会根据partition来读取自己对应的数据。接着运行combiner(如果设置了的话),combiner的本质也是一个Reducer,其目的是对将要写入到磁盘上的文件先进行一次处理,这样,写入到磁盘的数据量就会减少。最后将数据写到本地磁盘产生spill文件(spill文件保存在{mapred.local.dir}指定的目录中,Map任务结束后就会被删除)。

  最后,每个Map任务可能产生多个spill文件,在每个Map任务完成前,会通过多路归并算法将这些spill文件归并成一个文件。至此,Map的shuffle过程就结束了。二、Reduce端的shuffle  Reduce端的shuffle主要包括三个阶段,copy、sort(merge)和reduce。
  首先要将Map端产生的输出文件拷贝到Reduce端,但每个Reducer如何知道自己应该处理哪些数据呢?因为Map端进行partition的时候,实际上就相当于指定了每个Reducer要处理的数据(partition就对应了Reducer),所以Reducer在拷贝数据的时候只需拷贝与自己对应的partition中的数据即可。每个Reducer会处理一个或者多个partition,但需要先将自己对应的partition中的数据从每个Map的输出结果中拷贝过来。
  接下来就是sort阶段,也成为merge阶段,因为这个阶段的主要工作是执行了归并排序。从Map端拷贝到Reduce端的数据都是有序的,所以很适合归并排序。最终在Reduce端生成一个较大的文件作为Reduce的输入。

  最后就是Reduce过程了,在这个过程中产生了最终的输出结果,并将其写到HDFS上。4、spark集群运算的模式Spark有很多种模式,最简单就是单机本地模式,还有单机伪分布式模式,复杂的则运行在集群中,目前能很好的运行在Yarn和Mesos中,当然Spark还有自带的Standalone模式,对于大多数情况Standalone模式就足够了,如果企业已经有Yarn或者Mesos环境,也是很方便部署的。
standalone(集群模式):典型的Mater/slave模式,不过也能看出Master是有单点故障的;Spark支持ZooKeeper来实现HA
on yarn(集群模式): 运行在yarn资源管理器框架之上,由yarn负责资源管理,Spark负责任务调度和计算
on mesos(集群模式): 运行在mesos资源管理器框架之上,由mesos负责资源管理,Spark负责任务调度和计算on cloud(集群模式):比如AWS的EC2,使用这个模式能很方便的访问Amazon的S3;Spark支持多种分布式存储系统:HDFS和S35、HDFS读写数据的过程读:
1、跟namenode通信查询元数据,找到文件块所在的datanode服务器
2、挑选一台datanode(就近原则,然后随机)服务器,请求建立socket流
3、datanode开始发送数据(从磁盘里面读取数据放入流,以packet为单位来做校验)
4、客户端以packet为单位接收,现在本地缓存,然后写入目标文件
写:
1、根namenode通信请求上传文件,namenode检查目标文件是否已存在,父目录是否存在
2、namenode返回是否可以上传
3、client请求第一个block该传输到哪些datanode服务器上
4、namenode返回3个datanode服务器ABC
5、client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将真个pipeline建立完成,逐级返回客户端
6、client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答7、当一个block传输完成之后,client再次请求namenode上传第二个block的服务器。6RDD中reduceBykey与groupByKey哪个性能好,为什么 reduceByKey:reduceByKey会在结果发送至reducer之 香港云主机前会对每个mapper在本地进行merge,有点类似于在MapReduce中的combiner。这样做的好处在于,在map端进行一次reduce之后,数据量会大幅度减小,从而减小传输,保证reduce端能够更快的进行结果计算。
groupByKey:groupByKey会对每一个RDD中的value值进行聚合形成一个序列(Iterator),此操作发生在reduce端,所以势必会将所有的数据通过网络进行传输,造成不必要的浪费。同时如果数据量十分大,可能还会造成OutOfMemoryError。

通过以上对比可以发现在进行大量数据的reduce操作时候建议使用reduceByKey。不仅可以提高速度,还是可以防止使用groupByKey造成的内存溢出问题。
7、spark2.0的了解 更简单:ANSI SQL与更合理的API
速度更快:用Spark作为编译器
更智能:Structured Streaming

8、rdd怎么分区宽依赖和窄依赖宽依赖:父RDD的分区被子RDD的多个分区使用例如groupByKey、reduceByKey、sortByKey等操作会产生宽依赖,会产生shuffle窄依赖:父RDD的每个分区都只被子RDD的一个分区使用例如map、filter、union等操作会产生窄依赖9、spark streaming读取kafka数据的两种方式这两种方式分别是:
Receiver-base
使用Kafka的高层次Consumer API来实现。receiver从Kafka中获取的数据都存储在Spark Executor的内存中,然后Spark Streaming启动的job会去处理那些数据。然而,在默认的配置下,这种方式可能会因为底层的失败而丢失数据。如果要启用高可靠机制,让数据零丢失,就必须启用Spark Streaming的预写日志机制(Write Ahead Log,WAL)。该机制会同步地将接收到的Kafka数据写入分布式文件系统(比如HDFS)上的预写日志中。所以,即使底层节点出现了失败,也可以使用预写日志中的数据进行恢复。
Direct
Spark1.3中引入Direct方式,用来替代掉使用Receiver接收数据,这种方式会周期性地查询Kafka,获得每个topic+partition的最新的offset,从而定义每个batch的offset的范围。当处理数据的job启动时,就会使用Kafka的简单consumerapi来获取Kafka指定offset范围的数据。10、kafka的数据存在内存还是磁盘Kafka最核心的思想是使用磁盘,而不是使用内存,可能所有人都会认为,内存的速度一定比磁盘快,我也不例外。在看了Kafka的设计思想,查阅了相应资料再加上自己的测试后,发现磁盘的顺序读写速度和内存持平。
而且Linux对于磁盘的读写优化也比较多,包括read-ahead和write-behind,磁盘缓存等。如果在内存做这些操作的时候,一个是JAVA对象的内存开销很大,另一个是随着堆内存数据的增多,JAVA的GC时间会变得很长,使用磁盘操作有以下几个好处:
磁盘缓存由Linux系统维护,减少了程序员的不少工作。
磁盘顺序读写速度超过内存随机读写。
JVM的GC效率低,内存占用大。使用磁盘可以避免这一问题。
系统冷启动后,磁盘缓存依然可用。

11、怎么解决kafka的数据丢失
producer端:
宏观上看保证数据的可靠安全性,肯定是依据分区数做好数据备份,设立副本数。
broker端:
topic设置多分区,分区自适应所在机器,为了让各分区均匀分布在所在的broker中,分区数要大于broker数。
分区是kafka进行并行读写的单位,是提升kafka速度的关键。
Consumer端:
consumer端丢失消息的情形比较简单:如果在消息处理完成前就提交了offset,那么就有可能造成数据的丢失。由于Kafka consumer默认是自动提交位移的,所以在后台提交位移前一定要保证消息被正常处理了,因此不建议采用很重的处理逻辑,如果处理耗时很长,则建议把逻辑放到另一个线程中去做。为了避免数据丢失,现给出两点建议:
enable.auto.commit=false关闭自动提交位移
在消息被完整处理之后再手动提交位移
12、fsimage和edit的区别?
大家都知道namenode与secondarynamenode的关系,当他们要进行数据同步时叫做checkpoint时就用到了fsimage与edit,fsimage是保存最新的元数据的信息,当fsimage数据到一定的大小事会去生成一个新的文件来保存元数据的信息,这个新的文件就是edit,edit会回滚最新的数据。

13、列举几个配置文件优化?
1)Core-site.xml文件的优化
a、fs.trash.interval,默认值:0;说明: 这个是开启hdfs文件删除自动转移到垃圾箱的选项,值为垃圾箱文件清除时间。一般开启这个会比较好,以防错误删除重要文件。单位是分钟。
b、dfs.namenode.handler.count,默认值:10;说明:hadoop系统里启动的任务线程数,这里改为40,同样可以尝试该值大小对效率的影响变化进行最合适的值的设定。
c、mapreduce.tasktracker.http.threads,默认值:40;说明:map和reduce是通过http进行数据传输的,这个是设置传输的并行线程数。

14、datanode首次加入cluster的时候,如果log报告不兼容文件版本,那需要namenode执行格式化操作,这样处理的原因是?
1)这样处理是不合理的,因为那么namenode格式化操作,是对文件系统进行格式化,namenode格式化时清空dfs/name下空两个目录下的所有文件,之后,会在目录dfs.name.dir下创建文件。
2)文本不兼容,有可能时namenode与datanode的 数据里的namespaceID、clusterID不一致,找到两个ID位置,修改为一样即可解决。
15、MapReduce中排序发生在哪几个阶段?这些排序是否可以避免?为什么?
1)一个MapReduce作业由Map阶段和Reduce阶段两部分组成,这两阶段会对数据排序,从这个意义上说,MapReduce框架本质就是一个Distributed Sort。
2)在Map阶段,Map Task会在本地磁盘输出一个按照key排序(采用的是快速排序)的文件(中间可能产生多个文件,但最终会合并成一个),在Reduce阶段,每个Reduce Task会对收到的数据排序,这样,数据便按照Key分成了若干组,之后以组为单位交给reduce()处理。
3)很多人的误解在Map阶段,如果不使用Combiner便不会排序,这是错误的,不管你用不用Combiner,Map Task均会对产生的数据排序(如果没有Reduce Task,则不会排序,实际上Map阶段的排序就是为了减轻Reduce端排序负载)。
4)由于这些排序是MapReduce自动完成的,用户无法控制,因此,在hadoop 1.x中无法避免,也不可以关闭,但hadoop2.x是可以关闭的。

16、hadoop的优化?
1)优化的思路可以从配置文件和系统以及代码的设计思路来优化
2)配置文件的优化:调节适当的参数,在调参数时要进行测试
3)代码的优化:combiner的个数尽量与reduce的个数相同,数据的类型保持一致,可以减少拆包与封包的进度
4)系统的优化:可以设置linux系统打开最大的文件数预计网络的带宽MTU的配置
5)为job添加一个Combiner,可以大大的减少shuffer阶段的maoTask拷贝过来给远程的 reduce task的数据量,一般而言combiner与reduce相同。
6)在开发中尽量使用stringBuffer而不是string,string的模式是read-only的,如果对它进行修改,会产生临时的对象,二stringBuffer是可修改的,不会产生临时对象。
7)修改一下配置:以下是修改mapred-site.xml文件
a、修改最大槽位数:槽位数是在各个tasktracker上的mapred-site.xml上设置的,默认都是2mapred.tasktracker.map.tasks.maximum
2
mapred.tasktracker.reduce.tasks.maximum
2
b、调整心跳间隔:集群规模小于300时,心跳间隔为300毫秒
mapreduce.jobtracker.heartbeat.interval.min心跳时间
mapred.heartbeats.in.second集群每增加多少节点,时间增加下面的值
mapreduce.jobtracker.heartbeat.scaling.factor集群每增加上面的个数,心跳增多少
c、启动带外心跳
mapreduce.tasktracker.outofband.heartbeat默认是false
d、配置多块磁盘
mapreduce.local.dir
e、配置RPC hander数目
mapred.job.tracker.handler.count默认是10,可以改成50,根据机器的能力
f、配置HTTP线程数目
tasktracker.http.threads默认是40,可以改成100根据机器的能力
g、选择合适的压缩方式,以snappy为例:mapred.compress.map.output
true
mapred.map.output.compression.codec
org.apache.hadoop.io.compress.SnappyCodec

17、设计题
1)采集nginx产生的日志,日志的格式为user ip time url htmlId 每天产生的文件的数据量上亿条,请设计方案把数据保存到HDFS上,并提供一下实时查询的功能(响应时间小于3s
A、某个用户某天访问某个URL的次数
B、某个URL某天被访问的总次数
实时思路是:使用Logstash + Kafka + Spark-streaming + Redis +报表展示平台
离线的思路是:Logstash + Kafka + Elasticsearch + Spark-streaming +关系型数据库
A、B、数据在进入到Spark-streaming中进行过滤,把符合要求的数据保存到Redis中

18、有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。 还是典型的TOP K算法,
解决方案如下:
1)方案1:
顺序读取10个文件,按照hash(query)%10的结果将query写入到另外10个文件(记为)中。这样新生成的文件每个的大小大约也1G(假设hash函数是随机的)。 找一台内存在2G左右的机器,依次对用hash_map(query, query_count)来统计每个query出现的次数。利用快速/堆/归并排序按照出现次数进行排序。将排序好的query和对应的query_cout输出到文件中。这样得到了10个排好序的文件(记为)。 对这10个文件进行归并排序(内排序与外排序相结合)。
2)方案2:
一般query的总量是有限的,只是重复的次数比较多而已,可能对于所有的query,一次性就可以加入到内存了。这样,我们就可以采用trie树/hash_map等直接来统计每个query出现的次数,然后按出现次数做快速/堆/归并排序就可以了。
3)方案3:
与方案1类似,但在做完hash,分成多个文件后,可以交给多个文件来处理,采用分布式的架构来处理(比如MapReduce),最后再进行合并。

19、在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
1)方案1:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)进行,共需内存2^32 * 2bit=1 GB内存,还可以接受。然后扫描这2.5亿个整数,查看Bitmap中相对应位,如果是00变01,01变10,10保持不变。所描完事后,查看bitmap,把对应位是01的整数输出即可。
2)方案2:也可采用与第1题类似的方法,进行划分小文件的方法。然后在小文件中找出不重复的整数,并排序。然后再进行归并,注意去除重复的元素。

20腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
1)方案1:oo,申请512M的内存,一个bit位代表一个unsigned int值。读入40亿个数,设置相应的bit位,读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在。
2)方案2:这个问题在《编程珠玑》里有很好的描述,大家可以参考下面的思路,探讨一下:又因为2^32为40亿多,所以给定一个数可能在,也可能不在其中;这里我们把40亿个数中的每一个用32位的二进制来表示 ,假设这40亿个数开始放在一个文件中。 然后将这40亿个数分成两类:
1.最高位为0
2.最高位为1
并将这两类分别写入到两个文件中,其中一个文件中数的个数=20亿(这相当于折半了); 与要查找的数的最高位比较并接着进入相应的文件再查找再然后把这个文件为又分成两类:
1.次最高位为0
2.次最高位为1
并将这两类分别写入到两个文件中,其中一个文件中数的个数=10亿(这相当于折半了); 与要查找的数的次最高位比较并接着进入相应的文件再查找。
…..
以此类推,就可以找到了,而且时间复杂度为O(logn),方案2完。
3)附:这里,再简单介绍下,位图方法: 使用位图法判断数组是否存在重复,判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。
位图法比较适合于这种情况,它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1,如遇到5就给新数组的第六个元素置1,这样下次再遇到5想置位时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。这 种给新数组初始化时置零其后置一的做法类似于位图的处理方法故称位图法。它的运算次数最坏的情况为2N。如果已知数组的最大值即能事先给新数组定长的话效 率还能提高一倍。

21、怎么在海量数据中找出重复次数最多的一个?
1)方案1:先做hash,然后求模映射为小文件,求出每个小文件中重复次数最多的一个,并记录重复次数。然后找出上一步求出的数据中重复次数最多的一个就是所求(具体参考前面的题)。

22、上千万或上亿数据(有重复),统计其中出现次数最多的钱N个数据。
1)方案1:上千万或上亿的数据,现在的机器的内存应该能存下。所以考虑采用hash_map/搜索二叉树/红黑树等来进行统计次数。然后就是取出前N个出现次数最多的数据了,可以用第2题提到的堆机制完成。

23、一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词,给出思想,给出时间复杂度分析。
1)方案1:这题是考虑时间效率。用trie树统计每个词出现的次数,时间复杂度是O(n*le)(le表示单词的平准长度)。然后是找出出现最频繁的前10个词,可以用堆来实现,前面的题中已经讲到了,时间复杂度是O(n*lg10)。所以总的时间复杂度,是O(n*le)与O(n*lg10)中较大的哪一 个。
24、100w个数中找出最大的100个数。
1)方案1:在前面的题中,我们已经提到了,用一个含100个元素的最小堆完成。复杂度为O(100w*lg100)。
2)方案2:采用快速排序的思想,每次分割之后只考虑比轴大的一部分,知道比轴大的一部分在比100多的时候,采用传统排序算法排序,取前100个。复杂度为O(100w*100)。
3)方案3:采用局部淘汰法。选取前100个元素,并排序,记为序列L。然后一次扫描剩余的元素x,与排好序的100个元素中最小的元素比,如果比这个最小的 要大,那么把这个最小的元素删除,并把x利用插入排序的思想,插入到序列L中。依次循环,直到扫描了所有的元素。复杂度为O(100w*100)。

25、有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复。 请用5分钟时间,找出重复出现最多的前10条。
1)分析: 常规方法是先排序,在遍历一次,找出重复最多的前10条。但是排序的算法复杂度最低为nlgn。
2)可以设计一个hash_table, hash_map,依次读取一千万条短信,加载到hash_table表中,并且统计重复的次数,与此同时维护一张最多10条的短信表。 这样遍历一次就能找出最多的前10条,算法复杂度为O(n)。
获取更多大数据相关资料:一线企业大数据工程师免费在线指导技术问题请扫描下方微信二维码:

相关推荐: 电脑蓝屏原因是什么

这篇文章主要介绍“电脑蓝屏原因是什么”,在日常操作中,相信很多人在电脑蓝屏原因是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”电脑蓝屏原因是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!1.硬盘出现问题当电脑内存过小…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 07/23 18:20
下一篇 07/23 18:21

相关推荐