1. 从一份滴滴运维开发笔试题说起
每年秋招季,总有一批岗位名字看着熟悉、实则陌生,运维开发工程师就是典型代表。很多同学投简历时以为是“运维”,结果打开笔试系统发现要写代码、查网络、分析数据库索引、设计监控系统,直接愣住。我当时看滴滴出行2018校园招聘网申笔试-运维开发工程师(第一套)这套题时,最大的感受就是:它不像在考知识点,更像在考“你有没有真正在线上环境里处理过问题”。这套卷子对网络、Linux、数据库、脚本语言、监控体系、故障排查几乎全覆盖,而且很多题目不是背八股能答出来的,需要真的理解原理。
这篇文章我会把这套笔试题的题型结构、核心考点、典型题目拆开揉碎讲一遍,并给出我当年备考和实际工作中的解题思路、避坑经验。不管你是想投运维开发岗,还是想系统梳理自己的工程能力,这套题都值得认真过一遍。文章不涉及具体题目答案的搬运,而是把“这类题背后的考察意图和知识点”讲透,方便你举一反三。
2. 运维开发岗笔试到底在考察什么
2.1 岗位定位:不是纯运维,也不是纯开发
先解决一个根本问题:运维开发(DevOps Engineer / SRE方向)和传统运维有什么区别?传统运维的核心是“确保系统不出事”,重心在巡检、变更、扩容、备份等日常操作,脚本能力属于锦上添花。而运维开发的核心是“用开发手段解决运维问题”,你得把重复的人工操作变成自动化的平台、工具、流水线,把“事后救火”变成“事前预防”。
所以笔试时,出题人考察的不是你会不会敲命令,而是你有没有能力把运维经验“代码化”。这套滴滴笔试题最能体现这一点:它既考网络原理、Linux基础这类运维硬功夫,又考Python/Shell脚本、算法思路、系统设计这类开发能力。换句话说,你得是“两条腿走路”的人。
2.2 校招笔试的典型题型分布
从我见过的大厂运维开发笔试题来看,题型分布通常比较固定。滴滴这套题基本代表了主流风格:
| 知识领域 | 常见题型 | 考察能力 |
|---|---|---|
| 计算机网络 | 选择题、简答 | 协议细节、故障排查基础 |
| Linux系统 | 选择题、命令分析 | 系统管理、性能分析 |
| 数据库 | SQL题、索引分析 | 数据处理、优化能力 |
| 脚本编程 | Python/Shell编程题 | 自动化能力、编码基本功 |
| 监控与架构 | 场景设计题 | 全局视野、架构思维 |
| 算法与数据结构 | 编程题 | 逻辑思维、coding能力 |
| 开放性问题 | 案例分析 | 问题定位思路、沟通表达 |
这套题的总体风格偏工程实践,很多题目给出的都是线上真实场景的简化版。比如会给你一个“服务响应变慢”的现场,让你列出排查思路,而不是直接问“CPU负载高怎么办”。这两者有本质区别:前者考的是排查路径和优先级判断,后者考的是孤立的知识点记忆。
3. 计算机网络题目拆解:必考的硬骨头
3.1 高频考点:三次握手、四次挥手、TCP状态变迁
网络部分基本是每套运维开发笔试题的“开场菜”。滴滴这套题里,TCP相关的内容占比不低,而且考法比较细。比如“TCP连接建立过程中,客户端最后进入的状态是什么?”这种题,如果只背过“三次握手”四个字,见到详细的SYN_SENT、ESTABLISHED、SYN_RCVD这些状态就直接懵。
我的建议是,不要只背结论,要把状态流转图画在自己脑子里。三次握手本质是“双方确认收发能力”的过程:客户端发SYN进入SYN_SENT,服务端收到后回SYN+ACK并进入SYN_RCVD,客户端收到后进入ESTABLISHED并回ACK,服务端收到ACK后也进入ESTABLISHED。四次挥手则是因为TCP连接是全双工的,每一方向的关闭都需要单独的FIN和ACK,所以才有四次交互,以及TIME_WAIT状态。
这里我特别想提醒一个点:TIME_WAIT是校招笔试题里的“钉子户”。很多同学只知道“主动关闭方会进入TIME_WAIT”,但不知道为什么是2MSL。如果从工程角度理解:一来保证最后一个ACK能重传,避免对端收不到;二来让旧连接的报文在网络中消散,避免影响新连接。理解了原因,再遇到“大量TIME_WAIT怎么处理”的问题,你才能答出内核参数调优思路,而不是背一堆sysctl命令。
3.2 常见陷阱题:HTTP与TCP的关系
这套题里出现的另一个典型考法是“浏览器输入URL后发生了什么”。这题看起来像送分题,其实坑很多,因为它涉及DNS解析、TCP连接、HTTP请求封装、服务端处理、响应返回、浏览器渲染等多个环节。很多同学答得乱,是因为没有分层的概念。
我推荐使用“分层讲述法”:先讲应用层(HTTP请求的URL解析、DNS查域名),再讲传输层(TCP建立连接),再讲网络层(IP寻址路由),最后讲链路层和物理层(ARP、MAC帧)。这样结构清晰,而且面试官或阅卷人一眼就能看出你脑子里的网络模型是成体系的。运维开发场景下,还需要额外提一嘴“如果服务端在Nginx后面,经过了几层代理”,因为线上业务往往不是直连,而是经过LVS、Nginx、网关等多层跳转。
3.3 排查型网络题:故障定位思路比答案重要
滴滴这套题里有相当一部分网络题不是概念题,而是“场景题”。比如:用户在某个时段反馈App加载很慢,你怎么排查?这类题目其实没有标准答案,但如果你的回答只写了“ping一下服务器”,那基本就丢了分。
我的答题框架是“从外到内、逐层排除”:
- 先分客户端还是服务端问题:看监控,如果所有用户都慢,就不是个别客户端的问题;如果只有某个地区慢,考虑运营商链路或CDN节点。
- 看基础连通性:ping测丢包率和延迟,确认网络链路是否有问题。
- 看TCP连接建立延时:如果connect耗时高,可能是有丢包重传;如果连接建立正常但响应慢,问题可能在后端。
- 看服务端入口:Nginx或网关的access log里看响应耗时分布,区分是网络耗时还是应用处理耗时。
- 深入应用层:查数据库慢查询、缓存命中率、依赖的外部服务响应时间。
这个思路可以套用在绝大多数线上故障排查场景里。笔试时把“排查顺序”和“每一步的判定依据”写清楚,即使没给出最终答案,阅卷人也能看出你有实战思维。
4. Linux与系统知识:运维的基本盘
4.1 高频命令和它们背后的原理
Linux题在这套笔试题里占了相当比例,考法也很直接:给一个实际问题,让你选命令或解释输出。比如“如何查看系统平均负载?”“如何查看某个端口被哪个进程占用?”“如何查看磁盘IO使用情况?”这类问题看起来简单,但坑藏在细节里。
以“查看系统负载”为例,很多同学张口就是uptime、top,这没错。但笔试题可能会问“load average的三个数值分别代表什么?”这时候就得知道,它们是1分钟、5分钟、15分钟的平均活跃进程数,而且这个数值要和CPU核数对比才有意义。如果load average是4,而机器是2核,说明系统可能处于过载状态;如果是8核,则还算健康。这是很多没真正看过线上机器的同学容易忽略的点。
再比如“如何查看端口占用”,netstat -tlnp和ss -tlnp都能用,但要理解:ss是netstat的替代品,性能更好,因为它直接读取内核socket信息而不是遍历/proc。笔试中如果能主动说明“用ss而不是netstat,因为连接数大时netstat会卡”,这就是加分项,因为体现的不只是命令记忆,而是对工具选型的思考。
4.2 性能分析:从top到vmstat、iostat、sar的组合拳
这套笔试题里有一类典型题:机器CPU使用率很高,你怎么定位是哪个进程、哪段代码导致的?这个问题如果只答“用top看”,只能算及格。完整的定位链应该这样:
先用top或htop看整体负载和CPU消耗TOP进程,然后记住CPU时间的组成——us(用户态)、sy(系统态)、wa(IO等待)、id(空闲)、st(被虚拟机偷走)。如果us很高,说明是计算密集,进一步用perf或火焰图看热点函数;如果sy很高,说明系统调用频繁,要查是不是上下文切换过多;如果wa很高,那CPU在等磁盘IO,问题根源在存储层。
这里我强烈建议备考的同学把vmstat和iostat的输出项背熟,尤其是:r(运行队列)、b(阻塞进程数)、si/so(换入换出)、await(IO平均等待)、util(设备利用率)。因为运维开发的日常工作就是和这些指标打交道,“看指标说结论”是基本功。笔试中出现vmstat输出让你解读的题目,其实就是在考你线上排障的基本功。
4.3 系统调优题:不是背参数,而是理解场景
滴滴这套笔试题里有一类开放性题目,比如“高并发短连接场景下,如何优化系统?”这类题的切入点是:短连接意味着频繁的TCP建连和断连,服务器会积累大量TIME_WAIT连接,可能耗尽端口或内存。要答好这题,你不仅要回答修改内核参数(net.ipv4.tcp_tw_reuse、tcp_fin_timeout等),还要说明每个参数为什么有效、有什么副作用。
以tcp_tw_reuse为例,它允许客户端在TIME_WAIT状态下重用连接,减少端口占用,但前提是开启timestamps且主要对客户端生效。如果只背参数不考虑场景,很容易在面试追问时露馅。我的建议是,把常见内核参数按“连接层、文件层、内存层”分类整理,每个参数配套一个适用场景和副作用说明,这样遇到任何调优题都能有条理地组织答案。
5. 数据库部分:索引与SQL优化是重头戏
5.1 索引失效的经典场景
数据库题目在运维开发笔试中从来不会缺席,而且MySQL是绝对主流。滴滴这套题里,典型的考察方式是给一条SQL语句,问它是否走索引、为什么慢。这类题的核心就是“索引失效场景”的掌握程度。
我整理过一份索引失效的高频场景清单,笔试前值得反复过:
- 对索引列使用了函数或计算,例如WHERE YEAR(create_time)=2024,索引直接失效,正确写法是范围查询。
- 隐式类型转换,例如索引列是varchar,但查询条件是数字,MySQL会隐式转换掉索引。
- 前导模糊查询,LIKE '%关键字' 无法走索引,但LIKE '关键字%' 可以(前提是排序规则支持)。
- 联合索引不满足最左前缀原则。
- 用OR连接的条件中,如果只有一个字段有索引,整个查询可能全表扫描。
我在实际业务里最常踩的坑是隐式类型转换。曾经排查过一条线上慢查询,SQL执行要2秒多,explain一看是全表扫描,最后定位到问题是查询参数是string类型,但表字段是bigint,走了隐式转换导致索引失效。这个场景出现在笔试里的话,如果你能举出类似的实战案例,会非常有说服力。
5.2 慢查询分析与explain解读
“线上有一条SQL执行很慢,你怎么排查?”这几乎是运维开发笔试的必考题。这道题的本质是考察你是否能系统化地使用慢查询日志和explain工具,而不是靠猜。我的标准答题流程是:
第一步,在MySQL中开启慢查询日志(long_query_time设为1秒甚至更低),拿到慢SQL。这一步在线上环境要谨慎,注意磁盘空间和性能影响。 第二步,用EXPLAIN分析执行计划,重点看几个字段:type(访问类型,从好到坏依次是const、eq_ref、ref、range、index、ALL)、key(实际使用的索引)、rows(预估扫描行数)、Extra(是否有Using filesort、Using temporary等)。
这里特别提示一个初级工程师容易忽略的点:rows预估行数和实际执行消耗不一定完全一致,但“ALL”和“Using filesort”同时出现时,基本可以断定这条SQL需要优化。笔试中如果能把这个判断逻辑说清楚,比单纯背字段含义要强很多。
5.3 SQL题:手写正确语法是底线
这套题里还包含手写SQL的题目,通常是多表关联查询或带条件的统计查询。这类题没什么捷径,就是平时多写多练。比如“统计每个城市的订单量,按订单量降序排列,只显示订单量大于100的城市”,这类SQL看似简单,但要注意GROUP BY、HAVING、ORDER BY的使用顺序,很多同学会把WHERE和HAVING搞混。
再延伸一下:如果表数据量很大,这个统计查询怎么优化?这就涉及“预聚合”或“定时汇总表”的思路,属于运维开发较高级的话题。笔试时如果能把这类优化思路写出来,能让阅卷人看到你有大数据量场景的意识。
6. 编程与脚本题:运维开发的分水岭
6.1 Python还是Shell:按场景选
编程题是运维开发笔试和传统运维笔试最大的区别。滴滴这套题中,编程部分以Python为主,也涉及Shell脚本。很多同学会问:备考时到底重点准备哪个?我的经验是:Shell处理文本和系统命令场景,Python处理复杂逻辑和数据处理场景。笔试中“读取日志文件,统计每个IP的出现次数,按次数从高到低排序输出”这类题,用Shell的awk一行就能搞定,用Python写也不难。但如果题目变成“解析JSON格式的日志并筛选特定字段”,Shell就力不从心了,Python的json模块才是正解。
所以备考时不要只盯一门语言,而是把两者结合。Shell不擅长的是复杂数据结构、正则处理、多级嵌套逻辑;Python不擅长的是快速调系统命令、管道处理大文件。校招笔试一般不会要求你写极其复杂的脚本,但基础字符串处理、文件操作、正则表达式、循环判断必须做到随手能写。
6.2 一段参考代码:日志IP统计
我来给一道典型的笔试编程题示例,这类题在滴滴的笔试里出现过类似版本:给定一个nginx日志文件access.log,每行包含客户端IP等字段,统计每个IP出现的次数,输出出现次数最多的前10个IP及次数。用Python写大概是这样:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from collections import Counter ip_counter = Counter() with open('access.log', 'r', encoding='utf-8') as f: for line in f: # nginx 日志中 IP 通常是第一列,用 split 取第一个字段即可 ip = line.split()[0] ip_counter[ip] += 1 for ip, count in ip_counter.most_common(10): print(f"{ip}\t{count}")如果日志格式复杂(比如IP不在第一列),可以改用正则表达式:
import re from collections import Counter pattern = re.compile(r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b') ip_counter = Counter() with open('access.log', 'r', encoding='utf-8') as f: for line in f: match = pattern.search(line) if match: ip_counter[match.group()] += 1写代码时有两个细节要注意:一是用Counter和most_common能简化代码且性能不错;二是要处理空行和异常格式,保证脚本健壮。笔试时如果时间充裕,建议额外考虑“如果日志文件超大(几个GB)怎么办”的优化方案,比如分块读取、用外部排序等,这类延伸思考能体现工程意识。
6.3 编程题的评分点:不只是能跑
很多同学以为编程题“跑过测试用例”就万事大吉,其实大厂的笔试系统大多是按多个用例分批评分的。这意味着,边界条件和异常输入处理往往决定了你能拿多少分。比如上述日志统计题,如果日志文件不存在怎么办?文件里有空白行怎么办?IP格式非法怎么办?这些处理逻辑本身就是加分项。
另外,代码风格也是隐性评分点。Python代码要符合PEP8习惯,变量命名要见名知意,函数要拆分清晰,不要把所有逻辑堆在main里。运维开发的代码以后是要给团队维护的,如果你在笔试中展示出良好的编码习惯,会留下非常正面的印象。
7. 监控、自动化与架构设计:拉开分差的场景题
7.1 监控体系设计:从采集到告警
如果说前面的选择题考察的是知识广度,那后面的大题就是考察你的系统设计能力。滴滴这类体量的公司,线上服务器数量巨大,服务链路复杂,监控体系是运维开发的“脸面”。笔试中常见的题目是:“请设计一个监控系统,能实时掌握线上服务的健康状态,并在异常时通知相关人员。”
这类题没有标准答案,但有一个答题框架值得参考:数据采集层 + 数据存储层 + 告警计算层 + 通知触达层。数据采集层要说明用什么方式采集指标(Pull还是Push)、采集哪些指标(CPU、内存、磁盘、IO、网络、应用QPS、延迟、错误率、日志关键字等)、采集频率是多少。数据存储层要考虑时序数据库(如Prometheus生态的TSDB),指标保留策略,聚合维度。告警计算层要说明告警规则的配置方式(基于阈值、基于环比、基于多条件组合),以及如何避免告警风暴。通知触达层则要回答“通过什么渠道通知,怎么分级,怎么升级,谁来响应”。
我在笔试答题时的一个技巧是:每说一个模块,就顺带提一个实际场景。比如谈到告警规则,可以举“请求量在凌晨峰值时段波动较大,用固定阈值会产生大量误报,所以采用动态基线算法”为例。这种细节会让答案更丰满,也更有说服力。
7.2 自动化与DevOps流程题:从代码到上线
另一种常见的场景题是:“描述一下一个完整的持续集成和持续发布流程。”这道题考察的是你对DevOps全链路的理解。我的习惯是“从左到右按阶段讲”:代码提交触发CI流水线,先跑单元测试和代码规范检查;通过后构建镜像,推送到镜像仓库;然后走CD流水线,先部署到测试环境,跑集成测试;通过后审批进入预发环境;最终发布到生产环境,并按批次灰度,观察监控指标。
这里有一个容易被忽略的点:你在描述流程时必须说明“每个阶段的卡点是什么”。比如单元测试失败则终止流水线,镜像漏洞扫描不通过则不能推送,灰度发布时如果错误率上升则自动回滚等。这些卡点就是所谓“质量门禁”,是DevOps体系里最核心的工程实践,也是大厂运维开发日常工作中真正在建设的东西。
7.3 一个反直觉的设计题:如何做到高可用
滴滴的笔试中还有一类“高可用设计”题,比如:“一个核心服务需要做到全年可用性99.99%,你会从哪些方面设计?”这类题考的是系统性的思维,答题时我会分几个层面来展开:
- 冗余层面:服务多实例部署、多可用区部署、数据库主从和跨机房容灾。
- 负载均衡层面:入口层用DNS轮询和负载均衡设备,应用层用注册中心和服务发现,避免单点。
- 故障转移层面:健康检查失败自动摘除节点,数据库主从自动切换,缓存集群分片故障时自动重平衡。
- 容量层面:做压测确定单实例容量上限,提前规划扩容预案和限流降级方案。
- 演练层面:定期做故障演练(混沌工程思路),验证故障转移真的能在预期时间内生效。
把这几层串起来,就能构成一个相对完整的SRE视角答卷。如果能在最后补一句“再好的架构也要靠监控和复盘持续改进”,这段话就更有沉淀感。
8. 这套题背后的能力模型与备考建议
8.1 从笔试反推岗位能力要求
把滴滴这套运维开发笔试题从头到尾看下来,你会发现一个核心逻辑:它考察的不是某个单独的工具或命令,而是一个工程师“面对复杂系统时能否快速定位、解决问题,并把解决过程自动化”的综合能力。拆解开来,大致对应以下几项能力:
| 能力维度 | 对应题目类型 | 备考重点 |
|---|---|---|
| 网络与系统基础 | 选择/简答 | 协议细节、状态流转、常用命令 |
| 数据库实战 | SQL/索引分析 | 索引原理、执行计划、慢查询优化 |
| 编程能力 | Python/Shell编程题 | 文件处理、正则、数据统计 |
| 监控与运维 | 场景设计题 | 监控指标体系、告警策略 |
| 系统设计思维 | 架构题 | 高可用、容量规划、故障转移 |
| 排障思路 | 场景分析题 | 分层定位、工具链使用、优先级判断 |
我见过很多同学在备考时陷入一个误区:花大量时间背命令参数,却忽略了对“为什么”的理解。实际上,校招笔试更看重底层原理和逻辑推理能力。因为命令和工具更新迭代快,今天熟悉的工具明天可能就被替代,但“TCP握手为什么是三次”“索引为什么能加速查询”“为什么会产生慢查询”这些底层的原理,却是十年不过时的。
8.2 时间分配与答题策略
这套题题量不小,而且大题需要手写较多文字,时间分配很关键。我的建议是:先快速扫一遍全卷,把会做的选择题立刻做掉,把不会做的标记好先跳过,不恋战。然后优先做编程题,因为编程题分值高且答案确定性最强,先把能拿的分拿到手。
对于简答和设计题,我的策略是“结构化作答”:分点列条,先结论后解释,每一点控制在两三行。这样既方便阅卷人快速抓取核心信息,也能避免长篇大论后重点不突出的问题。举个例子,如果题目问“服务响应慢的排查思路”,不要写一大段话,而是写“1. 确认是否全局限流;2. 看监控确认瓶颈为CPU/IO/网络/锁;3. 深入日志和trace定位具体模块;4. 针对定位结果采取扩容、优化或降级措施”,每个点后面简单展开一句即可。
8.3 一条实操复现路径
如果你想拿这套题来自测或备考,我建议按下面这个思路走一遍:
第一步,不要看答案,先限时2小时做一套题,模拟真实考试,标记自己的薄弱环节。 第二步,针对错的题目,不要只记正确答案,而是回到知识点源头,把对应的协议流程、系统命令、索引机制彻底弄懂。 第三步,给自己布置两个实战小项目:一是写一个日志采集和统计脚本(对应编程题),二是画一张自己熟悉系统的监控架构图并说明指标设计逻辑(对应设计题)。 第四步,找一位有运维开发经验的前辈或朋友,把场景题的答题思路讲述一遍,让他帮你看有没有逻辑漏洞。这一步特别重要,因为设计类和排查类题目,只有通过“说出来讲给别人听”才能发现自己的思维盲区。
我自己当年备考时,最大的体会就是:校招笔试题其实是“面试的预演”。很多时候,笔试中遇到的设计题和排查题,到了面试环节会以追问的形式再出现一次。如果你只是背了答案而不是真正理解,到了面试时很容易在深挖中露馅。反过来,如果你笔试时就把题吃透,面试几乎是顺理成章的事。
8.4 再往前一步:运维开发的长线成长路径
最后聊点轻松的体会。很多人觉得运维开发是个“不那么前端”的岗位,好像离业务很远。但做了几年后你会发现,运维开发恰恰是互联网公司里离“全局”最近的角色之一。每次大促容量评估、每次线上故障复盘、每次架构升级,运维开发都要站在全局视角协调资源和风险。这套笔试里的场景题,本质上就是在筛选“有全局视角的工程师”。
如果你正在准备这类笔试,我的建议是:不要把它当成纯粹的应试,把题目里出现的这些场景当作“预演的线上事故”,用解题的心态去推演如果真遇到这种情况你会怎么办。带着问题意识去学,学到的就不是死知识,而是以后真的能用的工程能力。这套题做完之后,建议再找两三套其他大厂的运维开发真题交叉练习,把高频考点变成自己的肌肉记忆,到笔试现场才能不慌不忙地发挥出真实水平。