維開(kāi)發(fā)筆試:腳本/數(shù)據(jù)庫(kù)/緩存/排查/容器全解析)
1. 題目拆解與考察方向分析1.1 這份第二部分到底在考什么先說(shuō)個(gè)整體印象。金山辦公的校招筆試尤其是運(yùn)維開(kāi)發(fā)這個(gè)崗和單純背命令、背配置的傳統(tǒng)運(yùn)維筆試有本質(zhì)區(qū)別。它叫運(yùn)維開(kāi)發(fā)不是系統(tǒng)運(yùn)維不是網(wǎng)絡(luò)運(yùn)維這個(gè)名字本身就是在告訴你你的核心價(jià)值是用開(kāi)發(fā)能力解決運(yùn)維問(wèn)題。我在一線(xiàn)做運(yùn)維開(kāi)發(fā)也有些年頭了帶過(guò)不少新人也幫朋友公司出過(guò)類(lèi)似的筆試題。我的整體感受是這類(lèi)第二部分的筆試通常是在第一輪基礎(chǔ)考核Linux命令、網(wǎng)絡(luò)基礎(chǔ)、SQL這類(lèi)之上做一次篩選式進(jìn)階。什么意思呢就是它不再問(wèn)某條命令怎么用而是問(wèn)在什么場(chǎng)景下你會(huì)選擇哪條命令、為什么給你一個(gè)具體問(wèn)題你如何設(shè)計(jì)一套自動(dòng)化解決方案。前者考記憶后者考工程思維。所以如果你打算裸考或者以為把《鳥(niǎo)哥的Linux私房菜》翻一遍就夠那大概率會(huì)在第二部分翻車(chē)。真正能拉開(kāi)差距的是這幾類(lèi)題目腳本編程與邏輯設(shè)計(jì)、數(shù)據(jù)庫(kù)與緩存的實(shí)際應(yīng)用、故障排查與性能分析、CI/CD與容器化思路。后面我會(huì)逐個(gè)拆開(kāi)講。1.2 考察重點(diǎn)與崗位需求的對(duì)應(yīng)關(guān)系金山辦公的產(chǎn)品線(xiàn)很重WPS、云文檔、協(xié)同辦公這些業(yè)務(wù)對(duì)服務(wù)的穩(wěn)定性、API的響應(yīng)速度、數(shù)據(jù)的一致性都有很高要求。運(yùn)維開(kāi)發(fā)崗在這樣一家公司里日常要做的事包括但不限于維護(hù)大規(guī)模服務(wù)器的穩(wěn)定運(yùn)行、推動(dòng)發(fā)布流程自動(dòng)化、設(shè)計(jì)監(jiān)控告警體系、處理線(xiàn)上故障、優(yōu)化中間件性能。這就決定了筆試題目會(huì)往這些方向傾斜。我總結(jié)下來(lái)第二部分的題目的核心考察點(diǎn)大概有四塊第一腳本和編程能力。也就是你能否自動(dòng)化地處理文件批量操作、日志分析、文本抽取這種真實(shí)場(chǎng)景。第二數(shù)據(jù)庫(kù)和緩存設(shè)計(jì)。你的MySQL慢查詢(xún)優(yōu)化、Redis緩存策略是不是真的有實(shí)際經(jīng)驗(yàn)支撐而不是只背了八股文。第三系統(tǒng)排查和性能分析。給你一臺(tái)高負(fù)載服務(wù)器你如何定位瓶頸、怎么處理。第四運(yùn)維開(kāi)發(fā)工具鏈和CI/CD。你對(duì)Git、Jenkins、Docker、K8s這些工具的理解深度是否停留在用過(guò)層面。整份卷子的邏輯其實(shí)是先考你會(huì)不會(huì)寫(xiě)代碼解決問(wèn)題再考你懂不懂系統(tǒng)底層最后考你有沒(méi)有全局工程化思維。我把這套邏輯反過(guò)來(lái)從應(yīng)試者的角度拆解一下每類(lèi)題目的準(zhǔn)備方法。2. 腳本編程與自動(dòng)化處理筆試題的重頭戲2.1 Shell與Python的典型考題形式先說(shuō)Shell。凡是考運(yùn)維開(kāi)發(fā)Shell腳本幾乎是必出的而且一般不會(huì)直接問(wèn)你echo是什么意思而是給你一段殘缺的腳本讓你補(bǔ)全或者讓你實(shí)現(xiàn)一個(gè)具體的功能。比如統(tǒng)計(jì)Nginx訪(fǎng)問(wèn)日志中IP出現(xiàn)的次數(shù)并按次數(shù)降序排列。找出某個(gè)目錄下7天前修改過(guò)、大于100MB的日志文件并清理。檢查一組服務(wù)器的端口連通性異常時(shí)輸出報(bào)警信息。這些題目表面上看是在考命令實(shí)際上考的是你懂不懂真實(shí)運(yùn)維場(chǎng)景下的自動(dòng)巡檢思路。執(zhí)行順序、退出碼處理、定時(shí)任務(wù)怎么對(duì)接這些才是題目想看的。再一個(gè)高頻考點(diǎn)是Python。注意這里考的不是語(yǔ)法而是腳本的健壯性。比如讓你寫(xiě)一個(gè)腳本讀取一個(gè)CSV文件過(guò)濾出特定條件的數(shù)據(jù)再寫(xiě)入另一個(gè)文件。這時(shí)候考官在意的點(diǎn)包括你有沒(méi)有處理文件不存在的情況、有沒(méi)有考慮內(nèi)存占用用流式逐行讀而不是一次性readlines、有沒(méi)有處理異常并輸出日志。如果你只是寫(xiě)出能跑的代碼分?jǐn)?shù)可能不會(huì)太高。如果你能多寫(xiě)一個(gè)裝飾器記錄運(yùn)行耗時(shí)或者加上參數(shù)解析支持命令行傳參這就能明顯拉開(kāi)差距。我在實(shí)際工作中寫(xiě)自動(dòng)化腳本的習(xí)慣是能復(fù)用函數(shù)就復(fù)用不寫(xiě)一坨到底的面條代碼所有可能拋異常的地方一定要有捕獲和錯(cuò)誤日志腳本執(zhí)行結(jié)束后必須有明確的輸出提示。這些習(xí)慣可以直接遷移到筆試答題里。2.2 一種更高效的答題思路先設(shè)計(jì)再動(dòng)手很多同學(xué)看到編程題第一反應(yīng)是直接打開(kāi)編輯器想到哪寫(xiě)到哪。這個(gè)習(xí)慣在筆試?yán)锾貏e吃虧因?yàn)楣P試題給的空格有限閱卷人看的是你的邏輯不是你敲代碼的速度。我建議的答題順序是先在草稿紙上把輸入、處理、輸出三個(gè)環(huán)節(jié)列出來(lái)明確每一步可能出現(xiàn)的異常情況再動(dòng)筆寫(xiě)代碼。舉個(gè)例子如果題目要求讀取某個(gè)配置文件解析出所有keyvalue的鍵值對(duì)并檢查有沒(méi)有重復(fù)key你在動(dòng)手前就要想清楚配置文件格式是統(tǒng)一的keyvalue嗎有沒(méi)有可能包含注釋行或者空行重復(fù)key怎么處理是報(bào)錯(cuò)、忽略還是保留最后一個(gè)如果value本身含有符號(hào)呢比如urlhttp://a.com/bc這種情況split()以后要不要限制分割次數(shù)想清楚這三件事你寫(xiě)出來(lái)的代碼結(jié)構(gòu)是完全不同的。第一種寫(xiě)法可能是config_dict {} with open(config.ini) as f: for line in f: key, value line.strip().split() if key in config_dict: raise ValueError(fduplicate key: {key}) config_dict[key] value但如果你考慮到了value中可能含就會(huì)寫(xiě)成config_dict {} with open(config.ini) as f: for line in f: line line.strip() if not line or line.startswith(#): continue key, _, value line.partition() key key.strip() if not key: continue if key in config_dict: raise ValueError(fduplicate key: {key}) config_dict[key] value.strip()兩種寫(xiě)法高下立判。后者我一眼看過(guò)去就知道這人的生產(chǎn)環(huán)境經(jīng)驗(yàn)豐富因?yàn)槲覍?shí)際處理配置文件時(shí)就踩過(guò)value里藏著等號(hào)的坑。你答題時(shí)能讓閱卷人產(chǎn)生這種這人是同行的感覺(jué)分?jǐn)?shù)一定低不了。2.3 文本處理的常用命令組合Shell筆試?yán)镂谋咎幚砣齽蚲rep、sed、awk屬于必考內(nèi)容建議你不光會(huì)用還得會(huì)組合。這里分享幾個(gè)我從實(shí)際工作里總結(jié)出來(lái)的高頻組合公式從日志中統(tǒng)計(jì)某個(gè)關(guān)鍵詞的分布grep ERROR app.log | awk {print $1} | sort | uniq -c | sort -rn按時(shí)間范圍拉取日志片段sed -n /2020-06-01 10:00:00/,/2020-06-01 10:30:00/p app.log替換配置文件的某個(gè)字段要求整行匹配才替換sed -i /^max_connections/c\max_connections2000 /etc/mysql/my.cnf考試時(shí)大概率會(huì)出現(xiàn)類(lèi)似的組合場(chǎng)景建議你別只背單條命令要理解管道符串聯(lián)之后的每一步作用。面試的時(shí)候考官如果追問(wèn)中間這步輸出什么格式能準(zhǔn)確答上來(lái)的人不到三成。3. 數(shù)據(jù)庫(kù)與緩存從基礎(chǔ)語(yǔ)法到性能思維3.1 MySQL考點(diǎn)索引與慢查詢(xún)校招筆試考數(shù)據(jù)庫(kù)幾乎繞不開(kāi)MySQL。但我發(fā)現(xiàn)一個(gè)現(xiàn)象很多同學(xué)對(duì)SQL語(yǔ)法背得滾瓜爛熟什么left join、子查詢(xún)、group by都用得很溜但一遇到為什么這個(gè)查詢(xún)慢就答不上來(lái)。這說(shuō)明什么說(shuō)明他們?nèi)鄙傩阅芤暯?。針?duì)金山這類(lèi)互聯(lián)網(wǎng)辦公產(chǎn)品數(shù)據(jù)庫(kù)題目大概率會(huì)圍繞如何優(yōu)化一條慢SQL和如何設(shè)計(jì)表結(jié)構(gòu)支撐某業(yè)務(wù)場(chǎng)景來(lái)出。我強(qiáng)烈建議你在復(fù)習(xí)時(shí)每一道SQL題都追問(wèn)自己三個(gè)問(wèn)題這張表的字段長(zhǎng)度合理嗎有沒(méi)有為所有where條件里的字段建立索引這條查詢(xún)會(huì)不會(huì)產(chǎn)生全表掃描explain的結(jié)果是什么樣的如果數(shù)據(jù)量到100萬(wàn)、1000萬(wàn)級(jí)這條SQL還能扛住嗎能問(wèn)出這三個(gè)問(wèn)題說(shuō)明你是真的在生產(chǎn)環(huán)境里見(jiàn)過(guò)數(shù)據(jù)量級(jí)而不是只在本地練習(xí)庫(kù)里跑過(guò)幾千行數(shù)據(jù)。舉個(gè)典型的考題例子有一個(gè)訂單表orders字段包括order_id、user_id、status、created_at查詢(xún)某用戶(hù)最近10筆訂單的SQL請(qǐng)優(yōu)化。最差的答案就是直接select * from orders where user_id 123 order by created_at desc limit 10;因?yàn)楫?dāng)數(shù)據(jù)量大時(shí)MySQL需要先篩出該用戶(hù)所有訂單再排序。更好的思路是創(chuàng)建(user_id, created_at)的聯(lián)合索引讓索引直接按用戶(hù)和時(shí)間排序避免額外排序操作。加上索引之后這條SQL基本可以走索引覆蓋掃描性能提升往往是幾十倍級(jí)別。這不是憑空說(shuō)的是實(shí)際線(xiàn)上優(yōu)化過(guò)的經(jīng)驗(yàn)。3.2 Redis考點(diǎn)緩存穿透、擊穿與雪崩數(shù)據(jù)庫(kù)之外的第二個(gè)高頻考點(diǎn)就是Redis。字節(jié)也好、金山也好互聯(lián)網(wǎng)公司基本都重度依賴(lài)Redis做緩存。校招題里最常見(jiàn)的三種極端情況這里先給你說(shuō)清楚緩存穿透查詢(xún)一個(gè)根本不存在的數(shù)據(jù)Redis里沒(méi)有DB里也沒(méi)有惡意請(qǐng)求直接打到DB上。解法一般是布隆過(guò)濾器或者緩存空值并設(shè)置短過(guò)期時(shí)間。緩存擊穿某個(gè)熱點(diǎn)key在過(guò)期瞬間大量請(qǐng)求同時(shí)落到DB上。解法是互斥鎖重建緩存熱點(diǎn)數(shù)據(jù)邏輯上永不過(guò)期后臺(tái)異步續(xù)期。緩存雪崩大量key在同一時(shí)間段集中過(guò)期導(dǎo)致DB壓力驟增。解法是給過(guò)期時(shí)間加一個(gè)隨機(jī)值打散過(guò)期時(shí)間點(diǎn)。我不會(huì)只丟概念下面用一個(gè)題來(lái)演示答題思路。題目可能是某系統(tǒng)使用Redis緩存用戶(hù)信息key為user:{id}請(qǐng)?jiān)O(shè)計(jì)一個(gè)方案避免緩存雪崩。常規(guī)答法是過(guò)期時(shí)間設(shè)置為setex user:{id} 3600 value但3600秒就是固定值所有用戶(hù)同時(shí)過(guò)期。優(yōu)化方案是過(guò)期時(shí)間設(shè)置為3600 random.randint(0,300)這樣同一秒內(nèi)過(guò)期的key大幅減少。如果再進(jìn)一步可以引入多級(jí)緩存比如本地緩存一層Redis一層徹底兜底。筆試的考察深度通常到方案設(shè)計(jì)這個(gè)層級(jí)就夠了但如果你能多提一嘴熱點(diǎn)key的過(guò)期延時(shí)續(xù)期策略閱卷人印象會(huì)非常深。3.3 數(shù)據(jù)一致性場(chǎng)景題除了直接考語(yǔ)句和緩存策略第二部分還經(jīng)常給一個(gè)業(yè)務(wù)場(chǎng)景來(lái)考數(shù)據(jù)一致性。比如用戶(hù)修改頭像后需要展示新頭像但CDN/緩存里還是舊頭像你怎么處理這類(lèi)題的考察點(diǎn)很明確你有沒(méi)有真正思考過(guò)寫(xiě)更新和緩存失效之間的順序。我個(gè)人推薦的經(jīng)驗(yàn)公式是先更新數(shù)據(jù)庫(kù)再刪緩存。為什么不是先更新緩存因?yàn)椴l(fā)場(chǎng)景下先更新緩存再寫(xiě)庫(kù)一旦寫(xiě)庫(kù)失敗緩存里就是錯(cuò)誤數(shù)據(jù)。而先更新庫(kù)哪怕刪緩存失敗最多是下一次請(qǐng)求打回一個(gè)舊值再過(guò)一次過(guò)期時(shí)間就自愈了。這個(gè)順序問(wèn)題是我在真實(shí)項(xiàng)目中踩過(guò)坑后才徹底明白的。筆試時(shí)把這個(gè)順序邏輯寫(xiě)清楚比堆一堆術(shù)語(yǔ)要強(qiáng)得多。4. 網(wǎng)絡(luò)與系統(tǒng)排查思路比記參數(shù)更重要4.1 高頻網(wǎng)絡(luò)知識(shí)點(diǎn)TCP握手、HTTP狀態(tài)碼、DNS解析金山辦公的筆試中網(wǎng)絡(luò)部分的題目不會(huì)像網(wǎng)絡(luò)工程師那樣考報(bào)文級(jí)細(xì)節(jié)更多是考你能不能在應(yīng)用服務(wù)出問(wèn)題時(shí)順著網(wǎng)絡(luò)去排查鏈路。所以TCP三次握手過(guò)程、四次揮手為什么需要TIME_WAIT、HTTP的常見(jiàn)狀態(tài)碼含義200、301、302、403、404、500、502、503這些一定要滾瓜爛熟。另外我建議你重點(diǎn)準(zhǔn)備一下HTTP和HTTPS的區(qū)別以及Nginx反向代理的工作方式因?yàn)榻鹕竭@種產(chǎn)品線(xiàn)很重的公司線(xiàn)上一定大量使用Nginx做網(wǎng)關(guān)和負(fù)載均衡。常見(jiàn)的前置Nginx返回502的排查思路是先確認(rèn)后端服務(wù)是否存活再看Nginx連接后端的超時(shí)配置最后看后端進(jìn)程的連接數(shù)是否被打滿(mǎn)。這種排查鏈路如果能在筆試?yán)镉眠壿嬊逦奈淖謱?xiě)出來(lái)是很加分的。4.2 系統(tǒng)負(fù)載高你能不能在半小時(shí)內(nèi)定位問(wèn)題服務(wù)器CPU負(fù)載突然飆高你如何排查這幾乎是每年必出的場(chǎng)景題但能把整個(gè)過(guò)程答完整的人很少。我會(huì)用下面這套五步走來(lái)拆解一個(gè)典型的壓力場(chǎng)景也是我做線(xiàn)上問(wèn)題定位時(shí)的習(xí)慣第一先用uptime看Load Average的整體趨勢(shì)判斷負(fù)載是在漲還是已經(jīng)平穩(wěn)。如果Load持續(xù)高于CPU核心數(shù)說(shuō)明可能存在真正的資源爭(zhēng)搶而不是瞬時(shí)抖動(dòng)。第二用top進(jìn)入交互界面按CPU排序找到具體是哪個(gè)進(jìn)程占用了大量CPU。這一步最關(guān)鍵因?yàn)樨?fù)載高只是一個(gè)表象真正的問(wèn)題往往集中在某一個(gè)進(jìn)程。如果這個(gè)進(jìn)程是Java應(yīng)用接著用top -Hp 進(jìn)程號(hào)找到這個(gè)進(jìn)程內(nèi)部的哪些線(xiàn)程占用了CPU再用jstack導(dǎo)線(xiàn)程快照看這些線(xiàn)程在干什么。第三如果不是CPU密集型而是IO等待那么top里的wa指標(biāo)會(huì)明顯偏高此時(shí)需要用iostat看磁盤(pán)吞吐和IOPS看看是不是磁盤(pán)讀寫(xiě)的瓶頸。很多新人只盯著CPU忽略磁盤(pán)IO結(jié)果排查了半天方向全錯(cuò)。第四檢查內(nèi)存用free -h看還有多少可用內(nèi)存用vmstat看swap使用情況。如果你的應(yīng)用在持續(xù)swap那性能一定好不了這往往是內(nèi)存設(shè)置不合理導(dǎo)致的。第五結(jié)合上下文看看是不是流量突增、代碼死循環(huán)、緩存失效回源這三種典型因素。這套思路如果你是第一次接觸建議反復(fù)讀幾遍因?yàn)檫@就是一線(xiàn)運(yùn)維開(kāi)發(fā)工程師處理線(xiàn)上事故的底層邏輯筆試的時(shí)候把一個(gè)完整鏈路答下來(lái)絕對(duì)能讓閱卷老師覺(jué)得你不是紙上談兵。4.3 經(jīng)典的端口不通排查題再給你拆一道高頻基礎(chǔ)題用戶(hù)反饋某個(gè)服務(wù)訪(fǎng)問(wèn)不通你怎么排查這道題的經(jīng)典答題框架必須是從底層往上層一層層排除先確認(rèn)服務(wù)進(jìn)程有沒(méi)有在監(jiān)聽(tīng)對(duì)應(yīng)端口ss -lntp | grep 8080。再確認(rèn)本機(jī)防火墻是否放行端口iptables -L -n或firewall-cmd --list-all。然后在客戶(hù)端測(cè)試TCP連通性telnet 目標(biāo)IP 8080或nc -vz 目標(biāo)IP 8080。如果TCP通但HTTP不通用curl -v看完整請(qǐng)求輸出重點(diǎn)看返回的狀態(tài)碼和響應(yīng)頭。很多同學(xué)在這個(gè)題上第一反應(yīng)就是重啟服務(wù)或者看日志實(shí)際上第一件該做的事是確認(rèn)到底是客戶(hù)端連不上還是服務(wù)端沒(méi)響應(yīng)。把鏈路拆開(kāi)才能定位到具體某一層出了問(wèn)題。做題和干活是一樣的先確認(rèn)故障邊界再深入排查。筆試時(shí)把這個(gè)邏輯寫(xiě)得越清晰得分就越高。5. 容器化與CI/CD從工具使用到鏈路思維5.1 Docker的基礎(chǔ)題鏡像與容器的生命周期金山辦公2020年前后的業(yè)務(wù)容器化已經(jīng)是常態(tài)所以考Docker基礎(chǔ)毫不意外。這里有個(gè)核心概念題你務(wù)必搞清楚鏡像和容器的區(qū)別。鏡像是一個(gè)只讀的模板容器是鏡像運(yùn)行時(shí)的實(shí)例。你可以把平時(shí)docker run、docker build、docker commit、docker exec這些命令都答上來(lái)但我不建議只背命令更重要的是理解容器本質(zhì)上是進(jìn)程級(jí)別的隔離這個(gè)理念。筆試在Docker這塊的常見(jiàn)問(wèn)法有Dockerfile中CMD和ENTRYPOINT的區(qū)別是什么如何減小Docker鏡像體積如何讓容器里的服務(wù)優(yōu)雅退出以最后一個(gè)問(wèn)題為例優(yōu)雅退出的核心是讓主進(jìn)程能夠接收到SIGTERM信號(hào)并完成清理而不是被直接kill。很多同學(xué)壓根不知道Docker stop發(fā)的是SIGTERM而不是SIGKILL也不清楚Java應(yīng)用要配合trap或者Spring Boot的Graceful Shutdown特性才能實(shí)現(xiàn)優(yōu)雅下線(xiàn)。這些細(xì)節(jié)如果能在筆試?yán)飳?xiě)出來(lái)可以證明你真用容器跑過(guò)生產(chǎn)服務(wù)而不僅僅是在本地docker run -it過(guò)。5.2 CI/CD流程設(shè)計(jì)題不只是一個(gè)概念題既然崗位叫運(yùn)維開(kāi)發(fā)CI/CD相關(guān)的問(wèn)題一定會(huì)占一部分比重。我覺(jué)得這部分最常考的題型是設(shè)計(jì)題比如請(qǐng)?jiān)O(shè)計(jì)一條從代碼提交到生產(chǎn)環(huán)境發(fā)布的流水線(xiàn)。很多同學(xué)第一反應(yīng)是把GitLab CI、Jenkins、Docker、K8s這些名詞懟上去但我要告訴你的是面試官想看到的不是工具清單而是階段劃分。一條合格的流水線(xiàn)至少包含以下幾個(gè)階段代碼提交觸發(fā)構(gòu)建階段進(jìn)行編譯和單元測(cè)試。構(gòu)建成功后產(chǎn)出制品鏡像或JAR包推送到制品庫(kù)。部署到測(cè)試環(huán)境跑自動(dòng)化接口測(cè)試。審核通過(guò)后部署到預(yù)發(fā)環(huán)境進(jìn)行冒煙驗(yàn)證。最后灰度發(fā)布到生產(chǎn)環(huán)境觀察監(jiān)控指標(biāo)逐步放量。如果筆試題目要求你畫(huà)流程圖或用語(yǔ)言描述流程建議你按上面的層次結(jié)構(gòu)來(lái)答每一步說(shuō)清楚輸入是什么、輸出是什么、誰(shuí)觸發(fā)、出現(xiàn)問(wèn)題怎么回滾。能把這四個(gè)維度講清楚你的工程化思維就已經(jīng)超過(guò)大多數(shù)人。5.3 K8s重點(diǎn)Pod、Deployment、Service的關(guān)系近些年校招筆試題對(duì)Kubernetes的考察越來(lái)越頻繁考的倒不深但會(huì)涉及最核心的抽象模型。舉個(gè)例子Pod和Deployment的區(qū)別是什么Service怎么實(shí)現(xiàn)負(fù)載均衡。很多同學(xué)答Pod是最小調(diào)度單元Deployment是管理副本的控制器這話(huà)沒(méi)錯(cuò)但太干了。我提供一個(gè)更貼合實(shí)操的答法Deployment負(fù)責(zé)聲明我要多少個(gè)Pod副本保持運(yùn)行并且當(dāng)Pod掛了的時(shí)候自動(dòng)拉起新的如果業(yè)務(wù)需要升級(jí)版本Deployment會(huì)按照RollingUpdate策略逐個(gè)替換Pod避免服務(wù)中斷。而Service則是給一組Pod提供一個(gè)穩(wěn)定的訪(fǎng)問(wèn)入口實(shí)現(xiàn)負(fù)載均衡和服務(wù)發(fā)現(xiàn)。答題的時(shí)候能把升級(jí)策略副本管理服務(wù)暴露這幾個(gè)行為層面的內(nèi)容帶出來(lái)比單純默寫(xiě)概念好得多。6. 實(shí)戰(zhàn)題型演練把思路落到實(shí)處6.1 場(chǎng)景題一日志關(guān)鍵詞監(jiān)控報(bào)警這種題我強(qiáng)烈建議你認(rèn)真過(guò)一遍因?yàn)樗湫土藥缀趺總€(gè)運(yùn)維開(kāi)發(fā)崗位面試都會(huì)碰到。題目描述通常是線(xiàn)上有多個(gè)應(yīng)用實(shí)例需要監(jiān)控日志中出現(xiàn)OutOfMemory關(guān)鍵詞的實(shí)例并發(fā)送報(bào)警你會(huì)怎么實(shí)現(xiàn)一個(gè)完整的方案分為數(shù)據(jù)采集、實(shí)時(shí)處理、告警通知三個(gè)部分。采集端可以用Filebeat或Logstash采集應(yīng)用日志發(fā)到Kafka實(shí)時(shí)處理端可以用Flink或者Go的grok庫(kù)做關(guān)鍵詞匹配也可以簡(jiǎn)單用Logstash的filter直接過(guò)濾告警端命中關(guān)鍵詞后通過(guò)Webhook調(diào)用企業(yè)微信、釘釘或短信網(wǎng)關(guān)。這樣一套鏈路下來(lái)比寫(xiě)個(gè)腳本crontab每分鐘grep日志要健壯得多不會(huì)漏報(bào)也能做到秒級(jí)響應(yīng)。如果筆試只讓你用一個(gè)腳本一個(gè)定時(shí)任務(wù)這種輕量方案來(lái)解決也不能說(shuō)錯(cuò)但你要意識(shí)到它的缺陷單點(diǎn)問(wèn)題、日志輪轉(zhuǎn)時(shí)的漏讀、多實(shí)例部署困難。答完輕量方案之后如果能主動(dòng)補(bǔ)一句這個(gè)方案適合臨時(shí)應(yīng)急長(zhǎng)期用我會(huì)考慮引入采集鏈路這樣的作答層次會(huì)更飽滿(mǎn)。6.2 場(chǎng)景題二線(xiàn)上發(fā)布后性能下降還有一類(lèi)高頻場(chǎng)景題新版本發(fā)布后線(xiàn)上調(diào)用響應(yīng)時(shí)間明顯變長(zhǎng)你怎么排查我的第一反應(yīng)永遠(yuǎn)不是回滾而是先確認(rèn)影響范圍和變更內(nèi)容。因?yàn)榛貪L是一種高成本操作且如果是代碼問(wèn)題回滾后可能要重新排查所以除非線(xiàn)上已經(jīng)不可用否則一般建議先定位。第二步是看監(jiān)控曲線(xiàn)。發(fā)布前后對(duì)比CPU、內(nèi)存、QPS、RT、GC情況如果GC次數(shù)和耗時(shí)明顯上升那可能是新代碼中創(chuàng)建了大量對(duì)象或者某個(gè)緩存設(shè)置有問(wèn)題如果QPS沒(méi)變但RT變大那重點(diǎn)檢查有沒(méi)有慢調(diào)用、鎖競(jìng)爭(zhēng)、數(shù)據(jù)庫(kù)連接池是否被打滿(mǎn)。第三步是看日志特別是error日志和慢日志。如果某個(gè)接口的耗時(shí)從200ms變成800ms用tracing工具定位到調(diào)用鏈中具體哪一環(huán)耗時(shí)最長(zhǎng)。如果是外部依賴(lài)數(shù)據(jù)庫(kù)、第三方接口變慢那就是下游問(wèn)題如果是自身代碼邏輯導(dǎo)致那就直接看對(duì)應(yīng)代碼段的性能。排查思路比具體命令重要。答出先看監(jiān)控、再分模塊定位、最后看代碼這個(gè)三層遞進(jìn)邏輯基本就穩(wěn)了。6.3 場(chǎng)景題三如何保障系統(tǒng)高可用這個(gè)問(wèn)題范圍很大經(jīng)常作為筆試最后一道論述題或設(shè)計(jì)題出現(xiàn)。考察面廣但沒(méi)有標(biāo)準(zhǔn)答案關(guān)鍵在于你能否覆蓋到多個(gè)層面。我習(xí)慣從入口層、應(yīng)用層、數(shù)據(jù)層、基礎(chǔ)設(shè)施層四個(gè)角度來(lái)答。入口層DNS解析可以配置多線(xiàn)路Nginx做多節(jié)點(diǎn)負(fù)載均衡避免單點(diǎn)入口。應(yīng)用層服務(wù)部署多副本放到不同機(jī)架/可用區(qū)自動(dòng)故障轉(zhuǎn)移無(wú)狀態(tài)服務(wù)用負(fù)載均衡重新分發(fā)流量。數(shù)據(jù)層數(shù)據(jù)庫(kù)做主從復(fù)制Redis用主從加哨兵或者集群定時(shí)備份和日志備份形成災(zāi)備體系。基礎(chǔ)設(shè)施層網(wǎng)絡(luò)、電源、存儲(chǔ)都考慮冗余監(jiān)控系統(tǒng)全維度覆蓋出現(xiàn)異常時(shí)能做自動(dòng)化預(yù)案。這類(lèi)論述題的加分項(xiàng)是成本意識(shí)。如果能在方案里提到核心鏈路重點(diǎn)保障非核心業(yè)務(wù)降級(jí)處理這種策略性設(shè)計(jì)比單純堆一堆高可用組件要高級(jí)得多。因?yàn)槲易龅南到y(tǒng)都知道把三個(gè)9還是五個(gè)9成本不是線(xiàn)性上漲而是指數(shù)級(jí)上漲。能夠結(jié)合業(yè)務(wù)實(shí)際去設(shè)計(jì)高可用方案才是面試官最想看到的能力。7. 備考與答題的獨(dú)家實(shí)操心得7.1 筆試題的常見(jiàn)扣分點(diǎn)早知道早避坑我說(shuō)幾個(gè)閱卷時(shí)最常見(jiàn)的扣分點(diǎn)希望對(duì)你有幫助。第一題目要求寫(xiě)出完整命令或?qū)懗瞿_本結(jié)果只寫(xiě)了核心命令沒(méi)寫(xiě)流程控制。比如讓寫(xiě)一個(gè)腳本檢查多個(gè)服務(wù)的端口是否存活很多人就寫(xiě)nc -zv 127.0.0.1 80不寫(xiě)循環(huán)、不寫(xiě)判斷、不寫(xiě)輸出日志。這在填空題里能得分但在實(shí)現(xiàn)題里只能拿一半分。第二答案里沒(méi)有體現(xiàn)防御性編程。舉個(gè)例子一個(gè)腳本里用了臨時(shí)文件正常運(yùn)行沒(méi)問(wèn)題但如果上次異常退出后臨時(shí)文件沒(méi)有清理再次運(yùn)行就會(huì)報(bào)錯(cuò)。有經(jīng)驗(yàn)的人在腳本開(kāi)頭會(huì)加一句trap rm -f /tmp/xxx.$$ EXIT來(lái)保證退出時(shí)清理。這種細(xì)節(jié)寫(xiě)出來(lái)就是強(qiáng)烈的生產(chǎn)經(jīng)驗(yàn)信號(hào)。第三只寫(xiě)做了什么不寫(xiě)為什么這么做。比如答Redis緩存更新方案只說(shuō)更新數(shù)據(jù)庫(kù)后刪除緩存沒(méi)說(shuō)為什么這個(gè)順序更安全分?jǐn)?shù)就差一截。我建議答題時(shí)養(yǎng)成習(xí)慣結(jié)論理由例外。結(jié)論是一句話(huà)理由是把關(guān)鍵邏輯講清楚例外是說(shuō)明什么場(chǎng)景下方案不適用。7.2 短期內(nèi)高效備考的方向建議如果距離筆試只剩一到兩周我建議你把精力集中在以下三個(gè)板塊這是性?xún)r(jià)比最高的突擊路徑一是Shell文本處理和Python腳本題這是最高頻的考法占分比最大而且短期刷題效果最明顯。把常見(jiàn)場(chǎng)景題做一遍形成肌肉記憶。二是MySQL和Redis的重點(diǎn)應(yīng)用集中看索引優(yōu)化、explain的使用、緩存三類(lèi)問(wèn)題穿透、擊穿、雪崩的解法務(wù)必能用文字理通邏輯。三是網(wǎng)絡(luò)和系統(tǒng)排查題重點(diǎn)是TCP握手、HTTP狀態(tài)碼、CPU高負(fù)載排查用先定位再處理的思路來(lái)答題拒絕只堆名詞。至于Docker、K8s、CI/CD這些內(nèi)容如果在筆試中出現(xiàn)大概率是基礎(chǔ)概念加簡(jiǎn)單的設(shè)計(jì)題時(shí)間不夠的話(huà)可以先把Dockerfile核心指令、Pod/Deployment/Service區(qū)別、流水線(xiàn)階段劃分這三大塊吃透。7.3 一些我的個(gè)人經(jīng)驗(yàn)總結(jié)我做了這些年運(yùn)維開(kāi)發(fā)最深的感受是這個(gè)崗位筆試不是終點(diǎn)準(zhǔn)確說(shuō)筆試只是一個(gè)篩選信號(hào)。真正決定你能否通過(guò)后面面試的是你對(duì)為什么的理解程度。公司培養(yǎng)一個(gè)運(yùn)維開(kāi)發(fā)新人的成本并不低他們希望招到的是遇到問(wèn)題不慌、能自己找到答案的人。所以備考筆試的時(shí)候不妨多地假如我是這個(gè)系統(tǒng)的運(yùn)維負(fù)責(zé)人我會(huì)怎么做來(lái)思考問(wèn)題。你在草稿紙上反復(fù)推敲過(guò)的每一個(gè)極端場(chǎng)景最后都會(huì)變成你面試時(shí)的底氣。還有一個(gè)小建議。筆試時(shí)如果遇到完全沒(méi)見(jiàn)過(guò)的題千萬(wàn)不要空著不寫(xiě)。你可以先把題目中你已經(jīng)知道的知識(shí)點(diǎn)列出來(lái)再?lài)L試給出一個(gè)你認(rèn)為合理的方案哪怕不完整也能讓閱卷人看到你分析問(wèn)題的方向是對(duì)的。我在實(shí)際業(yè)務(wù)里遇到未知問(wèn)題也是這個(gè)策略先把已知邊界確認(rèn)掉再把問(wèn)題從大化小一層層拆最后總能找一個(gè)可以落地的解法。這套思路本身其實(shí)比任何標(biāo)準(zhǔn)答案都更能代表運(yùn)維開(kāi)發(fā)工程師的核心能力。