
2024年7月中旬我投了Shopee SRE站点可靠性工程师提前批一周后收到了笔试链接。考完那天下午我在手机备忘录里写了一段话这个笔试真正的难点不是哪道题特别难而是它把Linux、网络、分布式、算法、还有SRE特有的故障场景判断全部塞进一个半小时你得同时调度起五套知识。这篇文章就是从那天的备忘录开始的。先说结论如果你准备秋招时只刷LeetCode不碰Linux和监控告警那这场笔试会让你很被动。但反过来说只要你在平时干活时真的处理过线上问题而不是只写过业务代码很多题你是能靠直觉蒙对的——这里的“蒙对”是靠系统工程师的肌肉记忆而不是运气。这篇复盘我尽量把记得的题目、我的答题思路、以及考完之后的反思都写清楚给后面准备Shopee SRE或者其他大厂SRE岗位的朋友一个参考。1. 先搞懂Shopee的SRE笔试考的是什么人1.1 SRE这个岗位和普通运维、后端开发到底差在哪很多人对SRE的认知还停留在“运维换了个洋气的名字”。这个理解在笔试里会吃大亏。SRE最早是Google提出来的角色核心是用软件工程的方式解决运维问题。也就是说你既要懂系统、懂网络、懂数据库也要能写代码去自动化处理重复劳动还要懂怎么用量化指标比如SLI/SLO来衡量稳定性。和传统运维相比SRE必须会写代码笔试里直接上手撕算法题就是证据和后端开发相比SRE不追求功能迭代而是追求服务能不能稳定跑、出问题时能不能快速恢复。所以SRE的笔试才会是“基础题算法题场景题”的混合体它不是在筛一个纯粹的程序员而是在筛一个“懂开发的系统工程师”。1.2 Shopee的业务特点决定了它要什么样的SREShopee是东南亚电商业务上有几个特点大促流量峰值非常夸张9.9、11.11、12.12这些节点流量能翻好几倍业务跨多个市场多机房部署、数据同步、网络链路的复杂度都摆在那里。这意味着它的SRE要面对的不只是单机问题而是大规模分布式系统下的容量规划、故障隔离、监控告警、发布变更这些事儿。体现在笔试里就是客观题覆盖面特别广编程题偏数据结构基础而真正拉分的往往是场景题——它给你一个线上故障描述让你说排查思路。这类题没有标准答案但能看出你有没有真实的线上经验有没有一套自己的排查方法论。1.3 笔试的整体结构和我踩的第一个时间坑我这场笔试是牛客网在线作答总时长90分钟。题型大致分成三块单选和多选客观题大概十几道两道编程题纯手写代码一道场景问答给你一段线上故障描述让你写排查思路和止损方案。我踩的第一个坑就是时间分配。客观题我花了大概45分钟虽然大部分会做但有几道多选题反复犹豫导致后面编程题时间被压缩到35分钟左右场景题更是只剩10分钟草草写了几个要点。考完复盘正确的策略应该是客观题坚决控制在30到35分钟会做的快速过不会的先标记跳过编程题每道控制在15到18分钟先写出能跑的版本不追求最优解场景题至少留15分钟把排查思路分层次写完整。笔试不要求你每道题都满分而是要在有限时间内拿尽量多的分先保底再拔高。2. 基础题复盘Linux命令、网络细节、分布式概念一个都没跑2.1 选择题里的高频考点和容易翻车的地方客观题范围很杂但有几个高频主题是确定的Linux系统、网络协议、数据库、分布式理论。我印象比较深的几道题在这里还原一下大意和当时的判断逻辑。有一道题问某台服务器的load average持续偏高但CPU使用率只有30%可能的原因是什么这题考的是对load average的理解。load average是运行队列中处于可运行状态和不可中断睡眠状态的进程平均数量它不只是CPU指标如果大量进程阻塞在IO等待上CPU不高但load照样飙升。所以答案里“大量磁盘IO读写”是正确项。这题对没看过《性能之巅》或者没排查过IO瓶颈的人来说容易直接选成CPU相关选项。还有一道是网络题客户端请求服务端时大量出现TIME_WAIT最可能是什么原因TIME_WAIT是TCP四次挥手中主动关闭连接的一方在发送最后一个ACK后进入的状态要等2MSL确保对端收到。大量TIME_WAIT一般出现在高并发的短连接场景通常是服务端主动关闭了大量连接或者是客户端频繁创建短连接。这题的关键是“谁主动关闭谁进TIME_WAIT”。搞清楚这个状态机的来龙去脉比死记硬背答案管用。数据库相关也考了一道MySQL主从复制延迟可能由哪些原因引起选项里有“主库大事务长时间未提交”“从库单线程回放relay log”“从库硬件性能差”“主库binlog没开启”。前三个都是对的binlog没开启根本没法做主从所以第四个是干扰项。这题考的是你是否理解主从复制的整个链路主库写binlog、从库IO线程拉取、SQL线程回放。任何一环出现性能瓶颈都会造成延迟。分布式理论里我碰到的是CAP理论和一致性哈希。CAP的选择题比较基础关键是理解在网络分区发生时你必须在一致性和可用性之间做取舍一致性哈希考的是“节点增减时影响的数据范围最小”这题如果你用过Redis Cluster或者了解过负载均衡的一致性哈希实现基本送分。2.2 Shell命令题从日志文件里快速定位问题笔试里有道题是给你一个Nginx访问日志的路径要求用一条Shell命令统计出访问量最高的Top 10 IP。这题我几乎是秒答的awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10拆开解释一下awk取出每行的第一个字段也就是客户端IPsort把相同IP排到一起uniq -c统计出现次数sort -rn按次数从大到小排序head -10取前十。这道题后面还追问了一句如果日志里混入了CDN回源IP怎么过滤思路就变成了先从日志格式里找到标记客户端真实IP的字段比如X-Forwarded-For头里的最后一个非私有IP再用awk做条件过滤。这道题考的不是你能背多少命令而是你在真实环境里有没有处理过日志分析。还有一道Shell题更贴近SRE日常写一个脚本检查某个服务进程是否存在不存在则尝试启动启动失败就发出告警。我的写法大致是#!/bin/bash SERVICEmyapp if ! pgrep -f $SERVICE /dev/null; then systemctl start $SERVICE sleep 3 if ! pgrep -f $SERVICE /dev/null; then echo $(date) $SERVICE failed to start /var/log/service_watch.log # 这里可以接告警比如调用告警API fi fi这种脚本在笔试里不需要写得特别复杂但一定要体现出你有“检查-动作-二次确认-告警”的闭环思维。只写一个pgrep判断然后start说明你还没经历过“进程拉不起来但脚本已经报成功”的尴尬。2.3 网络细节题HTTP状态码和负载均衡容易被追问有一道选择题是区分HTTP 502和504。502 Bad Gateway是网关或代理服务器从上游服务器收到了无效响应比如上游崩了、返回了乱码504 Gateway Timeout是网关在指定时间内没等到上游响应也就是上游超时了。这个区别在SRE排查链路超时问题时很关键看报错是502还是504基本上能判断是上游应用挂了还是上游响应太慢。负载均衡的题问四层和七层的区别。四层LB工作在传输层基于IP和端口转发性能高典型如LVS、AWS NLB七层LB工作在应用层可以基于URL、Header做路由支持更细粒度的健康检查和灰度策略典型如Nginx、AWS ALB。如果你做过K8s应该能联想到Service的ClusterIP是四层转发而Ingress Controller本质上是七层。笔试里能把这些串起来答比孤立背概念要加分。3. 编程题复盘两道上机题我是怎么一步步写出来的3.1 第一道数组类——最大连续子数组和这道题LeetCode上有原题53. 最大子数组和但笔试里包装了一个场景某服务最近N天的请求量变化记录求连续一段时间内请求量增长的最大值也就是最大连续子数组和。题目要求时间复杂度O(n)空间O(1)。我用的是Kadane算法核心思路是维护两个变量一个是以当前元素结尾的最大子数组和endingHere一个是全局最大子数组和maxSoFar。遍历时对每个元素x要么把它接到之前的子数组后面要么从它自己重新开始def max_subarray_sum(arr): ending_here arr[0] max_so_far arr[0] for x in arr[1:]: ending_here max(x, ending_here x) max_so_far max(max_so_far, ending_here) return max_so_far要注意的边界是数组全负数的情况。这时候正确的答案应该是最大的那个负数而不是0。很多人在初始化max_so_far时写成0遇到全负数数组就会翻车。这题的升级版是要求返回最大子数组的起止下标笔试如果加问记得在更新endingHere和maxSoFar时同步记录索引。3.2 第二道设计一个带过期时间的LRU缓存第二道题明显更贴近SRE场景实现一个支持过期时间的LRU缓存set(key, value, ttl)和get(key)两个方法缓存容量有限满了淘汰最久未使用的key过期了要能自动失效。我现场用的是Python的OrderedDict它内部是哈希表加双向链表既能O(1)查找又能O(1)实现“移动到末尾”。from collections import OrderedDict import time class LRUCacheWithTTL: def __init__(self, capacity): self.capacity capacity self.cache OrderedDict() # key - (value, expire_at) def get(self, key): if key not in self.cache: return -1 value, expire_at self.cache[key] if time.time() expire_at: del self.cache[key] return -1 self.cache.move_to_end(key) return value def put(self, key, value, ttl): if key in self.cache: del self.cache[key] expire_at time.time() ttl self.cache[key] (value, expire_at) self.cache.move_to_end(key) if len(self.cache) self.capacity: self.cache.popitem(lastFalse)讲一下为什么用OrderedDict而不是普通dict加一个时间戳字段普通dict无法记录访问顺序你必须在get的时候自己去维护访问时间列表复杂度高且容易错。OrderedDict的move_to_end天然支持LRU的“最近使用挪到尾部”语义popitem(lastFalse)从头部弹出最久未使用的key写起来干净利落。你自己写的话还可以用哈希表加双向链表来实现这题在面试里也常考手写链表版本。笔试用OrderedDict已经能拿满分因为关键是考察你对“O(1)查找O(1)淘汰”这个核心矛盾的理解。3.3 在线笔试环境里的做题节奏和自查方法在线笔试和你平时在IDE里刷题完全不一样。没有自动补全没有编译器提示没有本地调试你得在网页文本框里直接写代码。我的经验是先花两分钟把题读透确认输入输出格式再在草稿纸上把核心思路写出来最后才落到代码。哪怕是核心代码模式也别上来就敲思路不通很容易写着写着就卡壳。代码写完别急着交先手动构造几个测试用例在脑子里跑一遍空数组、全负数、缓存容量为1、key刚好在过期边界。这些边界值是你最容易挂分的地方。还有一个技巧如果你的编辑器支持先写几个print调试输出自己确认没问题了再删除。我这次笔试就靠这个方法救了一道题因为第一版代码在缓存容量为1时逻辑有bugprint出来才发现的。编程题的时间节奏我建议每道不超过20分钟。如果一道题想了10分钟还没思路果断先写一个暴力解法拿部分分然后去把其他题做完再回来想优化。SRE笔试不是算法竞赛你的目标是总分最大化不是单题满分。4. 场景题复盘SRE的核心竞争力全在这道题里4.1 大促场景下P99延迟突增你的排查链路是什么这道场景题我印象最深因为它是真正的SRE日常。题干大概是这样9.9大促期间核心商品服务的P99延迟从平时的200ms涨到了2s但接口错误率没有明显上升CPU和内存使用率也正常。作为SRE你怎么排查我当时的答题思路是分层次展开的第一层先看监控面板确认“异常范围”。P99涨而平均延迟可能没涨太多说明是少数请求极慢不是所有请求都变慢。需要确认的三个问题是所有接口都慢还是单个接口慢是全部机器慢还是某台机器慢是用户端到端的慢还是服务端处理的慢这三个问题决定了后续排查方向。第二层如果确认是单个接口慢往下查依赖。P99高通常不是应用本身计算慢而是在等外部资源。我会按这几个排查点走数据库慢查询有没有增加连接池有没有打满Redis有没有热key导致单分片延迟高下游RPC调用的耗时有没有上涨线程池是否出现大量线程阻塞等待。其中慢SQL是最常见的元凶大促流量下一条没走索引的SQL就可能把数据库连接池拖垮。第三层看网络层。TCP重传率、连接数、TIME_WAIT数量、网络小包有没有丢包。特别是跨机房调用链路长任何一跳网络抖动都会放大到P99上。第四层止损动作要快。在定位根因的同时先做降级和限流对非核心依赖做降级对尖刺流量做限流必要时摘掉异常机器。SRE的原则是先恢复服务再找根因。把这句话写进去会让面试官觉得你有实战意识。这道题的评分点我认为不是看你最终能不能给出一个标准答案而是看你有没有一套从现象到根因的层次化排查思路以及在紧急情况下是否把“止损”放在“根因定位”前面。而这恰恰是SRE和纯开发最大的区别。4.2 SLI/SLO设计题要为订单创建接口设计可用性指标另一道场景题考的是SRE里最核心的概念SLI、SLO和错误预算。题目要求给“订单创建接口”设计SLI和SLO并计算一个月内的错误预算。我当时的答案分了三步。第一步定义SLI。对于订单创建接口我选了三个指标可用性请求成功率、延迟P95或P99、吞吐每秒成功处理的订单数。SLI的选择一定要贴合业务订单创建这种写操作成功率和延迟是最核心的吞吐可以作为容量监控的辅助指标。第二步设定SLO。比如成功率SLO为99.9%延迟SLO为P99在800ms以下。SLO不是拍脑袋定的要参考当前系统实际表现和业务容忍度。如果一个接口平时P99只有200ms你定一个5s的SLO等于没定。第三步计算错误预算。以30天计算总分钟数是43200分钟30×24×60。99.9%可用性对应的不可用时间是43200×0.00143.2分钟。这43.2分钟就是一个月的“出错额度”可以用来指导线上变更的发布策略错误预算还很多可以大胆发布预算快烧完了就要冻结变更、优先做稳定性治理。这个计算过程一定要自己亲手算一遍笔试里数字不能错。4.3 容量评估和告警风暴SRE躲不掉的两道必答题容量评估题考得很实在某服务单机支撑500 QPS大促预估峰值5万QPS需要准备多少台机器这里我写了完整的计算过程5万除以500等于100台但这是理论最下限。实际还要考虑几个因素单机故障冗余至少要再留20%到30%的buffer大促流量不是均匀分布的峰值可能集中在某个可用区如果是无状态服务可以考虑快速扩容兜底。所以我的答案是130台左右同时说明这是预估最终要以压测数据为准。重要的不是那个数字而是你是否知道“容量规划必须在压测数据基础上做而不是拍脑袋”。告警治理是最后一道题线上告警风暴一晚上几千条告警你怎么处理我答了分级和聚合的思路。告警要分优先级P0表示服务不可用需要立即响应P1表示功能异常但服务可用P2表示资源水位预警。几千条告警里大部分可能都是同一个根因引发的连带告警比如数据库慢查询导致所有依赖它的接口都超时这时候要做的是告警聚合把相关联的告警归并成一条事件而不是让On-Call的人淹没在几千条信息里。更进一步的做法是配置抑制规则和静默策略在已知故障期间自动抑制下游服务的告警。我在美团实习的时候处理过一次类似的告警风暴当时就是把根因服务定位出来把下游所有受影响服务的告警先静默掉然后集中精力处理根因这个经验让我在答这道题时特别有底气。5. 复盘之后的备考心得提前批的真实节奏和踩坑记录5.1 提前批的时间线别等“准备好了”再投Shopee的秋招提前批一般7月就开放了笔试通常安排在投递后一两周。我之前一直觉得暑假还长准备到8月再投也不迟后来发现提前批的流程比想象中快得多而且hc也相对充足。如果你准备走SRE方向7月上旬就要把简历打磨好中旬完成投递7月底到8月初集中准备笔试。一个很关键的信息是提前批如果挂了很多公司是允许转正式批的但具体政策每年可能不一样投递前一定要看清官方招聘公告里的说明。有的公司提前批面试挂了会影响正式批流程有的不会。这个信息直接决定你的投递策略如果允许转正式批可以早点投把提前批当试水如果不允许那就得准备得更充分再上。另外简历上一定要突出和SRE相关的项目。我在简历里写了一个监控系统开发和一次线上故障排查经历这两个项目在笔试后的面试环节几乎一定会被深挖。早点把这些项目的数据和细节准备好比临时抱佛脚刷题更有用。5.2 我自己踩过的坑多选题漏选和场景题没写完复盘的时候我给自己列了三宗罪。第一多选题太保守。多选题的评分规则通常是多选错选不得分少选得部分分所以很多人包括我在内都会因为怕错选而少选。但我发现有几道题我少选的是那种“SRE应该参与容量规划”“SRE需要关注错误预算”这类概念性选项属于送分题漏选纯粹是因为对SRE的职责范围理解不够自信。这块只能靠多读Google的SRE图书和多看稳定性相关的文章来补。第二编程题消耗了太多时间在优化上。第一道动态规划题我做完之后花了五分钟去纠结能不能用分治法写得更优雅实际上这五分钟完全可以留给场景题。场景题我只写了不到十个要点如果能写成一个有层次、有动作、有理由的完整流程分数会高很多。笔试中“完成”永远比“完美”重要。第三Shell题暴露了我“平时会用但手写不出来”的真实水平。平时在终端里awk和grep用得飞起但笔试要求你在空白的文本框里直接写一条完整命令时各种细节问题就来了字段顺序对不对、sort参数是-rn还是-nr、uniq -c之后为什么需要再sort一次。我的经验是考前一定要亲手在终端里敲几遍日志分析的常用命令组合不要只看不练。5.3 从笔试到面试的衔接把错题变成知识域的地图笔试结束之后我没有急着等消息而是花了大概半天时间把能回忆起来的题目全部整理了一遍按知识域归类Linux系统、网络协议、数据库、分布式理论、算法、SRE场景。然后针对每一个知识域列出自已的薄弱点比如我对TCP状态迁移的细节不够熟、对负载均衡的四层七层区别理解得不够深就找相关的文章和视频补了一遍。这个错题集在后续面试复习里帮了很大的忙。因为SRE面试的问题基本上都是从笔试考点延伸出去的。笔试考的是你是不是知道面试考的是你能不能讲清楚、能不能用在实际项目里。比如笔试里考了TIME_WAIT面试官可能就会问“你线上有没有遇到过端口耗尽的问题怎么解决的”。我还做了一件很有效的事在自己电脑上用Docker起了一个简单的Web服务然后人为制造故障来练排查——把服务连接数打到上限、让MySQL跑一条慢查询、用stress工具把CPU占满然后模拟一次完整的故障排查流程。这套自测做完之后我对场景题的信心提升了一大截因为很多问题只有真正亲手排过一遍才能形成条件反射式的思路。现在回头看2024年这场Shopee SRE提前批笔试与其说是一场考试不如说是一次对系统工程师综合能力的体检。它不考你背了多少命令也不考你刷了多少道题而是看你面对一个活生生的分布式系统时脑子里有没有一套清晰的排查框架手里有没有能落地的工具和代码能力。这种能力靠的是日常积累而不是考前突击。如果你也在准备SRE方向的秋招我建议你把复习重心放在两件事上一是把Linux、网络、数据库这些基本功打扎实二是亲手去做一次完整的线上故障排查。经历过一次真实的生产事故比刷十套笔试题都管用。