十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

网易2018大数据笔试题解析:从Java基础到Spark核心原理

网易2018大数据笔试题解析:从Java基础到Spark核心原理 春招和秋招那会儿网上铺天盖地都是各大厂的笔试题回忆版但很多帖子就是简单贴个题目列表顶多加几句“难度适中”“考了不少Java”。真正把一张卷子吃透、讲明白“为什么考这个、想考察什么能力”的帖子并不多。前阵子整理硬盘翻出了早年保存的网易2018校园招聘大数据开发工程师笔试卷重新看了一遍发现这张卷子虽然过去几年了但里面的考点设计和考察逻辑放到今天依然很有参考价值。如果你正在准备大数据开发岗的校招或社招或者刚从后端转大数据方向这篇文章值得你花十分钟看完。我会把这张卷子里涉及的考点挨个拆开讲清楚每个题目背后的原理、常见的答题思路以及我在实际工作中踩过的坑。毕竟笔试只是敲门砖真正干活的时候这些知识点会以各种姿势回来找你。1. 试卷整体拆解网易在找什么样的人先看大方向。2018年的网易大数据开发岗笔试整体分为两大部分客观题和主观编程题。客观题覆盖Java基础、并发编程、JVM、操作系统、网络、数据库还有大数据生态里Hadoop、Spark、Kafka、Hive、ZooKeeper这些核心组件的原理。主观题则是经典的算法题和场景设计题。1.1 大数据开发工程师的考察定位为什么校招笔试考这么多Java和计算机基础而不是直接考大数据框架的使用这个逻辑要先想明白。2018年那会儿虽然大数据生态已经比较成熟但校招进来的同学底子参差不齐。网易做的是互联网产品技术栈以Java为核心大数据平台也深度绑定Java生态。你写MapReduce、Spark作业本质上就是在写Java/Scala程序你调优Hive底层跑的还是MR或者Spark引擎。所以Java基础不扎实后面什么都白搭。考察计算机基础也是同理。大数据开发虽然表面上在操作框架但一旦遇到性能问题、数据倾斜、节点故障最后拼的还是你对操作系统、网络、数据库原理的理解。1.2 从笔试卷看技术能力模型把整张卷子的考点拉通来看网易想要的人才是这样的Java功底扎实对集合、并发、JVM有深入理解不是只会写CRUD熟悉大数据核心组件的原理不只是会调用API有一定算法功底能解决实际问题有系统设计思维能处理分布式环境下的数据一致性、性能问题这套能力模型跟今天的大数据开发岗要求几乎一致。现在很多团队面大数据开发依然会问HashMap原理、JVM调优、HDFS写入流程、Spark Shuffle机制这些考点从来没有过时。1.3 为什么这套题现在仍有参考价值有人可能会说2018年的题现在技术都变了还有啥好看的?确实像Flink在当年还没完全普及到现在已经是实时计算的事实标准Kafka的架构也经历了比较大的演进。但核心原理没变分布式存储怎么写数据才高效消息队列怎么保证不丢消息分布式协调服务怎么解决一致性问题。这些底层逻辑十年不变变的是上层封装。所以刷这套题的正确姿势不是背答案而是以考点为索引把背后的原理彻底搞懂。2. 核心考点解析语言基础与计算机原理这一部分是整个试卷的基石也是不少科班同学翻车的地方。我按照考点类型逐个展开讲。2.1 Java必考点HashMap、并发与JVMHashMap是Java面试的常青树网易这轮笔试也不例外。我记得很清楚题目问的是HashMap在JDK 7和JDK 8底层实现的区别以及在什么情况下链表会转成红黑树。这里有一个容易忽略的细节为什么要引入红黑树本质上是为了解决哈希冲突严重时的查询性能退化问题。Java 8之前HashMap的冲突处理是链地址法如果哈希函数设计不好或者冲突概率高链表会变得很长get操作的时间复杂度从O(1)退化成O(n)。红黑树是一种自平衡二叉查找树插入、删除、查找的时间复杂度都是O(log n)所以当链表长度超过阈值默认8时JDK 8的实现会把链表转成红黑树。但有个点很多人背了八股也不知道为什么——为什么阈值是8因为经过数学计算和工程验证在负载因子0.75、哈希函数分布均匀的前提下一个桶里链表长度达到8个元素的概率只有大约千万分之六。也就是说绝大多数情况下链表根本不会长到8阈值设成8是为了极端情况下才触发树化平时尽量保持链表结构因为红黑树的节点占用的内存是普通链表节点的两倍左右树化的代价并不小。上面这些深挖下去答题的时候比干巴巴地列区别要精彩得多。并发编程方面笔试考察了synchronized和ReentrantLock的区别以及volatile关键字的语义。这里核心要抓住几个本质问题synchronized是JVM层面的锁由字节码指令monitorenter/monitorexit实现ReentrantLock是JDK提供的API层面的锁synchronized是非公平锁ReentrantLock默认也是非公平锁但可以传参变成公平锁synchronized的锁升级过程无锁、偏向锁、轻量级锁、重量级锁是JDK 6之后的重要优化volatile保证可见性和有序性但不保证原子性volatile这个点值得展开。很多新手分不清volatile和synchronized实际上它们的应用场景完全不同。volatile是轻量级同步机制适合解决多线程环境下的可见性问题比如一个线程修改了某个标志位其他线程需要立刻看到。它不具备原子性所以i这种复合操作哪怕变量是volatile修饰的依然存在线程安全问题。我当时在实际项目中就踩过这个坑用volatile修饰一个计数器结果并发环境下出现了丢数据。排查了很久才意识到问题所在。JVM部分考了大题问的是内存溢出怎么排查。网易出题很实际直接给了场景某个线上服务持续Full GCCPU飙升怎么定位。正常的排查思路是# 1. 先用TOP命令找到耗CPU的进程PID top # 2. 再用top -Hp PID 找到耗CPU的线程ID top -Hp 12345 # 3. 将线程ID转成十六进制用于线程dump定位 printf %x\n 8636 # 4. 使用jstack导出线程栈分析问题线程 jstack 12345 | grep -A 30 0x21bc # 5. 查看GC日志确认是否有内存溢出 jstat -gcutil 12345 1000这里的关键不只是背命令而是理解排查思路先看是不是GC频繁导致的CPU飙升如果是再确认是内存泄漏还是内存分配过大最后通过堆dump分析具体是哪个对象占用了内存。2.2 操作系统与网络系统底层决定上线高度操作系统考了进程和线程的区别、死锁产生的条件、进程间通信方式。这些题看着基础但绝对是筛选器。很多人觉得大数据开发不涉及操作系统其实完全相反。MapReduce的每个Task本质是一个JVM进程Spark Executor也是进程理解进程/线程模型才能理解分布式计算框架的资源调度。死锁的四个必要条件——互斥、持有并等待、不可剥夺、循环等待——这里有一个考试时容易漏答的点只有四个条件同时满足才会产生死锁破坏任意一个就能预防死锁。实际工作中Spark配置资源过大会导致集群资源分配不均严重时会产生类似死锁的问题任务A占用Executor 1等待Executor 2释放资源任务B占用Executor 2等待Executor 3形成等待环。虽然Spark的调度器有超时机制不会真正死锁但任务排队等待资源的现象本质上跟死锁的“循环等待”条件很相似。网络部分考了TCP三次握手、四次挥手以及为什么需要TIME_WAIT状态。大数据框架里处处都是网络通信理解这些才能理解为什么Kafka的连接数这么高为什么Spark Shuffle经常出现端口冲突。有一个细节特别值得说为什么TIME_WAIT要等2MSL因为要确保网络上所有延迟的数据包都能消失避免新的连接收到旧连接的数据包。在大数据场景下频繁创建连接会导致大量TIME_WAIT连接堆积这就是为什么很多大数据服务都需要调大本地端口范围、开启端口复用。2.3 数据库与SQL数据开发的基本功数据库部分考了B树索引底层原理、事务隔离级别、MVCC机制。这些也是大数据开发的必备知识。一个值得展开的点是SQL的执行顺序。笔试有一道题给了一张多表关联的SQL让大家写出优化方案。常见错误是直接加索引但如果你理解了SQL执行顺序FROM - ON - JOIN - WHERE - GROUP BY - HAVING - SELECT - DISTINCT - ORDER BY - LIMIT就会明白WHERE后面条件怎么写、子查询怎么改写会直接影响性能。在Hive里写SQL也是一样的道理。不要以为引擎帮你优化了就可以随便写。MapJoin、SMB Join这些机制都需要你在编写SQL时主动设计而不是指望优化器帮你解决一切。3. 大数据生态考点Hadoop核心与Spark原理到了这里才真正进入大数据开发的专业领域。网易这张卷子在Hadoop和Spark上的考察很有深度不是单纯问概念而是结合了实际工作中遇到的问题。3.1 HDFS写入流程详解笔试有一道题是描述HDFS写入文件的完整流程。这个考点基本上是大数据开发的必考题而且面试官后续一定会追问细节。HDFS写入流程简单概括是这样客户端调用DistributedFileSystem.create()方法向NameNode发送创建文件请求NameNode检查权限和目录是否存在返回可以创建的信息客户端开始写入第一个Block获取DataNode列表按照网络拓扑距离排序客户端以Packet为单位默认64KB往第一个DataNode写数据第一个DataNode写完一个Packet后通过Pipeline管道传给第二个DataNode第二个传给第三个实现副本的流水线式复制最后一个DataNode写完后逐级返回ack客户端收到所有ack后继续写下一个Packet所有Block写完后调用close()通知NameNode完成写入这里面值得展开的细节很多副本放置策略第一个副本放在客户端所在节点如果客户端不在集群内随机选一个节点第二个副本放在不同机架的节点第三个副本放在与第二个相同机架的不同节点。这种策略兼顾了可靠性不同机架容灾和写入性能跨机架传输只发生一次流水线复制为什么比链式复制快因为Packet写完后立刻传给下游不需要等整个Block写完相当于多级流水线并行为什么Packet大小是64KB而不是更大或更小太小会导致网络传输效率低太大则会导致内存占用过高、出错重传代价大。这个数值是工程权衡的结果笔试答题时最好画出时序图把每一步的数据流向标注清楚。这题答好了面试官对你分布式系统理解能力的印象分会高很多。3.2 MapReduce Shuffle机制与优化MapReduce是网易笔试的另一道重头戏。考的是Shuffle过程也就是MapReduce最核心、最容易出性能问题的环节。Shuffle可以拆成Map端和Reduce端来看Map端Map函数输出结果先写入环形缓冲区默认100MB缓冲区达到阈值默认80%后触发SpillSpill前会对数据进行分区Partition同一个分区的数据进入同一个Reducer分区内按键排序如果配置了Combiner会在排序后做一次本地聚合Spill生成的临时文件在Map结束时合并成一个大文件同样按键排序Reduce端Reduce Task启动后从Map Task拉取属于自己分区的数据拉取的数据先放内存缓冲区满了就合并到磁盘所有数据拉完后按键合并排序然后输入到Reduce函数考这个点的时候要理解为什么Shuffle是MapReduce的性能瓶颈因为数据要经过“内存写入 - 磁盘写入 - 网络传输 - 磁盘写入 - 内存写入”这个过程每一步都有开销。这也是为什么Spark选择尽量在内存做Shuffle、减少磁盘IO的原因。实际工作中遇到Shuffle性能问题一般的优化思路是增大环形缓冲区大小减少Spill次数开启Combiner减少数据传输量增加Reduce Task数量但要控制好过多会导致小文件问题使用压缩如Snappy减少网络传输3.3 Spark RDD依赖关系与Stage划分Spark的题目集中在RDD的窄依赖、宽依赖和Stage划分。这是Spark面试逃不掉的核心内容。宽窄依赖的判断标准是父RDD的每个分区被几个子RDD分区的使用。一对一或者一对固定多个NarrowDependency一个父分区被多个子分区使用可能被所有分区使用就是宽依赖。这里有一个容易混淆的点reduceByKey和groupByKey都是宽依赖但为什么reduceByKey的shuffle数据量更小因为reduceByKey在Map端先做了一次预聚合combine传输到下游的数据量大幅减少。而groupByKey是原样传输所有数据。我之前在调优时遇到过一个任务把groupByKey换成reduceByKey后运行时间从40分钟降到了8分钟效果极其显著。Stage划分的原则是遇到宽依赖就切断生成一个新的Stage。为什么因为宽依赖意味着下游的分区需要上游所有分区完整计算后才能运行这是一个天然的性能屏障。窄依赖则可以在同一个Stage内进行Pipeline计算多个算子在一个Task里顺序执行减少调度开销和中间数据落地。笔试有一道题给了一段Spark代码问会生成几个Stage。答题技巧是顺着RDD的转换链往下走遇到shuffle算子reduceByKey、groupByKey、join就Stage边界1。3.4 Kafka消息可靠性与消费语义Kafka在大数据生态里的地位不用多说网易这套卷子也考了。主要考点是如何保证消息不丢失以及at-least-once、at-most-once、exactly-once三者的区别。消息不丢失要分三个环节看Producer端设置acksall表示所有副本都写入成功才返回这样即使Leader副本宕机数据也已经同步到Follower副本不会丢Broker端设置replication.factor大于1通常3个副本ISR最少同步副本数为2同时禁止unclean leader选举关闭unclean.leader.election.enable避免ISR之外的节点被选为Leader导致数据丢失Consumer端关闭自动提交offset采用手动提交在业务逻辑处理完成后再提交offset。否则可能出现消费后业务逻辑还没执行完就提交了offset然后程序Crash重启后直接从新offset继续消费中间的消息就丢了exactly-once的语义是流处理中比较难实现的目标。Kafka通过事务API实现端到端的精确一次语义但这需要生产者开启enable.idempotence同时消费者配合事务性读取。在实际大数据开发中我见过很多团队标榜自己实现了exactly-once实际上只是at-least-once加上下游的幂等写入严格来讲并不是真正的精确一次。4. 场景设计题与代码题真正的区分度所在笔试的最后一道大题是场景设计题这类题没有标准答案考察的是你面对复杂问题时的拆解能力。这里没有标准答案但考察的能力模型非常清晰。4.1 数据仓库分层设计思路网易出了一道数据仓库分层的设计题给定一个电商平台的业务数据需要做用户行为分析如何设计数仓分层。数仓分层的经典结构是ODS层原始数据层存放原始日志和业务库数据保持和数据源一致DWD层明细数据层对ODS层的数据进行清洗、脱敏、维度退化构建明细事实表DWS层汇总数据层按主题用户、商品、商家进行轻度汇总形成宽表ADS层应用数据层面向具体业务需求的应用表如实时大屏、报表查询分层的核心价值是空间换时间。每一层都会产生重复数据但通过层层递进最终业务方查询时不需要接触原始数据响应速度快且逻辑清晰。这里有一个非常容易踩的坑ODS层不要做太多过滤尽量保留原始数据。因为业务需求是演进的你今天觉得没用的字段明天可能就要用了。如果ODS层就把字段过滤掉了后面补数据就是大工程。另外要特别注意分区策略。数仓表一般按天分区但大表要额外考虑按小时甚至按分钟分区否则某天数据量过大时查询性能会断崖式下降。分区粒度不是越细越好分区太多会导致小文件数量爆炸HDFS的NameNode压力剧增。4.2 大数据场景的算法题思路编程题考了一道TopK的问题从10亿个数中找出最大的1000个数。标准解法是使用堆维护一个大小为1000的最小堆遍历所有数据如果当前数大于堆顶就移除堆顶元素并插入当前数。遍历完成后堆里的1000个元素就是最大的1000个数。时间复杂度是O(n log k)空间复杂度是O(k)k1000。这道题的进阶版本是数据量太大单机内存放不下怎么办答案是把数据分片每台机器处理一部分每台机器输出局部TopK最后在汇总节点合并各机器的TopK得到全局TopK。这个思路和MapReduce的分而治之异曲同工分布式框架的底层思想在算法题里展现得淋漓尽致。还有一道题是两个有序数组合并要求时间复杂度O(mn)。这道题和MapReduce中多路归并排序的思路基本一致也是大数据框架中常见的底层操作。如果面试时你能联系到归并排序在Hadoop排序中的应用场景会给面试官留下很深的印象。4.3 代码题常见的考场陷阱网易这套笔试卷的代码题不算特别难但有几个考场常见的陷阱对输入的边界条件考虑不全比如数组为空、k等于0溢出问题比如int类型相加可能溢出需要用long空间复杂度的要求容易被忽略做题时务必先确认函数签名是什么、时间/空间复杂度限制是多少。不同限制条件下最优解可能完全不同。5. 那些年我们一起踩过的坑——常见问题与备考建议最后这部分我把自己在准备这类笔试时踩过的坑、以及带过的学弟学妹们经常犯的错误整理了一下算是给准备笔试的同学一份避坑指南。5.1 备考误区与避坑指南第一个误区是把大量时间花在背框架API上。Hadoop的Configuration怎么设置、Spark的某算子有几个参数这类问题笔试很少考考了也是送分题。真正拉开差距的是原理理解。比如你背了RDD有transformation和action两类算子不如真正理解一个action算子触发Job提交的完整链路。第二个误区是只刷题不思考。刷题的有效方式是每个考点先理解原理再做题验证然后总结同类题的答题模板。比如所有考HDFS写入的题答题框架都是“客户端 - NameNode - DataNode - 流水线复制 - 副本确认”框架搭建好之后再往里填细节答题效率和准确率都会高很多。第三个误区是忽视动手实操。大数据开发是工科活不亲手搭建一次集群你永远无法真正理解HDFS的副本机制。建议在本地用虚拟机或者Docker搭一套最小集群三个节点就够跑一个MapReduce或Spark示例观察日志和Web UI理解作业的执行流程。这个过程花不了太久但对原理理解的帮助远超刷十套卷。5.2 现场笔试的答题策略在校招笔试现场时间紧张不可能每道题都深入作答。我的建议是第一先做会做的题标记不确定的题最后统一回来处理。不要在一道题上纠结太久一道3分的客观题耗了15分钟后面10分的大题就没时间了。第二主观题和代码题即使不会也要写上你的思路。笔试题经常有部分给分哪怕只是写了一个暴力解法也比空着强。第三涉及系统设计的大题一定要先确定边界条件再展开。比如题目说“设计一个用户行为分析系统”你需要先问自己数据规模多大实时性要求如何存储选型是什么把这些基础约束明确了再往下做设计这样结构性会清晰很多。5.3 笔试之后的面试延展笔试只是第一关你答过的东西在面试里大概率会被问到。建议笔试结束后立即复盘所有不会的题把你写的所有答案都整理成笔记。面试官最喜欢做的事情就是顺着你笔试的答题思路追问如果你笔试时写了某个方案但面试时说不清楚这比笔试不会更让人失望。举个例子如果你在笔试中写了“用Kafka做消息缓冲”面试官可能会追问Kafka的瓶颈在哪里如果Broker宕机了怎么办消费者消费能力跟不上生产速度怎么办这时候如果你只停留在API使用层面回答起来就会非常吃力。我的建议是准备面试时每个考点至少向外延展两层。比如你准备HDFS写入流程第一层是理解写入流程图第二层是能解释为什么用流水线复制能说清楚如果DataNode中途宕机会触发什么机制答案是管线重建客户端会从写入管道中剔除故障节点并通知NameNode重新分配副本。能做到这个程度基本就不会被问倒了。
返回列表