ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

网易存储开发笔试题解析:底层基本功与系统级思维

网易存储开发笔试题解析:底层基本功与系统级思维 抱歉这份试卷并非公开可获取的实物我手头没有原题。不过咱们可以聊点更实在的以当年网易这套笔试题为引子结合这些年我在存储方向踩过的坑、带过的应届生聊聊云计算存储开发这个岗位到底考什么、为什么这么考以及怎么准备才能不白费功夫。先说结论这份卷子虽然挂在“存储开发”名下但它的考察范围一点都不窄。数据结构、操作系统、网络、数据库、分布式理论、Linux 基础、代码题全都有。如果你只盯着“存储”两个字基本会挂。更准确地说它考的是一名存储方向工程师的“底层基本功”外加一点分布式系统的直觉。下面我就按这套思路把当年的考点拆开揉碎了讲顺便告诉你哪些地方最容易翻车哪些地方值得花大力气。1. 试卷整体思路存储岗位到底想要什么样的人1.1 从岗位描述反推考察范围网易这套试卷的目标岗位是“云计算存储开发工程师”对应到实际业务大概率是去做对象存储、块存储、文件存储、KV 存储或者更底层的分布式存储引擎。这类岗位有一个共同点离系统底层非常近。这意味着你写的代码不是在业务层“调API”而是要在几毫秒内处理百万级并发读写要保证数据不丢、不错、不重还要在硬盘故障、网络分区、机器宕机时自动恢复。所以笔试不考框架怎么用也不考 Docker 怎么部署而是考“你在最底层的东西上有没有理解力”。结合当年题目分布我复盘下来大概是这么几块数据结构与算法数组、链表、哈希表、树、排序、字符串处理偶尔来一道动态规划或贪心。操作系统进程线程、内存管理、堆栈区别、虚拟内存、页面置换、锁与同步、死锁。网络TCP三次握手、四次挥手、滑动窗口、拥塞控制HTTP 基本语义偶尔考 socket 编程。数据库与存储索引原理B树、哈希索引、事务隔离级别、存储引擎差异、日志系统、缓存淘汰策略。分布式系统CAP 理论、一致性哈希、副本策略、数据一致性模型、分布式事务。编程题手写算法或者设计一个带并发控制的小型存储模块。看到没它其实不是在考“存储”而是在考“你能不能理解存储系统运行的整个环境”。1.2 为什么要考得这么杂你可能觉得“我就面个存储岗考我 TCP 拥塞控制和堆栈区别干嘛”这里有一个很实际的原因存储系统往往是整个技术栈里最容易出问题的部分而且出问题时排查链路往往横跨网络、OS、磁盘、数据库、分布式协议。举个例子。一个对象存储服务上游超时了你排查问题时先看网络发现 TCP 重传率异常再看应用层发现线程池打满接着看内核发现 Page Cache 压力大触发大量回写最后发现是某个存储节点磁盘 IO 延迟飙升。这一条链路下来网络、操作系统、存储、并发编程的知识全都用上了。如果笔试只考“哈希表怎么实现”根本筛不出能扛住这种问题的人。所以这套卷子的出题逻辑是用看似分散的知识点筛掉那些只会背八股文、却不懂系统联动的人。它真正想找的是那些具备“系统级思维”的候选人。这个点后面每个章节我都会反复提到因为它是你答题时的核心思路。2. 操作系统与底层基础绕不开的存根功课2.1 堆栈和内存管理的常见坑“堆栈”这个词在面试里几乎必考但很多人其实没弄清楚。网上有一堆文章讲“堆是动态分配、栈是自动分配”这没错但停留在表面。真正笔试爱考的是这三点第一栈为什么快。栈的分配本质上就是移动一下栈指针几乎零开销而堆分配需要走 malloc 或 new涉及空闲链表查找、内存碎片整理、系统调用brk/mmap等开销大且不可控。这也是为什么存储引擎里大量使用内存池和对象池而不是频繁 new 对象。第二栈大小有限。比如 Linux 默认栈大小通常为 8MBulimit -s 可查递归写太深就爆栈。笔试可能会让你判断一段递归代码是否栈溢出或者让你优化一个递归算法。核心思路只有两个改循环或者手动模拟栈。后者更常见于存储引擎的迭代器实现比如 B树遍历就是显式维护一个栈结构。第三虚拟内存与缺页中断。存储场景里最常见的问题之一是“内存明明还有为什么用的内存不够”或“进程 RSS 很大为什么虚拟内存更大”。这背后是虚拟内存与物理内存的映射关系。笔试题如果问“一个进程 malloc 了 1GB 内存但只写了 10MB物理内存占用多少”答案不是 1GB也不是 10MB而是“写了脏页的 10MB 左右”并且这些页是按需分配进来的。存储引擎里很多内存参数调优比如 MySQL 的 innodb_buffer_pool_size如果不理解缺页就会调出问题来。2.2 页面置换算法笔试只是开始工程才是真考验页面置换几乎是操作系统必考题但笔试只考概念太简单了网易当年更倾向于考“结合场景选算法”。比如这样一道题“一个存储引擎需要缓存 100 万个 KV 对读写比例 8:2热点数据约占 20%你会用 FIFO、LRU 还是 LFU为什么”标准答案思路是FIFO 会淘汰掉仍在高频访问的热数据而且存在 Belady 异常实际工程中基本不用。LRU 适合时间局部性明显的场景实现简单哈希表双向链表但如果数据是扫描型访问比如一次性全表扫描LRU 会被“刷掉”热数据。LFU 适合频率分布不均的场景能抗住扫描型访问但实现复杂要维护频率计数还要处理“旧热点不冷”的问题。真正的工程实现比我上面写的还要细。比如 Redis 的近似 LRU、Memcached 的 LRU 分桶、RocksDB 的 Bloom Filter 与 LRU 配合使用都是笔试之外的内容。但你在笔试里如果能答出“LRU 会被扫描型访问污染所以很多存储系统用 LRU 变体或分段策略”这套题基本就拿下了。我建议你不仅会背概念还要能手写一个 O(1) 的 LRU哈希表 双向链表。这几乎是存储/后端岗位编程题的“保留节目”跑不掉。2.3 文件系统与磁盘 I/O从 inode 到 Page Cache存储开发岗位对文件系统的理解要求比普通后端高得多。笔试里常问的点有这几个inode 是什么硬链接和软链接的区别Page Cache 的作用mmap 和 read/write 的差异inode 这一题很多人的回答是“inode 是索引节点存文件的元数据”这不够。你看一个文件的内容实际要经过“文件名 - 目录项 - inode - 数据块”的过程。inode 里存放的是文件大小、权限、时间戳、数据块指针直接、间接、双重间接但不存文件名。笔试如果给你一张图让你标出这个流程别画错就行。软链接存的是另一个文件的路径硬链接则是多个名字指向同一个 inode硬链接不能跨文件系统也不能指向目录。Page Cache 和 mmap 是更进阶的考点也是真正区分“死记硬背”和“理解力”的地方。简单说Page Cache 是内核把磁盘数据缓存到内存的一种机制读文件时优先走缓存写文件时先写缓存再异步刷盘。mmap 则是把文件映射到进程地址空间读写操作直接操作内存省去了 read/write 的系统调用和用户态内核态拷贝性能更好但也带来一个问题——进程崩溃时脏页可能还没刷盘数据容易丢。存储引擎之间的取舍很有意思RocksDB 默认用 mmap 做只读操作但写路径尽量走 pwrite 以控制丢数据风险。这类题如果你从“存储系统设计需要考虑崩溃一致性”的角度去回答就比干巴巴背概念要加分得多。笔试不是让你背概念是让你展示“我知道为什么这么设计”。3. 数据库与分布式存储从 B 树到一致性哈希3.1 索引原理B 树、哈希索引与 LSM-Tree存储岗笔试最容易出彩的地方就是把索引这块答深了。很多同学背了一堆“B树叶子节点存储数据、磁盘友好”但一问到细节就露馅。先说最基础的为什么 MySQL InnoDB 用 B 树而不是 B 树或红黑树答案是磁盘 IO。B树的所有数据都存在叶子节点并且叶子节点之间有链表相连范围扫描时顺序访问叶子链表磁盘预读友好而 B 树的数据分散在所有节点中序遍历会跳来跳去产生大量随机 IO。红黑树是二叉树高度太高放磁盘上要访问太多次节点。二叉树只适合内存场景比如 C 的 std::map。哈希索引呢你去看 MySQL 的 Memory 引擎或者 Redis 的哈希结构它只支持等值查询不支持范围查询。哈希索引查找是 O(1) 复杂度但一旦范围扫描就全表扫描所以 OLTP 场景很少单独用哈希索引而是用 B树或 LSM-Tree。LSM-Tree 是分布式存储和 NoSQL 场景绕不开的话题。很多考生一听到 LSM 就紧张其实核心就三句话写操作先写内存MemTable达到阈值后转成不可变的 SSTable 刷到磁盘读的时候先查内存再查磁盘用 Bloom Filter 加速判断数据是否存在后台定期做 Compaction把多个 SSTable 合并清理无效数据。基于这个思路LevelDB、RocksDB、Cassandra、HBase 的底层都说得通。笔试如果问“为什么很多分布式数据库用 LSM-Tree 而不是 B树”你要答出两点写放大问题。B树是原地更新随机写需要大量磁盘寻道而 LSM-Tree 是顺序写写性能高很多。代价是什么读放大和空间放大读取可能要跨多个 SSTable 查询后台 Compaction 还会带来额外 IO 开销。存储岗笔试题考到这里其实已经进入半设计题范畴了。你能把 B树、哈希索引、LSM-Tree 放在同一个维度下对比说明你是真理解了存储引擎的取舍。3.2 事务、隔离级别与 MVCC不要只会背名字数据库事务的 ACID 四大特性属于必背但网易这套卷子考的从来不是“ACID 是什么”而是“某个隔离级别下这个操作会发生什么”。举个例子。MySQL 默认隔离级别是 Repeatable Read很多人会问“RR 是不是就完全不存在幻读了”答案是否定的。在 InnoDB 中RR 下普通 SELECT 使用快照读通过 MVCC 机制避免幻读但如果使用 SELECT ... FOR UPDATE 或 UPDATE 这类当前读依然可能读到其他事务新提交的数据出现幻读现象。这个点笔试经常出案例题比如“事务 A 先查询了 id5 的记录事务 B 插入了 id6 的记录并提交事务 A 再次 SELECT COUNT(*) 会得到什么结果”不会 MVCC 的人基本就晕了。MVCC 的核心是版本链和 ReadView。InnoDB 每一行都有隐藏列 trx_id最后修改该行的事务 ID和 roll_pointer指向 undo log 版本链。生成 ReadView 时会把当前活跃事务 ID 列表记录下来查询时按照可见性算法逐版本判断。这里面有几个判断条件比如 trx_id 是否小于 min_id、是否在活跃列表里、是否大于 max_id笔试不一定会让你手写但你要能画出版本链说明哪个版本对当前事务可见。分布式事务的考点更倾向概念级。比如分布式事务的几种方案两阶段提交2PC、三阶段提交3PC、本地消息表、TCC、Saga。我见过大多数候选人能把 2PC 的两个阶段说出来但问到“2PC 协调者挂了怎么办”“3PC 为什么比 2PC 好”就卡壳。这个在笔试里一般是简答题或场景题不会特别深但答不出协调者故障恢复机制会减分。3.3 分布式存储架构CAP 不是让你背定理CAP 理论被问烂了但多数人只会背“一致性、可用性、分区容错性三选二”。这套卷子如果只考这种题那也太没区分度了。真正有区分度的是场景题。比如“你设计一个对象存储系统客户端写入一个对象数据需要跨三个机房冗余存储。当两个机房之间网络抖动时这个写请求应该返回成功还是失败为什么”这道题考察的就是你对 CAP 在真实系统里的理解。正确的思路是对象存储的核心诉求是“只要返回成功数据就必须可靠存储”所以优先保证一致性C和分区容错性P在极端网络分区时可能会短暂不可用A。这是大多数对象存储如 AWS S3 的强一致模型的默认策略。再比如一致性哈希。笔试会给你几个节点和几个 key让你计算 key 应该落在哪个节点上。这道题不难但如果你只按照顺时针找最近的节点会遇到一个经典问题节点比较少时数据分布严重不均。解决方案是给每个物理节点加一圈虚拟节点比如每个物理节点有 100~200 个虚拟节点key 落在虚拟节点上后再映射到物理节点。加虚拟节点之前哈希环上节点少的数据分布方差非常大加完之后基本能保证每个节点的数据量和负载相对均匀。笔试如果问“为什么一致性哈希要引入虚拟节点”核心答案就四个字负载均衡。还有副本策略。一个分布式存储系统的数据通常有 3 副本写入时可以采用同步写三副本都写完才返回或异步写主副本写完就返回后台同步到其他副本。同步写数据更可靠但写延迟更高异步写性能好但主副本宕机时可能丢数据。绝大多数云厂商的存储服务默认是同步写因为“数据不丢”是存储系统的底线。你答这个点的时候如果能说出“同步写能保证 RPO0”就说明你真懂。4. 网络与编程能力大多数候选人折戟的地方4.1 TCP/IP 知识不只是三次握手网络部分的题网易这套卷子喜欢从“应用层故障排查”角度切入而不是让你背协议状态机。举个例子它可能会问“一个存储服务的客户端连接经常出现大量 TIME_WAIT这可能是什么原因怎么优化”TIME_WAIT 是 TCP 四次挥手中主动关闭方进入的状态持续 2MSL约 1~2 分钟。大量 TIME_WAIT 一般意味着服务端主动关闭了大量连接常见场景是短连接请求过多。优化方案包括改用连接池复用连接、开启 tcp_tw_reuse、调整 tcp_fin_timeout 等。但在分布式存储里我的建议是优先搞连接池因为 TIME_WAIT 只是表象更深的含义是你在频繁地建连和断连而每一次建连都有 TCP 和 TLS 的开销积少成多是性能杀手。拥塞控制也是一个常考难点。慢启动、拥塞避免、快重传、快恢复这些名词大家都背得下来但笔试真正想考的可能是“为什么 TCP 要避免队头阻塞”“为什么数据中心网络里 TCP 性能往往不好”这里可以讲的点非常多TCP 的可靠传输依赖序号和确认重传但一旦有包丢失后续包即使到达也只能排着队等重传这就是队头阻塞。在分布式存储里一个底层存储节点的 TCP 超时重传可能导致上层请求批量失败进而引发雪崩所以很多存储系统会用多路复用、连接池隔离、超时熔断等方式来缓解。4.2 编程题从手写 LRU 到并发设计编程题是笔试的压轴戏也是最拉开差距的地方。网易这套卷子的编程题不会特别偏怪但很贴近存储场景常见的有以下几类手写 LRU Cache。前面已经提到这是高频题。要求 get 和 put 操作都是 O(1) 时间复杂度推荐用 unordered_map 双向链表实现。关键注意点链表的头尾要处理好node 在 get 时会被移动到头部容量满时要删除尾部节点同时删除哈希表里的条目。很多人在删除尾部时忘了同步删除哈希表里的键导致内存泄漏或者逻辑错误写代码的时候一定要把“链表的删除”和“哈希表的删除”这两个动作关联起来。线程安全的单例模式。存储引擎里有很多全局的资源管理器比如连接池、缓存池都需要线程安全单例。C 里推荐用 Meyers Singleton局部静态变量Java 里推荐枚举单例或双重检查锁。笔试如果让你手写双重检查锁要注意 volatile 关键字Java或 atomic 并发原语C防止指令重排导致拿到未完全构造的对象。TopK 问题。存储系统里经常要统计“访问最频繁的 Top 100 个 key”笔试可能让你实现一个类或者写出思路。常见解法小顶堆堆大小为 K 哈希表计数。如果数据量极大可以用“哈希分桶 每桶内堆排序”的分布式思想这就有存储系统的味道了。答出后面这种思路绝对加分。另外还有一种设计题比如“设计一个线程安全的无锁队列”或“实现一个支持过期时间的 KV 缓存”。这类题不一定要写出完整代码但你要能画出数据结构并讲清楚并发控制方式。如果设计里还提到“使用环形缓冲区分担生产者消费者压力”“用 CAS 代替互斥锁”面试官会觉得你确实了解存储系统里的工程细节。4.3 避坑清单笔试中容易丢分的细节概念混淆是笔试丢分的重灾区。我在带人和改卷时见过太多这样的案例把硬链接和软链接搞反、把 GET 和 POST 幂等性说错、把线程和进程的地址空间关系说反、在“LRU 与 LFU 的淘汰策略”上张冠李戴。这些其实都还属于基础题丢分很可惜。还有一类错误是答题格式的问题。简答题里只写关键词不写逻辑或者只写代码不写思路都会被扣分。正确的做法是“结论先行然后给理由”比如“我会用 B 树因为它对磁盘顺序 IO 友好并且天然支持范围查询下面是具体分析。”这种总分总结构在笔试里特别占优势。5. 备考路径与考场策略照着做就行5.1 从零到 Offer一套可以复制的复习路线结合这套卷子和这些年我带校招生的经验我建议备考周期至少安排 2~3 个月分三个阶段走。第一个阶段约三周打基础。把操作系统、计算机网络、数据库这几门课的核心概念过一遍重点是理解“为什么”不是背定义。比如 TCP 三次握手你不仅要能画出状态图还要能解释“为什么不是两次或四次”再比如 B树不仅要记住叶子节点存数据还要理解磁盘预读和页大小4KB/16KB的关系。第二个阶段约三周刷题和写代码。代码题主要刷 LeetCode 的 Top 100 高频题加上存储场景相关的经典题LRU、线程安全单例、TopK。这个阶段除了刷题还要花时间把数据结构里的树、哈希、堆这些基础结构用 C 或 Java 手写一遍写熟了笔试会很有底气。第三个阶段约两周做系统设计题和模拟笔试。你可以去找一些公开的存储笔试/面试题做总结比如“设计一个分布式 KV 存储”“设计一个对象存储系统”“MySQL 主从同步延迟怎么排查”。每道题都按“需求分析 - 模块设计 - 数据模型 - 一致性协议 - 故障处理”这个框架去答练习表达逻辑。模拟笔试的意义在于训练时间分配比如 120 分钟做完 40 道选择题加 3 道大题你要提前找到自己的节奏。5.2 考场策略先拿保底分再冲附加分笔试不是竞赛它更像“过线考试”。你要做的第一件事是确保基础题全对然后再去挑战困难题。我的习惯顺序是先快速浏览一遍所有题目标记出不确定的题然后按“选择题 - 简答题 - 编程题”的顺序作答编程题先写思路注释再写代码最后再写测试用例确保评分老师能看懂我的逻辑。选择题的陷阱主要藏在“绝对化表述”里比如“LRU 一定优于 FIFO”“B树一定比哈希索引快”这种说法基本是错的因为算法优劣取决于场景。简答题尽量写小标题或分点别写一大段让人找不到重点。编程题如果时间不够只写伪代码也比空着强但最好搭一个可运行的结构哪怕边界条件没处理完也能拿到不少分。5.3 复盘方法每次做错题都是赚到笔试结束后很多人对完答案就扔了这很浪费。我自己带的小朋友里进步最快的都有一个共同习惯做错题复盘。复盘不是把正确答案抄一遍就完了而是问自己三个问题这道题考的是哪个知识点我当初为什么没想到下一次遇到类似题我的判断依据应该是什么比如你错了一道“为什么 InnoDB 选择 B树”的选择题复盘时不能只背“叶子节点存数据”而要把整条因果链理清楚“数据量大 - 需要减少磁盘 IO - 希望树高度低且顺序访问友好 - B树高度约 3~4、叶子链表支持范围扫描 - 所以选择 B树”。下次如果改成“为什么 Redis 用跳表实现有序集合”你也能举一反三地答出 ZSet 需要“插入、删除、范围查询都高效且实现比红黑树简单”。另外很多同学忽略了人脉的作用。笔试之余如果有人能帮你内推或者给你看看往年的面经你准备起来会少走很多弯路。我当年在牛客、GitHub 上都收藏过不少分布式存储相关的面经合集自己也会整理一份“存储开发面试题库”比漫无目的地刷题效率高得多。说在最后回到开头那个问题网易这套笔试卷表面考的是知识点本质考的是“你有没有系统级思维”。存储系统是云的基石它要求你在面对问题时能同时想到操作系统、网络、数据库、分布式协议四个层面。这套卷子看起来杂实际上是在帮团队筛选具备这种思维的人。如果你正在准备类似岗位我的建议是别焦虑题多先吃透底层原理再刷几道典型代码题最后靠模拟笔试题练出手感。这个过程走完不管是网易还是别家你都会比大多数候选人更有底气。我个人在带人时最看重的一点是遇到没见过的题能不能冷静地从“它想考我什么”出发去拆解。这一点你在准备笔试的过程中真的可以练出来。
返回列表