
“滴滴出行2018校园招聘网申笔试-系统运维工程师(第一套”这套题在校招圈里讨论度一直不低。原因很简单它没有堆砌偏题怪题很多题目乍看是基础细想都是在考察你懂不懂“生产环境”这四个字的分量。今天我就借这套题聊一聊系统运维工程师这个岗位到底在考什么以及题目背后真正值钱的实操经验——从零搭一套生产系统、并且把它稳定维护住到底是什么感受。如果你正在准备运维校招或者刚入行想建立一套完整的运维知识体系这篇文章应该能给你一个比“刷题”更值钱的视角。我不会逐题给答案而是把考点拆开还原到一个真实的生产环境里让你看到面试官真正想听到的思路。1. 这套笔试题在考什么读题比做题更重要1.1 校招运维笔试的命题逻辑先想一个问题校招不像社招不指望你有三五年实战经验那笔试到底在筛选什么样的人从我的观察看运维岗位的校招笔试只做三件事第一考察你的基础是否扎实第二考察你有没有基本的系统思维第三考察你把知识落地的能力。所谓基础扎实就是Linux操作、网络协议、数据库原理、脚本语言这部分这是运维的“底层操作系统”。系统思维就是面对一个故障或一个需求时能不能分清主次、按顺序排查、考虑影响面。知识落地能力则是给你一个场景比如“线上服务CPU飙升”“磁盘写满”“数据库连接数暴增”你能不能给出可执行的排查步骤而不是只背出几个命令。滴滴这套题比较典型的地方在于它很多题目都是“披着基础外衣的场景题”。比如看起来在问TCP握手实际是希望你理解为什么高并发下连接队列会满看起来在问Linux命令实际是考你日志分析时的组合用法。如果你只是记住了孤立的知识点没有串成一条线做起来就会觉得哪里都眼熟但哪里都拿不准。1.2 透过题目看真实的业务场景还有一个很重要但不写在试卷上的点运维是对业务负责的。滴滴的业务是什么出行平台。这类业务有三个非常鲜明的特征流量高峰极其集中早晚高峰的订单量和位置上报频率会瞬间拉满实时性要求高乘客和司机的位置、订单状态都需要低延迟处理数据一致性敏感涉及支付、结算、订单分配任何数据错乱都是大事故。这些业务特征会直接决定运维的做事方式。比如你搭一套系统不能只考虑“能跑”要考虑它扛不扛得住峰值你选数据库方案不能只图方便要考虑数据一致性和故障恢复能力你设计监控不能只盯CPU内存还要关注业务指标比如订单成功率、接口延迟。所以你会发现真正有经验的运维看一套笔试题看的不是单个知识点而是题目背后映射的业务场景。这也是为什么我建议正在准备校招的同学每做完一道题多问自己一句这个知识点在生产环境里会以什么形式出现会引发什么故障我该怎么应对想通了这一点笔试和面试的层次就完全不一样了。2. 从零搭建一套生产系统先把“地基”打稳2.1 需求定义和容量评估先行很多刚入行的同学拿到“从零搭建系统”这个任务第一反应是装环境装个Linux、装个Nginx、装个MySQL跑起来就算完事。我见过不少这样的方案结论都是同一个跑起来很容易撑住业务很难。真正的第一步不是装软件而是问清楚需求。你要先搞清楚这几个问题这个系统的预估日活是多少峰值QPS大概什么量级数据量多大、保留多久可用性要求是几个9预算有多少团队有几个人维护这些信息直接决定架构选型和机器数量。我举一个简化的例子方便你理解容量评估的算法。假设业务方告诉我们预估峰值QPS是5000平均每个请求后端处理耗时50ms那单台应用服务器大约能扛1000QPS1000ms/50ms20个并发请求20×501000QPS实际要打折按700算更稳妥。这样一来你需要至少5台应用服务器做负载均衡再留一台冗余6台起步。数据库侧的估算也类似。假设读写比4:1那写QPS约为1000。MySQL单机在合理配置下写TPS大概2000-3000但为了留足余量通常只按峰值的50%规划。如果写QPS长期超过1500就得考虑分库分表或者上缓存挡一层读流量。这些数字不需要背但你需要知道怎么算因为这是后续所有资源规划的依据。2.2 Linux系统初始化清单需求确认完机器到位接下来才是真正动手的阶段。新机器拿到手别急着部署业务先把系统基础环境收拾利索。我整理了一份我在生产环境里每台机器都会做的初始化动作你可以直接拿来当checklist配置主机名和DNS解析保证内网机器之间通过主机名互通别用IP硬编码不然后面扩容迁移会想哭。设置时间同步使用chrony或者ntpd确保所有机器时钟一致。分布式系统里时间不一致会导致日志错乱、数据时间戳对不上排查问题的时候极其痛苦。调整内核参数在/etc/sysctl.conf里做配置。推荐几个关键项net.core.somaxconn65535提升连接队列长度net.ipv4.tcp_max_syn_backlog65535应对突发连接vm.swappiness10让内存优先用于缓存而不是换页fs.file-max6553560放宽文件句柄限制。修改文件句柄限制在/etc/security/limits.conf里设置* soft nofile 65535和* hard nofile 65535。注意这个配置需要重新登录或者重启进程才生效别改完就以为没问题了。统一yum源和基础软件包包括vim、curl、wget、jq、tree、lsof等。建议用内部镜像源方便后续批量安装。优化SSH配置关闭密码登录改用密钥修改默认端口非必须但公网机器强烈建议设置登录超时和失败重试限制。配置防火墙只放行业务端口和管理端口其他一律拒绝。这个步骤很多人会偷懒等被扫描器盯上再回头补就晚了。安装云监控agent或者自建监控agent确保机器一上线就纳入监控体系而不是等出故障了才发现这台机器“没被监控”。这套初始化做完一台机器才算真正达到“可交付”状态。可能有人觉得这些很琐碎但生产环境的稳定性恰恰是由这些琐碎细节堆出来的。提示初始化操作一定要写成脚本或者配置管理工具Ansible、SaltStack来执行几十台机器靠手动敲命令不仅效率低还容易出现两台机器配置不一致的问题。配置漂移是生产环境的大敌。3. 核心组件部署与配置Nginx、MySQL、Redis的一个可复用组合3.1 Nginx配置参数的计算方式应用服务有了前置的接入层一般用Nginx。很多教程会直接给你一个默认配置但生产环境里需要根据机器的实际规格调整参数。最关键的两个参数是worker_processes和worker_connections。worker_processes通常设为CPU核数比如你是8核的机器就设为8。worker_connections表示每个worker进程能同时维持的最大连接数设多大取决于系统文件句柄限制一般设为10240或者65535。Nginx的最大并发连接数约等于worker_processes × worker_connections但这个值是理论上限还要考虑带宽和业务响应时间。我举个实际例子。8核机器worker_connections设65535理论并发约50万但你的后端服务根本扛不住这个量级所以Nginx这一层通常不会是瓶颈。真正要注意的是内核参数是否匹配比如somaxconn如果默认是128高并发下就会出现连接排队溢出表现为客户端大量connect超时。这个问题网上案例特别多因为好多人只调了Nginx配置忘了调内核。Nginx层面还有几个值得注意的点开启gzip减少传输体积配置upstream时使用keepalive减少和后端服务建连开销日志格式里加上request_time和upstream_response_time这两个指标是排查接口慢的核心依据静态资源用alias直接返回别打到后端应用上。3.2 MySQL部署与基础优化数据库是整套系统的核心没有之一。MySQL的部署安装不算难难的是参数配置。我见过太多“默认配置跑线上”的案例结果就是业务量稍微上来数据库先扛不住。关键的参数是这些innodb_buffer_pool_size这是InnoDB的缓冲池大小直接决定数据缓存能力。经验值是物理内存的60%-70%。比如一台32G内存的数据库机器buffer pool设为20G-22G。注意这个比例是在数据库独占机器的情况下如果机器还要跑其他服务要适当下调。innodb_log_file_sizeredo log大小默认值往往偏小。写频繁的业务建议设为1G-2G太小会导致日志频繁切换影响写入性能。innodb_flush_log_at_trx_commit这个参数是性能和可靠性的权衡。默认是1每次事务提交都刷盘最安全但最慢设为2是每秒刷盘性能好一点但操作系统崩溃可能丢1秒数据。读多写少的业务可以设为2涉及资金交易的库老老实实保持1。max_connections默认151在稍微有点流量的场景就不够了一般根据机器内存和业务并发设为500-2000。但注意连接数不是越大越好每个连接都要占内存设太大反而会把机器拖垮。slow_query_log慢查询日志一定要开记录执行时间超过1秒的SQL这是后续优化索引的依据。主从复制方面至少要有一台从库做读写分离或备份源。同步方式建议用半同步复制主库写入后要等从库确认收到binlog才算提交成功牺牲一点延迟换取主从切换时数据不丢失。这里说一个我踩过的坑当年我把主库的binlog_format设为STATEMENT结果因为一条用了UUID()函数的SQL主从数据不一致查了好久才发现问题。现在一律建议使用ROW格式虽然binlog体积会大一些但主从数据一致性最有保障。3.3 Redis部署与持久化选择缓存层基本都用Redis。部署Redis不难但有几个配置项值得好好说。maxmemory一定要设置不然Redis会无限吃内存直到把机器拖垮。经验值是物理内存的50%-60%留出一部分给操作系统做page cache因为Redis做持久化时要fork子进程内存不足会失败。持久化方式选择RDB是快照恢复快但可能丢数据AOF是追加日志数据安全但体积大、恢复慢。Redis 4.0之后支持混合持久化AOF重写时生成RDB格式加上增量命令兼顾了恢复速度和数据安全我建议默认开启。内存淘汰策略maxmemory-policy生产环境常用allkeys-lru也就是内存满时淘汰最久没被访问的key。但要注意如果某个key被集中访问并且允许短暂过期可以用volatile-ttl。这个选择要结合业务容忍度别随便选。再聊聊缓存三大问题。缓存穿透查询一个不存在的key每次都打到数据库解决办法是缓存空值并且设置短过期时间或者用布隆过滤器挡一层。缓存击穿某个热点key过期瞬间大量请求打到数据库解决办法是互斥锁重建缓存或者热点key设置为逻辑上永不过期。缓存雪崩大量key同一时间过期导致数据库压力暴增解决办法是过期时间加随机值别让所有key在同一秒失效。这三个问题几乎是面试必考题但很多人只能背出名词。如果你能把每种问题的产生条件、排查思路、解决方案的trade-off讲清楚然后说出一两句自己的实践体会面试官对你的印象会好很多。4. 上线后的日常维护监控、备份、发布与应急4.1 监控体系从指标采集到告警闭环系统上线只是开始后续的维护才是运维工作的重头戏。监控体系是最先要建好的没有监控的生产环境就像闭着眼睛开车。当前主流方案是Prometheus Grafana Alertmanager。Node exporter负责采集机器层面的指标包括CPU使用率、内存使用率、磁盘空间、网络流量、TCP连接数等。业务层的指标比如接口QPS、延迟、错误率一般由应用自己暴露metrics接口Prometheus定期拉取。采哪些指标我认为机器层和业务层都要有。机器层选了CPU、内存、磁盘、网络、句柄数、TCP连接数业务层选了QPS、P99延迟、错误率、活跃用户数。监控指标不是越多越好每多一个指标就多一分维护成本关键是每个指标都要能回答一个问题系统健康吗如果不健康是哪里出了问题告警规则的设计也有讲究。我的原则是少而准别让告警变成噪声。磁盘使用率超过80%告警持续5分钟CPU使用率超过90%告警持续10分钟接口错误率超过5%告警持续2分钟。告警阈值要结合历史数据设定不要拍脑袋。设置完之后一定要有告警通知渠道钉钉、企微、邮件都可以但需要区分严重级别P0需要立即处理短信加电话P1需要当天处理工作群通知P2记录跟踪即可邮件通知。我见过不少团队监控面板做得很炫但告警阈值设置不合理要么一天几百条谁都不看要么出了大事才发现没配告警。监控不是装饰品报警一定要打到人而且要有人响应。没人响应的告警等于没有告警。4.2 备份策略与恢复演练只备份不演练等于白做备份是运维工作的底线也是很多人最容易忽略的部分。所有数据都可能在某一刻意外消失没有备份业务就只能赌运气了。我常用的备份方案是MySQL使用xtrabackup做物理备份每天凌晨2点全备保留最近7天同时开启binlog每小时备份一次binlog保留最近3天。这样最坏情况下可以恢复到最近1小时的任意时间点。如果业务对数据丢失零容忍可以再加一个实时同步的从库双保险。但备份这件事真正值钱的是恢复演练。很多团队备份做得挺好却从来没有真正恢复过一次等到真出事才发现备份文件损坏、恢复流程不通。我从业以来做过好几次恢复演练每次都会发现新问题有一次备份脚本因为磁盘空间不足悄悄失败了一个月还有一次xtrabackup版本和数据库版本不匹配导致恢复失败。所以我的建议是至少每季度做一次完整的恢复演练从备份文件里恢复到一台新机器验证数据完整性和流程可用性。这里分享一个真实场景。一次线上误操作某个业务表被truncate了业务数据丢了几分钟。当时心里咯噔一下但因为有binlog很快通过mysqlbinlog解析出误操作之前的事务把数据完整恢复回来了只影响了几分钟的写入。那几分钟的数据通过业务日志手动补齐。整个过程大概用了40分钟如果不是有备份和binlog这就不是40分钟能解决的事了。备份这东西平时看起来没用关键时刻是真的能救命。4.3 发布与变更管理的“保守主义”我见过太多线上故障不是因为业务代码写得差而是因为发布和变更太随意。运维必须对变更保持一种“保守主义”的态度——所有变更都要有方案、有审批、有回滚。一个标准的发布流程应该是这样的先在预发环境或灰度机器上发布观察监控指标和日志确认没有问题后再分批发布比如先发布10%的机器观察5-10分钟没问题再发布剩余机器。如果流量很高建议在业务低峰期发布比如凌晨2点到6点。紧急发布除外但也要有应急回滚方案。每次发布前一定要想好回滚方案。应用发布回滚相对简单重新部署上一个版本即可。配置变更回滚就比较麻烦了如果配置是集中管理的建议每次变更前先导出当前配置备份如果变更内容很复杂更应该先在测试环境验证一遍。我见过因为改了一个负载均衡的超时时间导致所有请求502的事故最后是回滚加重启才恢复。改配置之前有多谨慎都不为过。另外自动化发布工具该上就上。用Ansible做配置管理用脚本或Jenkins做发布让每次变更都是可重复、可记录的。手动操作越少出错的概率越低。4.4 故障排查的通用方法论最后一个重头戏故障排查。这部分也是笔试和面试里最容易出彩的地方因为比起背诵知识点面试官更想看你面对故障时的思考顺序。以CPU使用率飙高为例我分享一下我的排查路径。先top看哪个进程CPU高然后pidstat -t -p PID确认是哪个线程如果是Java应用用jstack导出线程栈搜索线程号对应内容看是不是业务死循环、锁等待、或者GC频繁如果是其他语言用perf top采样看热点函数。定位到具体代码后再决定是扩容、改代码还是重启。磁盘写满也是高频故障。先用df -h看挂载点使用率再用du -sh逐级定位大目录用lsof查看已经被删除但仍然被进程占用的文件。有个经典坑就是du显示磁盘没多少文件但df显示磁盘满了八成是有进程打开了一个被删除的大文件释放文件句柄或重启进程才能回收空间。内存溢出和内存泄漏的排查也值得说一下。内存溢出OOM一般是进程瞬间申请了大量内存可以用dmesg看内核OOM日志内存泄漏是进程内存缓慢增长需要监控历史曲线找规律。Java应用可以配-XX:HeapDumpOnOutOfMemoryError在OOM时dump堆后续用MAT分析使用golang的话pprof是必会的排查工具。我觉得故障排查最怕的是“没有章法地瞎试”。正确的做法是先明确现象再收集信息然后提出假设逐个验证最后修复复盘。这五个步骤看起来简单但很多人做的时候会跳过“收集信息”直接去“验证假设”结果定位了半天才发现方向错了。5. 从笔试题到实战几个反复出现的坑与答题思路5.1 高频失分点刷这套题或者类似校招题时我发现了几个高频失分点在这里给准备校招的同学提个醒。第一个只会背命令不会组合使用。比如日志分析给你一个access.log统计访问量前十的IP很多人知道awk、sort、uniq但就是没法一步写出来。这种题目考察的是基本功的熟练度没有任何技巧只能靠多写多练。awk {print $1} access.log | sort | uniq -c | sort -rn | head -10这种组合命令平时练熟到考场上才能信手拈来。第二个排查故障只有重启这一招。我记得有些答案里不管遇到什么问题“重启一下就好了”。这反映了对问题根本原因缺乏思考。生产环境里重启可能是应急手段但永远不是解决方案。你需要做的是找到问题为什么会发生否则重启十次也白搭。第三个不考虑影响面。比如问到“如何清理磁盘空间”有人直接说rm -rf删文件但如果这个文件是正在被写的大日志呢如果删的是数据库文件呢正确的回答先要看是什么文件占空间确认能否删除再动手。这种“安全意识”和“影响面评估”能力恰恰是校招面试时最能体现你和别人差距的地方。5.2 给准备校招的同学几条实操建议如果你真的想进入系统运维这个方向我给你几条具体建议。第一动手搭一套完整环境。本地用虚拟机或者云服务器都行从Linux安装开始装Nginx、MySQL、Redis部署一个简单的Web应用配好监控、日志、备份。这整个过程下来你对“从零搭建”就有切身体感了面试时讲到细节也更有底气。第二把一次故障从发现到解决完整复盘一遍写一篇文档。故障复盘文档是最能体现运维思维的东西。里面写清楚故障发生的现象、排查过程、根因、修复动作、后续改进。哪怕只是自己在实验环境里“制造”一个故障再排查也比纸上谈兵强得多。第三脚本语言要学透一个。Shell是你日常操作的最高频工具Python则是处理复杂逻辑、写自动化脚本的利器两个都至少要能上手。运维的很多工作都是重复性的能脚本化的绝不手动做这是效率的基石。第四面试时多讲“为什么”而不是“怎么做”。比如问你MySQL主从复制的原理你描述完流程之后可以主动说一句“这里binlog用ROW格式是为了保证主从一致性因为STATEMENT格式在特定SQL下会产生数据不一致”。这种主动补充的深度比被动回答问题要加分得多。说到底这套笔试题最大的价值不是让你背答案而是让你提前进入运维工程师的思考模式。带着“为什么”去刷题把每个知识点都放到真实的生产场景里去理解你收获的远不只是一份offer而是一套能支撑整个职业生涯的思维方式。在我带过的校招生里面后来成长最快的那拨人都有一个共同特点他们从来不满足于“把题做对”而是会追着问“这个知识点上线后是什么样”。运维这个岗位最值钱的不是背得有多熟而是遇到问题时的判断力。而判断力的来源就是你在平时积累的每一个“为什么”以及你真正动手练习过的每一个场景。如果你正在准备运维校招送你最后一句话别只刷题请每一步都往深里再走半步。这半步就是拉开差距的地方。